Full Code of chaitin/PandaWiki for AI

main 46edaa879b75 cached
1181 files
6.3 MB
1.7M tokens
3392 symbols
1 requests
Download .txt
Showing preview only (6,881K chars total). Download the full file or copy to clipboard to get everything.
Repository: chaitin/PandaWiki
Branch: main
Commit: 46edaa879b75
Files: 1181
Total size: 6.3 MB

Directory structure:
gitextract_zj65fk7g/

├── .gitattributes
├── .github/
│   ├── ISSUE_TEMPLATE/
│   │   ├── 功能建议.md
│   │   └── 故障报告.md
│   ├── PULL_REQUEST_TEMPLATE.md
│   └── workflows/
│       ├── backend.yml
│       ├── backend_check.yml
│       └── web.yml
├── .gitignore
├── .gitmodules
├── CODE_OF_CONDUCT.md
├── CONTRIBUTING.md
├── LICENSE
├── PROJECT_STRUCTURE.md
├── README.md
├── SECURITY.md
├── backend/
│   ├── .dockerignore
│   ├── .golangci.toml
│   ├── Dockerfile.api
│   ├── Dockerfile.api.pro
│   ├── Dockerfile.consumer
│   ├── Dockerfile.consumer.pro
│   ├── Makefile
│   ├── api/
│   │   ├── auth/
│   │   │   └── v1/
│   │   │       └── auth.go
│   │   ├── conversation/
│   │   │   └── v1/
│   │   │       └── conversation.go
│   │   ├── crawler/
│   │   │   └── v1/
│   │   │       ├── confluence.go
│   │   │       ├── crawler.go
│   │   │       ├── epub.go
│   │   │       ├── feishu.go
│   │   │       ├── mindoc.go
│   │   │       ├── notion.go
│   │   │       ├── siyuan.go
│   │   │       ├── wikijs.go
│   │   │       └── yuque.go
│   │   ├── kb/
│   │   │   └── v1/
│   │   │       └── kb.go
│   │   ├── nav/
│   │   │   └── v1/
│   │   │       └── nav.go
│   │   ├── node/
│   │   │   └── v1/
│   │   │       └── node.go
│   │   ├── openapi/
│   │   │   └── v1/
│   │   │       └── openapi.go
│   │   ├── share/
│   │   │   └── v1/
│   │   │       ├── auth.go
│   │   │       ├── common.go
│   │   │       ├── nav.go
│   │   │       ├── node.go
│   │   │       └── wechat.go
│   │   ├── stat/
│   │   │   └── v1/
│   │   │       └── stat.go
│   │   └── user/
│   │       └── v1/
│   │           └── user.go
│   ├── apm/
│   │   ├── provider.go
│   │   └── trace.go
│   ├── cSpell.json
│   ├── cmd/
│   │   ├── api/
│   │   │   ├── main.go
│   │   │   ├── wire.go
│   │   │   └── wire_gen.go
│   │   ├── consumer/
│   │   │   ├── main.go
│   │   │   ├── wire.go
│   │   │   └── wire_gen.go
│   │   └── migrate/
│   │       ├── main.go
│   │       ├── wire.go
│   │       └── wire_gen.go
│   ├── config/
│   │   ├── config.go
│   │   └── provider.go
│   ├── consts/
│   │   ├── admin.go
│   │   ├── app.go
│   │   ├── auth.go
│   │   ├── captcha.go
│   │   ├── consts.go
│   │   ├── contribute.go
│   │   ├── crawler.go
│   │   ├── license.go
│   │   ├── model.go
│   │   ├── node.go
│   │   ├── parse.go
│   │   └── system_setting.go
│   ├── docs/
│   │   ├── docs.go
│   │   ├── swagger.json
│   │   └── swagger.yaml
│   ├── domain/
│   │   ├── api_token.go
│   │   ├── app.go
│   │   ├── auth.go
│   │   ├── chat.go
│   │   ├── comment.go
│   │   ├── contribute.go
│   │   ├── conversation.go
│   │   ├── creation.go
│   │   ├── epub.go
│   │   ├── errors.go
│   │   ├── file.go
│   │   ├── icon.go
│   │   ├── ip.go
│   │   ├── json.go
│   │   ├── knowledge_base.go
│   │   ├── license.go
│   │   ├── llm.go
│   │   ├── model.go
│   │   ├── mq.go
│   │   ├── nav.go
│   │   ├── node.go
│   │   ├── notion.go
│   │   ├── openai.go
│   │   ├── openai_test.go
│   │   ├── pager.go
│   │   ├── prompt.go
│   │   ├── response.go
│   │   ├── setting.go
│   │   ├── siyuan.go
│   │   ├── sse_event.go
│   │   ├── stat.go
│   │   ├── system_setting.go
│   │   ├── user.go
│   │   ├── userfeedback.go
│   │   └── wechat.go
│   ├── go.mod
│   ├── go.sum
│   ├── handler/
│   │   ├── base.go
│   │   ├── mq/
│   │   │   ├── cron.go
│   │   │   ├── provider.go
│   │   │   ├── rag.go
│   │   │   └── rag_doc_update.go
│   │   ├── share/
│   │   │   ├── app.go
│   │   │   ├── auth.go
│   │   │   ├── captcha.go
│   │   │   ├── chat.go
│   │   │   ├── comment.go
│   │   │   ├── common.go
│   │   │   ├── coversation.go
│   │   │   ├── nav.go
│   │   │   ├── node.go
│   │   │   ├── openapi.go
│   │   │   ├── provider.go
│   │   │   ├── sitemap.go
│   │   │   ├── stat.go
│   │   │   └── wechat.go
│   │   └── v1/
│   │       ├── app.go
│   │       ├── auth.go
│   │       ├── comment.go
│   │       ├── conversation.go
│   │       ├── crawler.go
│   │       ├── creation.go
│   │       ├── file.go
│   │       ├── kb_user.go
│   │       ├── knowledge_base.go
│   │       ├── model.go
│   │       ├── nav.go
│   │       ├── node.go
│   │       ├── provider.go
│   │       ├── stat.go
│   │       └── user.go
│   ├── log/
│   │   ├── log.go
│   │   └── provider.go
│   ├── middleware/
│   │   ├── api_token.go
│   │   ├── auth.go
│   │   ├── jwt.go
│   │   ├── provider.go
│   │   ├── readonly.go
│   │   ├── session.go
│   │   └── share_auth.go
│   ├── migration/
│   │   ├── fns/
│   │   │   ├── 0001_migrate_node_version.go
│   │   │   ├── 0002_create_bot_auth.go
│   │   │   ├── 0003_fix_group_ids.go
│   │   │   ├── 0004_update_node_status_unreleased.go
│   │   │   ├── 0005_create_first_nav_tabs.go
│   │   │   └── provider.go
│   │   ├── func.go
│   │   ├── manager.go
│   │   └── provider.go
│   ├── mq/
│   │   ├── mq.go
│   │   ├── nats/
│   │   │   ├── consumer.go
│   │   │   ├── message.go
│   │   │   └── producer.go
│   │   └── types/
│   │       └── message.go
│   ├── pkg/
│   │   ├── anydoc/
│   │   │   ├── anydoc.go
│   │   │   ├── confluence.go
│   │   │   ├── dingtalk.go
│   │   │   ├── epub.go
│   │   │   ├── feishu.go
│   │   │   ├── mindoc.go
│   │   │   ├── notion.go
│   │   │   ├── req.go
│   │   │   ├── res.go
│   │   │   ├── rss.go
│   │   │   ├── sitemap.go
│   │   │   ├── siyuan.go
│   │   │   ├── wikijs.go
│   │   │   └── yuque.go
│   │   ├── bot/
│   │   │   ├── common.go
│   │   │   ├── dingtalk/
│   │   │   │   └── stream.go
│   │   │   ├── discord/
│   │   │   │   ├── discord_test.go
│   │   │   │   └── stream.go
│   │   │   ├── feishu/
│   │   │   │   └── stream.go
│   │   │   ├── lark/
│   │   │   │   └── client.go
│   │   │   ├── utils/
│   │   │   │   └── utils.go
│   │   │   ├── wechat/
│   │   │   │   ├── domain.go
│   │   │   │   └── wechat.go
│   │   │   ├── wechat_official_account/
│   │   │   │   └── official_account.go
│   │   │   ├── wechat_service/
│   │   │   │   ├── domain.go
│   │   │   │   ├── tools.go
│   │   │   │   └── wechat.go
│   │   │   └── wecom/
│   │   │       ├── ai_bot.go
│   │   │       └── crypt.go
│   │   ├── captcha/
│   │   │   └── captcha.go
│   │   ├── cas/
│   │   │   └── cas.go
│   │   ├── dingtalk/
│   │   │   └── dingtalk.go
│   │   ├── feishu/
│   │   │   └── feishu.go
│   │   ├── ldap/
│   │   │   └── ldap.go
│   │   ├── oauth/
│   │   │   ├── github.go
│   │   │   └── oauth.go
│   │   ├── ratelimit/
│   │   │   └── rate_limiter.go
│   │   └── wecom/
│   │       └── wecom.go
│   ├── pro_imports.go
│   ├── project-words.txt
│   ├── repo/
│   │   ├── cache/
│   │   │   ├── geo.go
│   │   │   ├── kb.go
│   │   │   └── provider.go
│   │   ├── ipdb/
│   │   │   ├── ip_addr.go
│   │   │   └── provider.go
│   │   ├── mq/
│   │   │   ├── provider.go
│   │   │   └── rag.go
│   │   └── pg/
│   │       ├── ap_token.go
│   │       ├── app.go
│   │       ├── auth.go
│   │       ├── block_word.go
│   │       ├── comment.go
│   │       ├── conversation.go
│   │       ├── knowledge_base.go
│   │       ├── mcp.go
│   │       ├── model.go
│   │       ├── nav.go
│   │       ├── node.go
│   │       ├── node_group.go
│   │       ├── node_stats.go
│   │       ├── prompt.go
│   │       ├── provider.go
│   │       ├── stat.go
│   │       ├── stat_hour.go
│   │       ├── system_setting.go
│   │       ├── user.go
│   │       ├── user_access.go
│   │       └── wechat.go
│   ├── server/
│   │   └── http/
│   │       ├── http.go
│   │       └── provider.go
│   ├── setup/
│   │   └── cert.go
│   ├── store/
│   │   ├── cache/
│   │   │   ├── provider.go
│   │   │   └── redis.go
│   │   ├── ipdb/
│   │   │   ├── ip2region.xdb
│   │   │   └── ipdb.go
│   │   ├── pg/
│   │   │   ├── migration/
│   │   │   │   ├── 000001_init.down.sql
│   │   │   │   ├── 000001_init.up.sql
│   │   │   │   ├── 000002_add_type_for_model.down.sql
│   │   │   │   ├── 000002_add_type_for_model.up.sql
│   │   │   │   ├── 000003_update_rerank_type.down.sql
│   │   │   │   ├── 000003_update_rerank_type.up.sql
│   │   │   │   ├── 000004_kb_dataset_id.down.sql
│   │   │   │   ├── 000004_kb_dataset_id.up.sql
│   │   │   │   ├── 000005_app_kb_id_type_uniq.down.sql
│   │   │   │   ├── 000005_app_kb_id_type_uniq.up.sql
│   │   │   │   ├── 000006_node_version.down.sql
│   │   │   │   ├── 000006_node_version.up.sql
│   │   │   │   ├── 000007_node_release_updated_at.down.sql
│   │   │   │   ├── 000007_node_release_updated_at.up.sql
│   │   │   │   ├── 000008_add_conversation_info.down.sql
│   │   │   │   ├── 000008_add_conversation_info.up.sql
│   │   │   │   ├── 000009_create_stat_pages.down.sql
│   │   │   │   ├── 000009_create_stat_pages.up.sql
│   │   │   │   ├── 000010_add_conversation_message_feedback.down.sql
│   │   │   │   ├── 000010_add_conversation_message_feedback.up.sql
│   │   │   │   ├── 000011_create_user_comment.down.sql
│   │   │   │   ├── 000011_create_user_comment.up.sql
│   │   │   │   ├── 000012_add_conversation_message_kb_id_parent_id.down.sql
│   │   │   │   ├── 000012_add_conversation_message_kb_id_parent_id.up.sql
│   │   │   │   ├── 000013_create_license.down.sql
│   │   │   │   ├── 000013_create_license.up.sql
│   │   │   │   ├── 000014_add_user_comment_status.down.sql
│   │   │   │   ├── 000014_add_user_comment_status.up.sql
│   │   │   │   ├── 000015_create_auth.down.sql
│   │   │   │   ├── 000015_create_auth.up.sql
│   │   │   │   ├── 000016_create_document_feedback.down.sql
│   │   │   │   ├── 000016_create_document_feedback.up.sql
│   │   │   │   ├── 000017_update_comversation_message_feedback.down.sql
│   │   │   │   ├── 000017_updtate_conversation_message_feedback.up.sql
│   │   │   │   ├── 000018_create_settings.down.sql
│   │   │   │   ├── 000018_create_settings.up.sql
│   │   │   │   ├── 000019_alter_stat_pages_type.down.sql
│   │   │   │   ├── 000019_alter_stat_pages_type.up.sql
│   │   │   │   ├── 000020_add_user_role_and_kb_users.down.sql
│   │   │   │   ├── 000020_add_user_role_and_kb_users.up.sql
│   │   │   │   ├── 000021_create_auth_groups.down.sql
│   │   │   │   ├── 000021_create_auth_groups.up.sql
│   │   │   │   ├── 000022_alter_model.down.sql
│   │   │   │   ├── 000022_alter_model.up.sql
│   │   │   │   ├── 000023_create_stat_page_hours.down.sql
│   │   │   │   ├── 000023_create_stat_page_hours.up.sql
│   │   │   │   ├── 000024_add_parent_id_to_auth_groups.down.sql
│   │   │   │   ├── 000024_add_parent_id_to_auth_groups.up.sql
│   │   │   │   ├── 000025_create_api_tokens_table.down.sql
│   │   │   │   ├── 000025_create_api_tokens_table.up.sql
│   │   │   │   ├── 000026_add_sync.down.sql
│   │   │   │   ├── 000026_add_sync.up.sql
│   │   │   │   ├── 000027_create_contributes_table.down.sql
│   │   │   │   ├── 000027_create_contributes_table.up.sql
│   │   │   │   ├── 000028_add_contributes_ip.down.sql
│   │   │   │   ├── 000028_add_contributes_ip.up.sql
│   │   │   │   ├── 000029_add_comment_pic_urls.down.sql
│   │   │   │   ├── 000029_add_comment_pic_urls.up.sql
│   │   │   │   ├── 000030_add_node_status_msg.down.sql
│   │   │   │   ├── 000030_add_node_status_msg.up.sql
│   │   │   │   ├── 000031_add_node_release_user_id.down.sql
│   │   │   │   ├── 000031_add_node_release_user_id.up.sql
│   │   │   │   ├── 000032_create_system_settings.down.sql
│   │   │   │   ├── 000032_create_system_settings.up.sql
│   │   │   │   ├── 000033_create_mcp_calls.down.sql
│   │   │   │   ├── 000033_create_mcp_calls.up.sql
│   │   │   │   ├── 000034_create_node_stats.down.sql
│   │   │   │   ├── 000034_create_node_stats.up.sql
│   │   │   │   ├── 000035_add_conversation_image_paths.down.sql
│   │   │   │   ├── 000035_add_conversation_image_paths.up.sql
│   │   │   │   ├── 000036_add_kb_release_publisher_id.down.sql
│   │   │   │   ├── 000036_add_kb_release_publisher_id.up.sql
│   │   │   │   ├── 000037_create_nav_tabs.down.sql
│   │   │   │   ├── 000037_create_nav_tabs.up.sql
│   │   │   │   ├── 000038_create_node_release_backups.down.sql
│   │   │   │   └── 000038_create_node_release_backups.up.sql
│   │   │   ├── pg.go
│   │   │   └── provider.go
│   │   ├── rag/
│   │   │   ├── ct.go
│   │   │   ├── html2md.go
│   │   │   └── rag.go
│   │   └── s3/
│   │       ├── minio.go
│   │       └── provider.go
│   ├── telemetry/
│   │   ├── aes.go
│   │   ├── client.go
│   │   ├── provider.go
│   │   └── version.go
│   ├── usecase/
│   │   ├── app.go
│   │   ├── auth.go
│   │   ├── auth_github.go
│   │   ├── chat.go
│   │   ├── comment.go
│   │   ├── conversation.go
│   │   ├── crawler.go
│   │   ├── creation.go
│   │   ├── dingtalk_bot.go
│   │   ├── file.go
│   │   ├── knowledge_base.go
│   │   ├── llm.go
│   │   ├── model.go
│   │   ├── nav.go
│   │   ├── node.go
│   │   ├── provider.go
│   │   ├── sitemap.go
│   │   ├── stat.go
│   │   ├── user.go
│   │   ├── wechat_app.go
│   │   ├── wechat_official_account.go
│   │   ├── wechat_service.go
│   │   └── wecom.go
│   └── utils/
│       ├── DFA.go
│       ├── epub.go
│       ├── feed.go
│       ├── file.go
│       ├── ip_addr.go
│       ├── processor.go
│       ├── time.go
│       └── utils.go
├── sdk/
│   └── rag/
│       ├── chunk.go
│       ├── client.go
│       ├── dataset.go
│       ├── document.go
│       ├── go.mod
│       ├── model_config.go
│       ├── models.go
│       └── retrieval.go
└── web/
    ├── .gitignore
    ├── .husky/
    │   └── pre-commit
    ├── .prettierignore
    ├── admin/
    │   ├── .dockerignore
    │   ├── .gitignore
    │   ├── .prettierignore
    │   ├── Dockerfile
    │   ├── Makefile
    │   ├── README.md
    │   ├── api-templates/
    │   │   ├── api.ejs
    │   │   ├── http-client.ejs
    │   │   └── procedure-call.ejs
    │   ├── eslint.config.js
    │   ├── index.html
    │   ├── nginx.conf
    │   ├── package.json
    │   ├── prettier.config.js
    │   ├── public/
    │   │   ├── echarts/
    │   │   │   └── china.js
    │   │   ├── geo/
    │   │   │   ├── geo.js
    │   │   │   └── world.json
    │   │   ├── panda-wiki.css
    │   │   ├── panda-wiki.js
    │   │   └── world.json
    │   ├── scripts/
    │   │   └── generate-routes.js
    │   ├── server.conf
    │   ├── src/
    │   │   ├── App.tsx
    │   │   ├── api/
    │   │   │   ├── index.tsx
    │   │   │   ├── request.ts
    │   │   │   └── type.ts
    │   │   ├── assets/
    │   │   │   ├── emoji-data/
    │   │   │   │   └── zh.json
    │   │   │   ├── fonts/
    │   │   │   │   ├── font.css
    │   │   │   │   ├── gilroy-bold.otf
    │   │   │   │   ├── gilroy-medium.otf
    │   │   │   │   └── gilroy-regular.otf
    │   │   │   ├── json/
    │   │   │   │   ├── coin.json
    │   │   │   │   ├── error.json
    │   │   │   │   ├── help-center.json
    │   │   │   │   ├── takeoff.json
    │   │   │   │   └── upgrade.json
    │   │   │   └── styles/
    │   │   │       ├── index.css
    │   │   │       └── markdown.css
    │   │   ├── components/
    │   │   │   ├── Avatar/
    │   │   │   │   └── index.tsx
    │   │   │   ├── BarTrend/
    │   │   │   │   └── index.tsx
    │   │   │   ├── Card/
    │   │   │   │   └── index.tsx
    │   │   │   ├── Cascader/
    │   │   │   │   └── index.tsx
    │   │   │   ├── CreateWikiModal/
    │   │   │   │   ├── index.tsx
    │   │   │   │   └── steps/
    │   │   │   │       ├── Step1Model.tsx
    │   │   │   │       ├── Step2Config.tsx
    │   │   │   │       ├── Step3Import.tsx
    │   │   │   │       ├── Step4Publish.tsx
    │   │   │   │       ├── Step5Test.tsx
    │   │   │   │       ├── Step6Decorate.tsx
    │   │   │   │       ├── Step7Complete.tsx
    │   │   │   │       ├── index.ts
    │   │   │   │       └── initData.ts
    │   │   │   ├── CustomImage/
    │   │   │   │   └── index.tsx
    │   │   │   ├── CustomModal/
    │   │   │   │   ├── components/
    │   │   │   │   │   ├── ShowContent.tsx
    │   │   │   │   │   ├── basicComponents/
    │   │   │   │   │   │   ├── DragBrand/
    │   │   │   │   │   │   │   ├── Item.tsx
    │   │   │   │   │   │   │   ├── SortableItem.tsx
    │   │   │   │   │   │   │   └── index.tsx
    │   │   │   │   │   │   ├── DragBtn/
    │   │   │   │   │   │   │   ├── Item.tsx
    │   │   │   │   │   │   │   ├── SortableItem.tsx
    │   │   │   │   │   │   │   └── index.tsx
    │   │   │   │   │   │   ├── DragSocialInfo/
    │   │   │   │   │   │   │   ├── Item.tsx
    │   │   │   │   │   │   │   ├── SortableItem.tsx
    │   │   │   │   │   │   │   └── index.tsx
    │   │   │   │   │   │   └── Switch.tsx
    │   │   │   │   │   ├── components/
    │   │   │   │   │   │   ├── ColorPickerField.tsx
    │   │   │   │   │   │   ├── ComponentBar.tsx
    │   │   │   │   │   │   ├── DragList.tsx
    │   │   │   │   │   │   ├── SortableItem.tsx
    │   │   │   │   │   │   ├── StyledCommon.tsx
    │   │   │   │   │   │   └── index.ts
    │   │   │   │   │   └── config/
    │   │   │   │   │       ├── BannerConfig/
    │   │   │   │   │       │   ├── HotSearchItem.tsx
    │   │   │   │   │       │   ├── Item.tsx
    │   │   │   │   │       │   └── index.tsx
    │   │   │   │   │       ├── BasicDocConfig/
    │   │   │   │   │       │   ├── Item.tsx
    │   │   │   │   │       │   └── index.tsx
    │   │   │   │   │       ├── BlockGridConfig/
    │   │   │   │   │       │   ├── Item.tsx
    │   │   │   │   │       │   └── index.tsx
    │   │   │   │   │       ├── CarouselConfig/
    │   │   │   │   │       │   ├── Item.tsx
    │   │   │   │   │       │   └── index.tsx
    │   │   │   │   │       ├── CaseConfig/
    │   │   │   │   │       │   ├── Item.tsx
    │   │   │   │   │       │   └── index.tsx
    │   │   │   │   │       ├── CommentConfig/
    │   │   │   │   │       │   ├── Item.tsx
    │   │   │   │   │       │   └── index.tsx
    │   │   │   │   │       ├── ConfigBar.tsx
    │   │   │   │   │       ├── DirDocConfig/
    │   │   │   │   │       │   ├── Item.tsx
    │   │   │   │   │       │   └── index.tsx
    │   │   │   │   │       ├── FaqConfig/
    │   │   │   │   │       │   ├── Item.tsx
    │   │   │   │   │       │   └── index.tsx
    │   │   │   │   │       ├── FeatureConfig/
    │   │   │   │   │       │   ├── Item.tsx
    │   │   │   │   │       │   └── index.tsx
    │   │   │   │   │       ├── FooterConfig.tsx
    │   │   │   │   │       ├── HeaderConfig.tsx
    │   │   │   │   │       ├── ImgTextConfig/
    │   │   │   │   │       │   └── index.tsx
    │   │   │   │   │       ├── MetricsConfig/
    │   │   │   │   │       │   ├── Item.tsx
    │   │   │   │   │       │   └── index.tsx
    │   │   │   │   │       ├── QuestionConfig/
    │   │   │   │   │       │   ├── Item.tsx
    │   │   │   │   │       │   └── index.tsx
    │   │   │   │   │       ├── SimpleDocConfig/
    │   │   │   │   │       │   ├── Item.tsx
    │   │   │   │   │       │   └── index.tsx
    │   │   │   │   │       ├── TextConfig/
    │   │   │   │   │       │   └── index.tsx
    │   │   │   │   │       └── type.ts
    │   │   │   │   ├── constants.tsx
    │   │   │   │   ├── index.tsx
    │   │   │   │   └── utils.ts
    │   │   │   ├── Drag/
    │   │   │   │   ├── DragRecommend/
    │   │   │   │   │   ├── Item.tsx
    │   │   │   │   │   ├── SortableItem.tsx
    │   │   │   │   │   └── index.tsx
    │   │   │   │   └── DragTree/
    │   │   │   │       ├── TreeItem.tsx
    │   │   │   │       ├── TreeMenu.tsx
    │   │   │   │       └── index.tsx
    │   │   │   ├── Emoji/
    │   │   │   │   └── index.tsx
    │   │   │   ├── EmptyState/
    │   │   │   │   └── index.tsx
    │   │   │   ├── Form/
    │   │   │   │   └── index.tsx
    │   │   │   ├── FreeSoloAutocomplete/
    │   │   │   │   └── index.tsx
    │   │   │   ├── Header/
    │   │   │   │   ├── Bread.tsx
    │   │   │   │   └── index.tsx
    │   │   │   ├── KB/
    │   │   │   │   ├── KBCreate.tsx
    │   │   │   │   ├── KBDelete.tsx
    │   │   │   │   ├── KBModify.tsx
    │   │   │   │   └── KBSelect.tsx
    │   │   │   ├── Loading/
    │   │   │   │   └── index.tsx
    │   │   │   ├── LottieIcon/
    │   │   │   │   └── index.tsx
    │   │   │   ├── MapChart/
    │   │   │   │   └── index.tsx
    │   │   │   ├── MarkDown/
    │   │   │   │   └── index.tsx
    │   │   │   ├── PieTrend/
    │   │   │   │   └── index.tsx
    │   │   │   ├── ShowText/
    │   │   │   │   └── index.tsx
    │   │   │   ├── Sidebar/
    │   │   │   │   ├── AuthTypeModal.tsx
    │   │   │   │   ├── Version.tsx
    │   │   │   │   └── index.tsx
    │   │   │   ├── Switch/
    │   │   │   │   └── index.tsx
    │   │   │   ├── System/
    │   │   │   │   ├── component/
    │   │   │   │   │   ├── AutoModelConfig.tsx
    │   │   │   │   │   ├── Member.tsx
    │   │   │   │   │   ├── MemberAdd.tsx
    │   │   │   │   │   ├── MemberDelete.tsx
    │   │   │   │   │   ├── MemberUpdate.tsx
    │   │   │   │   │   └── ModelConfig.tsx
    │   │   │   │   └── index.tsx
    │   │   │   ├── TreeDragSortable/
    │   │   │   │   ├── SortableTree.tsx
    │   │   │   │   ├── SortableTreeItem.tsx
    │   │   │   │   ├── SortingStrategy.ts
    │   │   │   │   ├── TreeItemWrapper.tsx
    │   │   │   │   ├── index.css
    │   │   │   │   ├── index.tsx
    │   │   │   │   ├── types.ts
    │   │   │   │   └── utilities.ts
    │   │   │   ├── UploadFile/
    │   │   │   │   ├── Drag.tsx
    │   │   │   │   ├── FileText.tsx
    │   │   │   │   └── index.tsx
    │   │   │   └── VersionMask/
    │   │   │       └── index.tsx
    │   │   ├── constant/
    │   │   │   ├── area.ts
    │   │   │   ├── enums.tsx
    │   │   │   ├── rag.ts
    │   │   │   ├── styles.ts
    │   │   │   └── version.ts
    │   │   ├── hooks/
    │   │   │   ├── index.tsx
    │   │   │   ├── useBindCaptcha.ts
    │   │   │   ├── useCommitPendingInput.tsx
    │   │   │   ├── useDebounceAppPreviewData.tsx
    │   │   │   ├── useURLSearchParams.tsx
    │   │   │   └── useVersionFeature.ts
    │   │   ├── layouts/
    │   │   │   └── index.tsx
    │   │   ├── main.tsx
    │   │   ├── pages/
    │   │   │   ├── 401/
    │   │   │   │   └── index.tsx
    │   │   │   ├── contribution/
    │   │   │   │   ├── ContributePreviewModal.tsx
    │   │   │   │   ├── DocModal.tsx
    │   │   │   │   ├── MarkdownPreviewModal.tsx
    │   │   │   │   └── index.tsx
    │   │   │   ├── conversation/
    │   │   │   │   ├── Detail.tsx
    │   │   │   │   ├── Search.tsx
    │   │   │   │   └── index.tsx
    │   │   │   ├── document/
    │   │   │   │   ├── component/
    │   │   │   │   │   ├── AddDocBtn.tsx
    │   │   │   │   │   ├── AddDocByType/
    │   │   │   │   │   │   ├── FileParse/
    │   │   │   │   │   │   │   └── index.tsx
    │   │   │   │   │   │   ├── FormSubmit/
    │   │   │   │   │   │   │   ├── FormInput.tsx
    │   │   │   │   │   │   │   └── index.tsx
    │   │   │   │   │   │   ├── ListRender/
    │   │   │   │   │   │   │   ├── Action.tsx
    │   │   │   │   │   │   │   ├── Item.tsx
    │   │   │   │   │   │   │   └── index.tsx
    │   │   │   │   │   │   ├── components/
    │   │   │   │   │   │   │   ├── StatusBackground.tsx
    │   │   │   │   │   │   │   └── StatusBadge.tsx
    │   │   │   │   │   │   ├── constants.ts
    │   │   │   │   │   │   ├── hooks/
    │   │   │   │   │   │   │   └── useGlobalQueue.ts
    │   │   │   │   │   │   ├── index.tsx
    │   │   │   │   │   │   └── util.ts
    │   │   │   │   │   ├── DocAddByCustomText.tsx
    │   │   │   │   │   ├── DocDelete.tsx
    │   │   │   │   │   ├── DocPropertiesModal.tsx
    │   │   │   │   │   ├── DocStatus.tsx
    │   │   │   │   │   ├── DocSummary.tsx
    │   │   │   │   │   ├── EditorCollaboration.tsx
    │   │   │   │   │   ├── MoveDocs.tsx
    │   │   │   │   │   ├── RagErrorReStart.tsx
    │   │   │   │   │   ├── Summary.tsx
    │   │   │   │   │   └── VersionRollback.tsx
    │   │   │   │   ├── editor/
    │   │   │   │   │   ├── Catalog/
    │   │   │   │   │   │   ├── KBSwitch.tsx
    │   │   │   │   │   │   └── index.tsx
    │   │   │   │   │   ├── edit/
    │   │   │   │   │   │   ├── AIGenerate.tsx
    │   │   │   │   │   │   ├── FullTextEditor.tsx
    │   │   │   │   │   │   ├── Header.tsx
    │   │   │   │   │   │   ├── Loading.tsx
    │   │   │   │   │   │   ├── Summary.tsx
    │   │   │   │   │   │   ├── Toc.tsx
    │   │   │   │   │   │   ├── Toolbar.tsx
    │   │   │   │   │   │   ├── Wrap.tsx
    │   │   │   │   │   │   └── index.tsx
    │   │   │   │   │   ├── history/
    │   │   │   │   │   │   └── index.tsx
    │   │   │   │   │   ├── index.tsx
    │   │   │   │   │   └── space/
    │   │   │   │   │       └── index.tsx
    │   │   │   │   └── layout/
    │   │   │   │       ├── DocPageHeader/
    │   │   │   │       │   ├── DocSearch.tsx
    │   │   │   │       │   └── index.tsx
    │   │   │   │       ├── DocPageList/
    │   │   │   │       │   ├── DocListModals.tsx
    │   │   │   │       │   ├── DocPageListContainer.tsx
    │   │   │   │       │   ├── DocPageListContent.tsx
    │   │   │   │       │   ├── index.tsx
    │   │   │   │       │   ├── types.ts
    │   │   │   │       │   ├── useDocTreeMenu.tsx
    │   │   │   │       │   └── utils.ts
    │   │   │   │       ├── DocPageNavs/
    │   │   │   │       │   ├── NavEditModal.tsx
    │   │   │   │       │   └── index.tsx
    │   │   │   │       └── index.tsx
    │   │   │   ├── feedback/
    │   │   │   │   ├── Comments.tsx
    │   │   │   │   ├── Detail.tsx
    │   │   │   │   ├── Evaluate.tsx
    │   │   │   │   └── index.tsx
    │   │   │   ├── login/
    │   │   │   │   └── index.tsx
    │   │   │   ├── release/
    │   │   │   │   ├── components/
    │   │   │   │   │   ├── VersionDelete.tsx
    │   │   │   │   │   ├── VersionPublish.tsx
    │   │   │   │   │   └── VersionReset.tsx
    │   │   │   │   └── index.tsx
    │   │   │   ├── setting/
    │   │   │   │   ├── component/
    │   │   │   │   │   ├── AddRecommendContent.tsx
    │   │   │   │   │   ├── AddRole.tsx
    │   │   │   │   │   ├── CardAI.tsx
    │   │   │   │   │   ├── CardAuth.tsx
    │   │   │   │   │   ├── CardBasicInfo.tsx
    │   │   │   │   │   ├── CardCatalog.tsx
    │   │   │   │   │   ├── CardCustom.tsx
    │   │   │   │   │   ├── CardFeedback.tsx
    │   │   │   │   │   ├── CardKB.tsx
    │   │   │   │   │   ├── CardListen.tsx
    │   │   │   │   │   ├── CardMCP.tsx
    │   │   │   │   │   ├── CardProxy.tsx
    │   │   │   │   │   ├── CardQaCopyright.tsx
    │   │   │   │   │   ├── CardRobot/
    │   │   │   │   │   │   └── WebComponent/
    │   │   │   │   │   │       ├── RecommendDocDragList.tsx
    │   │   │   │   │   │       └── index.tsx
    │   │   │   │   │   ├── CardRobot.tsx
    │   │   │   │   │   ├── CardRobotApi.tsx
    │   │   │   │   │   ├── CardRobotDing.tsx
    │   │   │   │   │   ├── CardRobotDiscord.tsx
    │   │   │   │   │   ├── CardRobotFeishu.tsx
    │   │   │   │   │   ├── CardRobotLark.tsx
    │   │   │   │   │   ├── CardRobotWechatOfficeAccount.tsx
    │   │   │   │   │   ├── CardRobotWecom.tsx
    │   │   │   │   │   ├── CardRobotWecomAIBot.tsx
    │   │   │   │   │   ├── CardRobotWecomService.tsx
    │   │   │   │   │   ├── CardSecurity.tsx
    │   │   │   │   │   ├── CardStyle.tsx
    │   │   │   │   │   ├── CardWeb.tsx
    │   │   │   │   │   ├── CardWebCustomCode.tsx
    │   │   │   │   │   ├── CardWebSEO.tsx
    │   │   │   │   │   ├── CardWebStats.tsx
    │   │   │   │   │   ├── Common.tsx
    │   │   │   │   │   ├── ConfigKB.tsx
    │   │   │   │   │   ├── UserGroup/
    │   │   │   │   │   │   ├── GroupTree.tsx
    │   │   │   │   │   │   └── index.tsx
    │   │   │   │   │   └── UserGroupModal.tsx
    │   │   │   │   └── index.tsx
    │   │   │   └── stat/
    │   │   │       ├── Statistic/
    │   │   │       │   ├── AreaMap.tsx
    │   │   │       │   ├── ClientStat.tsx
    │   │   │       │   ├── HostReferer.tsx
    │   │   │       │   ├── HotDocs.tsx
    │   │   │       │   ├── QAReferer.tsx
    │   │   │       │   ├── RTVisitor.tsx
    │   │   │       │   ├── TypeCount.tsx
    │   │   │       │   └── index.tsx
    │   │   │       └── index.tsx
    │   │   ├── request/
    │   │   │   ├── App.ts
    │   │   │   ├── Auth.ts
    │   │   │   ├── Comment.ts
    │   │   │   ├── Conversation.ts
    │   │   │   ├── Crawler.ts
    │   │   │   ├── Creation.ts
    │   │   │   ├── File.ts
    │   │   │   ├── KnowledgeBase.ts
    │   │   │   ├── Message.ts
    │   │   │   ├── Model.ts
    │   │   │   ├── Nav.ts
    │   │   │   ├── Node.ts
    │   │   │   ├── NodePermission.ts
    │   │   │   ├── Stat.ts
    │   │   │   ├── User.ts
    │   │   │   ├── httpClient.ts
    │   │   │   ├── index.ts
    │   │   │   ├── pro/
    │   │   │   │   ├── ApiToken.ts
    │   │   │   │   ├── Auth.ts
    │   │   │   │   ├── AuthGroup.ts
    │   │   │   │   ├── AuthOrg.ts
    │   │   │   │   ├── Block.ts
    │   │   │   │   ├── Comment.ts
    │   │   │   │   ├── Contribute.ts
    │   │   │   │   ├── DocumentFeedback.ts
    │   │   │   │   ├── License.ts
    │   │   │   │   ├── Node.ts
    │   │   │   │   ├── Prompt.ts
    │   │   │   │   ├── ShareAuth.ts
    │   │   │   │   ├── ShareContribute.ts
    │   │   │   │   ├── ShareFile.ts
    │   │   │   │   ├── ShareOpenapi.ts
    │   │   │   │   ├── httpClient.ts
    │   │   │   │   ├── index.ts
    │   │   │   │   └── types.ts
    │   │   │   └── types.ts
    │   │   ├── router.tsx
    │   │   ├── services/
    │   │   │   └── modelService.ts
    │   │   ├── store/
    │   │   │   ├── index.ts
    │   │   │   └── slices/
    │   │   │       ├── breadcrumb.ts
    │   │   │       └── config.ts
    │   │   ├── themes/
    │   │   │   ├── dark.ts
    │   │   │   ├── index.ts
    │   │   │   └── light.ts
    │   │   ├── utils/
    │   │   │   ├── drag.ts
    │   │   │   ├── fetch.ts
    │   │   │   ├── getBasePath.ts
    │   │   │   ├── getBasename.ts
    │   │   │   ├── index.ts
    │   │   │   ├── loadScript.ts
    │   │   │   ├── render.ts
    │   │   │   └── tree.ts
    │   │   └── vite-env.d.ts
    │   ├── ssl/
    │   │   ├── panda-wiki.crt
    │   │   └── panda-wiki.key
    │   ├── swagger.api.config.ts
    │   ├── tsconfig.app.json
    │   ├── tsconfig.json
    │   ├── tsconfig.node.json
    │   └── vite.config.ts
    ├── app/
    │   ├── .gitignore
    │   ├── .prettierignore
    │   ├── Dockerfile
    │   ├── Makefile
    │   ├── README.md
    │   ├── api-templates/
    │   │   ├── api.ejs
    │   │   ├── http-client.ejs
    │   │   └── procedure-call.ejs
    │   ├── eslint.config.mjs
    │   ├── new-types.d.ts
    │   ├── next.config.ts
    │   ├── package.json
    │   ├── prettier.config.js
    │   ├── public/
    │   │   ├── cap@0.0.6/
    │   │   │   └── cap_wasm_bg.wasm
    │   │   ├── widget-bot.css
    │   │   └── widget-bot.js
    │   ├── sentry.edge.config.ts
    │   ├── sentry.server.config.ts
    │   ├── src/
    │   │   ├── app/
    │   │   │   ├── (pages)/
    │   │   │   │   ├── (doc)/
    │   │   │   │   │   ├── editor/
    │   │   │   │   │   │   └── [[...id]]/
    │   │   │   │   │   │       └── page.tsx
    │   │   │   │   │   ├── home/
    │   │   │   │   │   │   └── page.tsx
    │   │   │   │   │   ├── layout.tsx
    │   │   │   │   │   ├── node/
    │   │   │   │   │   │   ├── NodeClientLayout.tsx
    │   │   │   │   │   │   ├── [id]/
    │   │   │   │   │   │   │   └── page.tsx
    │   │   │   │   │   │   ├── error.tsx
    │   │   │   │   │   │   ├── layout.tsx
    │   │   │   │   │   │   └── page.tsx
    │   │   │   │   │   └── welcome/
    │   │   │   │   │       └── page.tsx
    │   │   │   │   ├── auth/
    │   │   │   │   │   └── login/
    │   │   │   │   │       └── page.tsx
    │   │   │   │   ├── layout.tsx
    │   │   │   │   └── not-found.tsx
    │   │   │   ├── error.tsx
    │   │   │   ├── feedback/
    │   │   │   │   ├── layout.tsx
    │   │   │   │   └── page.tsx
    │   │   │   ├── global-error.tsx
    │   │   │   ├── globals.css
    │   │   │   ├── h5-chat/
    │   │   │   │   └── page.tsx
    │   │   │   ├── layout.tsx
    │   │   │   ├── markdown.css
    │   │   │   ├── not-found.tsx
    │   │   │   └── widget/
    │   │   │       ├── layout.tsx
    │   │   │       └── page.tsx
    │   │   ├── assets/
    │   │   │   ├── fonts/
    │   │   │   │   ├── gilroy-bold-700.otf
    │   │   │   │   ├── gilroy-light-300.otf
    │   │   │   │   ├── gilroy-medium-500.otf
    │   │   │   │   └── gilroy-regular-400.otf
    │   │   │   └── type/
    │   │   │       └── index.ts
    │   │   ├── components/
    │   │   │   ├── QaModal/
    │   │   │   │   ├── AiQaContent.tsx
    │   │   │   │   ├── SearchDocContent.tsx
    │   │   │   │   ├── StyledComponents.tsx
    │   │   │   │   ├── constants.ts
    │   │   │   │   ├── index.tsx
    │   │   │   │   ├── types.ts
    │   │   │   │   └── utils.ts
    │   │   │   ├── commentInput/
    │   │   │   │   └── index.tsx
    │   │   │   ├── docFab/
    │   │   │   │   └── index.tsx
    │   │   │   ├── docSkeleton/
    │   │   │   │   └── index.tsx
    │   │   │   ├── emoji/
    │   │   │   │   ├── emoji-data/
    │   │   │   │   │   └── zh.json
    │   │   │   │   └── index.tsx
    │   │   │   ├── emptyDocPlaceholder/
    │   │   │   │   └── index.tsx
    │   │   │   ├── error/
    │   │   │   │   └── index.tsx
    │   │   │   ├── feedback/
    │   │   │   │   └── index.tsx
    │   │   │   ├── footer/
    │   │   │   │   ├── Overlay.tsx
    │   │   │   │   └── index.tsx
    │   │   │   ├── header/
    │   │   │   │   ├── index.tsx
    │   │   │   │   └── themeSwitch.tsx
    │   │   │   ├── icons/
    │   │   │   │   └── index.tsx
    │   │   │   ├── markdown/
    │   │   │   │   ├── index.tsx
    │   │   │   │   └── mermaid.tsx
    │   │   │   ├── markdown2/
    │   │   │   │   ├── imageRenderer.tsx
    │   │   │   │   ├── incrementalRenderer.tsx
    │   │   │   │   ├── index.tsx
    │   │   │   │   ├── mermaidRenderer.tsx
    │   │   │   │   └── thinkingRenderer.tsx
    │   │   │   ├── menuSelect/
    │   │   │   │   └── index.tsx
    │   │   │   ├── scrollToTopFab/
    │   │   │   │   └── index.tsx
    │   │   │   └── watermark/
    │   │   │       ├── WaterMarkProvider.tsx
    │   │   │       └── index.tsx
    │   │   ├── constant/
    │   │   │   └── index.ts
    │   │   ├── hooks/
    │   │   │   ├── index.ts
    │   │   │   ├── useBasePath.ts
    │   │   │   ├── useCopy.tsx
    │   │   │   ├── useScroll.ts
    │   │   │   ├── useSmartScroll.ts
    │   │   │   └── useSyncNavByDocId.ts
    │   │   ├── instrumentation-client.ts
    │   │   ├── instrumentation.ts
    │   │   ├── provider/
    │   │   │   ├── index.tsx
    │   │   │   └── themeStore.tsx
    │   │   ├── proxy.ts
    │   │   ├── request/
    │   │   │   ├── ShareApp.ts
    │   │   │   ├── ShareAuth.ts
    │   │   │   ├── ShareCaptcha.ts
    │   │   │   ├── ShareChat.ts
    │   │   │   ├── ShareChatSearch.ts
    │   │   │   ├── ShareComment.ts
    │   │   │   ├── ShareConversation.ts
    │   │   │   ├── ShareFile.ts
    │   │   │   ├── ShareNav.ts
    │   │   │   ├── ShareNode.ts
    │   │   │   ├── ShareOpenapi.ts
    │   │   │   ├── ShareStat.ts
    │   │   │   ├── Wechat.ts
    │   │   │   ├── Widget.ts
    │   │   │   ├── httpClient.ts
    │   │   │   ├── index.ts
    │   │   │   ├── pro/
    │   │   │   │   ├── ApiToken.ts
    │   │   │   │   ├── Auth.ts
    │   │   │   │   ├── AuthGroup.ts
    │   │   │   │   ├── AuthOrg.ts
    │   │   │   │   ├── Block.ts
    │   │   │   │   ├── Comment.ts
    │   │   │   │   ├── Contribute.ts
    │   │   │   │   ├── DocumentFeedback.ts
    │   │   │   │   ├── License.ts
    │   │   │   │   ├── Node.ts
    │   │   │   │   ├── Prompt.ts
    │   │   │   │   ├── ShareAuth.ts
    │   │   │   │   ├── ShareContribute.ts
    │   │   │   │   ├── ShareFile.ts
    │   │   │   │   ├── ShareOpenapi.ts
    │   │   │   │   ├── httpClient.ts
    │   │   │   │   ├── index.ts
    │   │   │   │   ├── otherCustomer.ts
    │   │   │   │   └── types.ts
    │   │   │   └── types.ts
    │   │   ├── theme.ts
    │   │   ├── utils/
    │   │   │   ├── cookie.ts
    │   │   │   ├── fetch.ts
    │   │   │   ├── getBasePath.ts
    │   │   │   ├── getDocContentSx.ts
    │   │   │   ├── getImagePath.ts
    │   │   │   ├── getServerHeader.ts
    │   │   │   ├── index.ts
    │   │   │   └── tree.ts
    │   │   └── views/
    │   │       ├── auth/
    │   │       │   └── login.tsx
    │   │       ├── chat/
    │   │       │   ├── ChatLoading.tsx
    │   │       │   └── constant.ts
    │   │       ├── editor/
    │   │       │   ├── edit/
    │   │       │   │   ├── AIGenerate.tsx
    │   │       │   │   ├── ConfirmModal.tsx
    │   │       │   │   ├── Header.tsx
    │   │       │   │   ├── Loading.tsx
    │   │       │   │   ├── Summary.tsx
    │   │       │   │   ├── Toc.tsx
    │   │       │   │   ├── Toolbar.tsx
    │   │       │   │   ├── Wrap.tsx
    │   │       │   │   ├── constant.ts
    │   │       │   │   └── index.tsx
    │   │       │   └── index.tsx
    │   │       ├── feedback/
    │   │       │   └── index.tsx
    │   │       ├── h5Chat/
    │   │       │   └── index.tsx
    │   │       ├── home/
    │   │       │   └── index.tsx
    │   │       ├── node/
    │   │       │   ├── Catalog.tsx
    │   │       │   ├── CatalogFolder.tsx
    │   │       │   ├── CatalogH5.tsx
    │   │       │   ├── DocAnchor.tsx
    │   │       │   ├── DocContent.tsx
    │   │       │   ├── NavBar.tsx
    │   │       │   ├── NoPermission.tsx
    │   │       │   ├── components/
    │   │       │   │   ├── AdjacentDocNav.tsx
    │   │       │   │   ├── CommentSection.tsx
    │   │       │   │   └── DocMetaInfo.tsx
    │   │       │   ├── folderList.tsx
    │   │       │   └── index.tsx
    │   │       └── widget/
    │   │           ├── AiQaContent.tsx
    │   │           ├── SearchDocContent.tsx
    │   │           ├── StyledComponents.tsx
    │   │           ├── constants.ts
    │   │           ├── index.tsx
    │   │           ├── types.ts
    │   │           └── utils.ts
    │   ├── swagger.api.config.ts
    │   └── tsconfig.json
    ├── package.json
    ├── packages/
    │   ├── icons/
    │   │   ├── package.json
    │   │   ├── scripts/
    │   │   │   └── generate.ts
    │   │   ├── src/
    │   │   │   ├── Icon123.tsx
    │   │   │   ├── IconA302ai.tsx
    │   │   │   ├── IconAAIshezhi.tsx
    │   │   │   ├── IconACaidan.tsx
    │   │   │   ├── IconAChilunshezhisheding.tsx
    │   │   │   ├── IconADiancaiWeixuanzhong2.tsx
    │   │   │   ├── IconADiscordjiqiren.tsx
    │   │   │   ├── IconAIcon_huaban1fuben22.tsx
    │   │   │   ├── IconAKuaizhao2.tsx
    │   │   │   ├── IconALianjie5.tsx
    │   │   │   ├── IconAShijian2.tsx
    │   │   │   ├── IconAWebyingyong.tsx
    │   │   │   ├── IconAWenhao8.tsx
    │   │   │   ├── IconAZiyuan2.tsx
    │   │   │   ├── IconAdd.tsx
    │   │   │   ├── IconAihubmix.tsx
    │   │   │   ├── IconAiyingyong1.tsx
    │   │   │   ├── IconAlayanew.tsx
    │   │   │   ├── IconAliyunbailian.tsx
    │   │   │   ├── IconAnthropic.tsx
    │   │   │   ├── IconAwsBedrock.tsx
    │   │   │   ├── IconAzure.tsx
    │   │   │   ├── IconBaichuan.tsx
    │   │   │   ├── IconBaiduyun.tsx
    │   │   │   ├── IconBaizhiyunlogo.tsx
    │   │   │   ├── IconBanben.tsx
    │   │   │   ├── IconBanben1.tsx
    │   │   │   ├── IconBangzhuwendang1.tsx
    │   │   │   ├── IconBaocun.tsx
    │   │   │   ├── IconBiaoge1.tsx
    │   │   │   ├── IconBukejian.tsx
    │   │   │   ├── IconBurncloud.tsx
    │   │   │   ├── IconBytedance.tsx
    │   │   │   ├── IconC183jianjumidu.tsx
    │   │   │   ├── IconCaiMoren.tsx
    │   │   │   ├── IconCaiXuanzhong.tsx
    │   │   │   ├── IconCephalon.tsx
    │   │   │   ├── IconChahao.tsx
    │   │   │   ├── IconChahao1.tsx
    │   │   │   ├── IconChakan.tsx
    │   │   │   ├── IconChangjianwenti.tsx
    │   │   │   ├── IconChatgpt.tsx
    │   │   │   ├── IconChilun.tsx
    │   │   │   ├── IconChuangjian.tsx
    │   │   │   ├── IconCohere.tsx
    │   │   │   ├── IconCorrection.tsx
    │   │   │   ├── IconDJzhinengzhaiyao.tsx
    │   │   │   ├── IconDMXAPI.tsx
    │   │   │   ├── IconDandulogo.tsx
    │   │   │   ├── IconDanliao.tsx
    │   │   │   ├── IconDanliao1.tsx
    │   │   │   ├── IconDanwenzi.tsx
    │   │   │   ├── IconDaochu.tsx
    │   │   │   ├── IconDashScope.tsx
    │   │   │   ├── IconDeepseek.tsx
    │   │   │   ├── IconDengchu.tsx
    │   │   │   ├── IconDiancaiWeixuanzhong.tsx
    │   │   │   ├── IconDianhua.tsx
    │   │   │   ├── IconDianhua1.tsx
    │   │   │   ├── IconDianzanMoren.tsx
    │   │   │   ├── IconDianzanWeixuanzhong.tsx
    │   │   │   ├── IconDianzanXuanzhong.tsx
    │   │   │   ├── IconDianzanXuanzhong1.tsx
    │   │   │   ├── IconDingdingdingd.tsx
    │   │   │   ├── IconDingdingjiqiren.tsx
    │   │   │   ├── IconDingzi.tsx
    │   │   │   ├── IconDitu_diqiu.tsx
    │   │   │   ├── IconDoubao.tsx
    │   │   │   ├── IconDouyin.tsx
    │   │   │   ├── IconDouyin3.tsx
    │   │   │   ├── IconDrag.tsx
    │   │   │   ├── IconDuihao.tsx
    │   │   │   ├── IconDuihao1.tsx
    │   │   │   ├── IconDuihualishi1.tsx
    │   │   │   ├── IconExcel1.tsx
    │   │   │   ├── IconFabu.tsx
    │   │   │   ├── IconFankui.tsx
    │   │   │   ├── IconFankuiwenti.tsx
    │   │   │   ├── IconFasong.tsx
    │   │   │   ├── IconFeishu.tsx
    │   │   │   ├── IconFeishujiqiren.tsx
    │   │   │   ├── IconFenxi.tsx
    │   │   │   ├── IconFenxiang.tsx
    │   │   │   ├── IconFireworks.tsx
    │   │   │   ├── IconFuzhi.tsx
    │   │   │   ├── IconFuzhi1.tsx
    │   │   │   ├── IconGemini.tsx
    │   │   │   ├── IconGeminiAi.tsx
    │   │   │   ├── IconGengduo.tsx
    │   │   │   ├── IconGengxinshijian.tsx
    │   │   │   ├── IconGitHub1.tsx
    │   │   │   ├── IconGitee_ai.tsx
    │   │   │   ├── IconGithub.tsx
    │   │   │   ├── IconGongjuTool.tsx
    │   │   │   ├── IconGongxian.tsx
    │   │   │   ├── IconGpustack.tsx
    │   │   │   ├── IconGraphRag.tsx
    │   │   │   ├── IconGrok.tsx
    │   │   │   ├── IconGroup.tsx
    │   │   │   ├── IconGuajian.tsx
    │   │   │   ├── IconHuanyuan.tsx
    │   │   │   ├── IconHuoshanyinqing.tsx
    │   │   │   ├── IconHyperbolic.tsx
    │   │   │   ├── IconIPdizhijiancha.tsx
    │   │   │   ├── IconIcon_tool_close.tsx
    │   │   │   ├── IconImageError.tsx
    │   │   │   ├── IconInfini.tsx
    │   │   │   ├── IconJiage.tsx
    │   │   │   ├── IconJiahao.tsx
    │   │   │   ├── IconJiajianzujianjiahao.tsx
    │   │   │   ├── IconJianyiwendang.tsx
    │   │   │   ├── IconJichuwendang.tsx
    │   │   │   ├── IconJina.tsx
    │   │   │   ├── IconJinggao.tsx
    │   │   │   ├── IconJinsousuo.tsx
    │   │   │   ├── IconJiugongge.tsx
    │   │   │   ├── IconJushou.tsx
    │   │   │   ├── IconKefu.tsx
    │   │   │   ├── IconKehuanli.tsx
    │   │   │   ├── IconKehupingjia.tsx
    │   │   │   ├── IconKejian.tsx
    │   │   │   ├── IconKim.tsx
    │   │   │   ├── IconKoulingrenzheng.tsx
    │   │   │   ├── IconLDAP.tsx
    │   │   │   ├── IconLanyun.tsx
    │   │   │   ├── IconLepton.tsx
    │   │   │   ├── IconLianjiezu.tsx
    │   │   │   ├── IconLianjiezu1.tsx
    │   │   │   ├── IconLingyiwanwu.tsx
    │   │   │   ├── IconLmstudio.tsx
    │   │   │   ├── IconLogoGroq.tsx
    │   │   │   ├── IconLunbotu.tsx
    │   │   │   ├── IconMianbaoxie.tsx
    │   │   │   ├── IconMima.tsx
    │   │   │   ├── IconMingliangmoshi.tsx
    │   │   │   ├── IconMiniMax.tsx
    │   │   │   ├── IconMistral.tsx
    │   │   │   ├── IconMixedbread.tsx
    │   │   │   ├── IconModaGPT.tsx
    │   │   │   ├── IconMoxing.tsx
    │   │   │   ├── IconMulu.tsx
    │   │   │   ├── IconMulushouqi.tsx
    │   │   │   ├── IconMuluwendang.tsx
    │   │   │   ├── IconMuluzhankai.tsx
    │   │   │   ├── IconNeirongdagang.tsx
    │   │   │   ├── IconNeirongguanli.tsx
    │   │   │   ├── IconNeteaseYoudao.tsx
    │   │   │   ├── IconNewapi.tsx
    │   │   │   ├── IconNomic_logo.tsx
    │   │   │   ├── IconO3.tsx
    │   │   │   ├── IconOcoolai.tsx
    │   │   │   ├── IconOllama.tsx
    │   │   │   ├── IconOpenrouter.tsx
    │   │   │   ├── IconPCduan.tsx
    │   │   │   ├── IconPDF.tsx
    │   │   │   ├── IconPageview1.tsx
    │   │   │   ├── IconPaperFull.tsx
    │   │   │   ├── IconPaperPlaneFill.tsx
    │   │   │   ├── IconPeizhi.tsx
    │   │   │   ├── IconPerplexity.tsx
    │   │   │   ├── IconPlainText1.tsx
    │   │   │   ├── IconPpio.tsx
    │   │   │   ├── IconQQ.tsx
    │   │   │   ├── IconQQ1.tsx
    │   │   │   ├── IconQiehuan.tsx
    │   │   │   ├── IconQiniuyun.tsx
    │   │   │   ├── IconQiyeweixinjiqiren.tsx
    │   │   │   ├── IconQiyeweixinkefu.tsx
    │   │   │   ├── IconQiyewx.tsx
    │   │   │   ├── IconQunliao.tsx
    │   │   │   ├── IconQunliao1.tsx
    │   │   │   ├── IconQuseqi.tsx
    │   │   │   ├── IconSetFull.tsx
    │   │   │   ├── IconShanchu.tsx
    │   │   │   ├── IconShanchu1.tsx
    │   │   │   ├── IconShanchu2.tsx
    │   │   │   ├── IconShangchuan.tsx
    │   │   │   ├── IconShangjiantou.tsx
    │   │   │   ├── IconShengji.tsx
    │   │   │   ├── IconShensemoshi.tsx
    │   │   │   ├── IconShoujihao.tsx
    │   │   │   ├── IconShuaxin.tsx
    │   │   │   ├── IconShuzikapian.tsx
    │   │   │   ├── IconSousuo.tsx
    │   │   │   ├── IconStep.tsx
    │   │   │   ├── IconTengxunhunyuan.tsx
    │   │   │   ├── IconTengxunyun.tsx
    │   │   │   ├── IconTexing.tsx
    │   │   │   ├── IconTextColor.tsx
    │   │   │   ├── IconTianjia.tsx
    │   │   │   ├── IconTianjiachengyuan.tsx
    │   │   │   ├── IconTianjiawendang.tsx
    │   │   │   ├── IconTianyiyun.tsx
    │   │   │   ├── IconTingzhi.tsx
    │   │   │   ├── IconTips.tsx
    │   │   │   ├── IconTokenflux.tsx
    │   │   │   ├── IconTokenguanli.tsx
    │   │   │   ├── IconTongjifenxi1.tsx
    │   │   │   ├── IconTuozhuai.tsx
    │   │   │   ├── IconTupian.tsx
    │   │   │   ├── IconTushu.tsx
    │   │   │   ├── IconUI_icon_wangfanjiantou.tsx
    │   │   │   ├── IconUnknow1.tsx
    │   │   │   ├── IconWangyeguajian.tsx
    │   │   │   ├── IconWebPage1.tsx
    │   │   │   ├── IconWeibo.tsx
    │   │   │   ├── IconWeibo1.tsx
    │   │   │   ├── IconWeixingongzhonghao.tsx
    │   │   │   ├── IconWeixingongzhonghaoDaiyanse.tsx
    │   │   │   ├── IconWendajiqiren.tsx
    │   │   │   ├── IconWenhao.tsx
    │   │   │   ├── IconWenjian.tsx
    │   │   │   ├── IconWenjianjia.tsx
    │   │   │   ├── IconWenjianjiaKai.tsx
    │   │   │   ├── IconWenzi.tsx
    │   │   │   ├── IconWenzishuliang.tsx
    │   │   │   ├── IconWord.tsx
    │   │   │   ├── IconXiajiantou.tsx
    │   │   │   ├── IconXiala.tsx
    │   │   │   ├── IconXiala1.tsx
    │   │   │   ├── IconXialaCopy.tsx
    │   │   │   ├── IconXiaohongshu.tsx
    │   │   │   ├── IconXiaohongshuHui.tsx
    │   │   │   ├── IconXinduihua.tsx
    │   │   │   ├── IconXinference.tsx
    │   │   │   ├── IconXingxing.tsx
    │   │   │   ├── IconYanzhengma.tsx
    │   │   │   ├── IconYidongduan.tsx
    │   │   │   ├── IconYingweida.tsx
    │   │   │   ├── IconYonghuwenjianjia.tsx
    │   │   │   ├── IconYoutuzuozi.tsx
    │   │   │   ├── IconYouxiang.tsx
    │   │   │   ├── IconYouxiang1.tsx
    │   │   │   ├── IconYulan.tsx
    │   │   │   ├── IconYunhang.tsx
    │   │   │   ├── IconYunhang1.tsx
    │   │   │   ├── IconYunpan.tsx
    │   │   │   ├── IconZaixianzixun.tsx
    │   │   │   ├── IconZhanghao.tsx
    │   │   │   ├── IconZhiding.tsx
    │   │   │   ├── IconZhinengwenda.tsx
    │   │   │   ├── IconZhipuAI.tsx
    │   │   │   ├── IconZhipuqingyan.tsx
    │   │   │   ├── IconZhishikulogo.tsx
    │   │   │   ├── IconZiti.tsx
    │   │   │   ├── IconZujian.tsx
    │   │   │   ├── IconZuotuyouzi.tsx
    │   │   │   ├── IconZuzhi.tsx
    │   │   │   └── index.tsx
    │   │   └── tsconfig.json
    │   ├── themes/
    │   │   ├── package.json
    │   │   ├── src/
    │   │   │   ├── black.ts
    │   │   │   ├── blue.ts
    │   │   │   ├── constants.ts
    │   │   │   ├── dark.ts
    │   │   │   ├── darkDeepForest.ts
    │   │   │   ├── darkGold.ts
    │   │   │   ├── deepTeal.ts
    │   │   │   ├── electricBlue.ts
    │   │   │   ├── green.ts
    │   │   │   ├── index.ts
    │   │   │   ├── light.ts
    │   │   │   ├── orange.ts
    │   │   │   ├── purple.ts
    │   │   │   └── red.ts
    │   │   ├── theme.d.ts
    │   │   └── tsconfig.json
    │   └── ui/
    │       ├── env.d.ts
    │       ├── package.json
    │       ├── src/
    │       │   ├── banner/
    │       │   │   └── index.tsx
    │       │   ├── basicDoc/
    │       │   │   └── index.tsx
    │       │   ├── blockGrid/
    │       │   │   └── index.tsx
    │       │   ├── carousel/
    │       │   │   ├── index.css
    │       │   │   └── index.tsx
    │       │   ├── case/
    │       │   │   └── index.tsx
    │       │   ├── comment/
    │       │   │   └── index.tsx
    │       │   ├── component/
    │       │   │   └── styledCommon/
    │       │   │       └── index.tsx
    │       │   ├── constants/
    │       │   │   └── index.ts
    │       │   ├── dirDoc/
    │       │   │   └── index.tsx
    │       │   ├── faq/
    │       │   │   └── index.tsx
    │       │   ├── feature/
    │       │   │   └── index.tsx
    │       │   ├── footer/
    │       │   │   ├── Overlay.tsx
    │       │   │   └── index.tsx
    │       │   ├── header/
    │       │   │   ├── NavBtns.tsx
    │       │   │   └── index.tsx
    │       │   ├── hooks/
    │       │   │   └── useGsapAnimation.tsx
    │       │   ├── imgText/
    │       │   │   └── index.tsx
    │       │   ├── index.tsx
    │       │   ├── metrics/
    │       │   │   └── index.tsx
    │       │   ├── question/
    │       │   │   └── index.tsx
    │       │   ├── simpleDoc/
    │       │   │   └── index.tsx
    │       │   ├── text/
    │       │   │   └── index.tsx
    │       │   ├── utils.ts
    │       │   ├── welcomeFooter/
    │       │   │   ├── Overlay.tsx
    │       │   │   └── index.tsx
    │       │   └── welcomeHeader/
    │       │       ├── NavBtns.tsx
    │       │       └── index.tsx
    │       └── tsconfig.json
    ├── pnpm-workspace.yaml
    ├── prettier.config.js
    └── tsconfig.base.json

================================================
FILE CONTENTS
================================================

================================================
FILE: .gitattributes
================================================
backend/store/ipdb/ip2region.xdb filter=lfs diff=lfs merge=lfs -text


================================================
FILE: .github/ISSUE_TEMPLATE/功能建议.md
================================================
---
name: 功能建议
about: 为PandaWiki提出新的想法或建议
title: "[功能建议] "
labels: enhancement
assignees: ''

---

**功能描述**
请简明扼要地描述您希望添加的功能或改进。

**使用场景**
请描述此功能会在哪些情况下使用,以及它将如何帮助用户。

**实现建议**
如果您有关于如何实现此功能的想法,请在此分享。

**附加信息**
请提供任何其他相关信息、参考资料或截图。


================================================
FILE: .github/ISSUE_TEMPLATE/故障报告.md
================================================
---
name: 故障报告
about: 创建故障报告以改进产品
title: "[故障报告] "
labels: bug
assignees: ''

---

**描述问题**
请简明扼要地描述您遇到的问题。

**复现步骤**
请描述如何复现这个问题:
1. 前往 '...'
2. 点击 '...'
3. 滚动到 '...'
4. 出现错误

**期望行为**
请描述您期望发生的情况。

**截图**
如有可能,请添加截图以帮助解释您的问题。

**环境信息**
- 操作系统:[如:Ubuntu/Windows]
- 浏览器:[如:Chrome/Safari/Firefox]
- 版本:[如:V1.2.3]

**其他信息**
请在此处添加有关此问题的任何其他背景信息。


================================================
FILE: .github/PULL_REQUEST_TEMPLATE.md
================================================
# PR 标题

简要描述这次 PR 的目的和内容

## 相关 Issue

关闭或关联的 Issue (如有):
- 修复 #123
- 关联 #456

## 变更类型

请勾选适用的变更类型:
- [ ] Bug 修复 (不兼容变更的修复)
- [ ] 新功能 (不兼容变更的新功能)
- [ ] 功能改进 (不兼容现有功能的改进)
- [ ] 文档更新
- [ ] 依赖更新
- [ ] 重构 (不影响功能的代码修改)
- [ ] 测试用例
- [ ] CI/CD 配置变更
- [ ] 其他 (请描述):

## 变更内容

详细描述本次 PR 的具体变更内容:
1. 
2. 
3. 

## 测试情况

描述本次变更的测试情况:
- [ ] 已本地测试
- [ ] 已添加测试用例
- [ ] 不需要测试 (理由: )

## 其他说明

任何其他需要说明的事项:

================================================
FILE: .github/workflows/backend.yml
================================================
name: Backend Build and Push

on:
  push:
    tags:
      - "v[0-9]+.[0-9]+.[0-9]+*"

jobs:
  build:
    runs-on: ubuntu-latest
    strategy:
      matrix:
        service: [api, consumer]
    timeout-minutes: 30

    outputs:
      version: ${{ steps.get_version.outputs.VERSION }}

    steps:
      - name: Checkout code
        uses: actions/checkout@v4
        with:
          lfs: true
          submodules: true
          token: ${{ secrets.PRO_TOKEN }}

      - name: Get version
        id: get_version
        run: |
          if [[ $GITHUB_REF == refs/tags/* ]]; then
            if [[ $GITHUB_REF == refs/tags/backend-* ]]; then
              echo "VERSION=${GITHUB_REF#refs/tags/backend-}" >> $GITHUB_OUTPUT
            else
              echo "VERSION=${GITHUB_REF#refs/tags/}" >> $GITHUB_OUTPUT
            fi
          else
            echo "VERSION=${GITHUB_SHA::7}" >> $GITHUB_OUTPUT
          fi

      - name: Set up QEMU
        uses: docker/setup-qemu-action@v3
        with:
          platforms: 'arm64,amd64'

      - name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v3

      - name: Login to Aliyun Container Registry
        if: startsWith(github.ref, 'refs/tags/')
        uses: docker/login-action@v3
        with:
          registry: chaitin-registry.cn-hangzhou.cr.aliyuncs.com
          username: ${{ secrets.CT_ALIYUN_USER }}
          password: ${{ secrets.CT_ALIYUN_PASS }}

      - name: Build and push
        uses: docker/build-push-action@v5
        with:
          context: ./backend
          file: ./backend/Dockerfile.${{ matrix.service }}.pro
          push: ${{ startsWith(github.ref, 'refs/tags/') }}
          platforms: linux/amd64, linux/arm64
          tags: chaitin-registry.cn-hangzhou.cr.aliyuncs.com/chaitin/panda-wiki-${{ matrix.service }}:${{ steps.get_version.outputs.VERSION }}
          build-args: |
            VERSION=${{ steps.get_version.outputs.VERSION }}
          cache-from: |
            type=gha,scope=${{ matrix.service }}
          cache-to: |
            type=gha,scope=${{ matrix.service }},mode=max


================================================
FILE: .github/workflows/backend_check.yml
================================================
name: Backend Pull Request Check

on:
  pull_request:
    branches:
      - main
    paths:
      - 'backend/**'

permissions:
  contents: read

jobs:
  golangci-lint:
    name: lint
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-go@v5
        with:
          go-version: '1.24'
          cache-dependency-path: 'backend/go.sum'
      - name: golangci-lint
        uses: golangci/golangci-lint-action@v8
        with:
          version: v2.1
          working-directory: backend
          args: --timeout 5m

  go-mod-check:
    name: go mod check
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-go@v5
        with:
          go-version: '1.24'
          cache-dependency-path: 'backend/go.sum'

      - name: Check go.mod formatting
        working-directory: backend
        run: |
          rm -rf cmd/api_pro
          if ! go mod tidy --diff ; then
            echo "::error::go.mod or go.sum is not properly formatted. Please run 'go mod tidy' locally and commit the changes."
            exit 1
          fi
          if ! go mod verify ; then
            echo "::error::go.mod or go.sum has unverified dependencies. Please run 'go mod verify' locally and commit the changes."
            exit 1
          fi
  build:
    runs-on: ubuntu-latest
    strategy:
      matrix:
        service: [api, consumer]
    timeout-minutes: 30

    outputs:
      version: ${{ steps.get_version.outputs.VERSION }}

    steps:
      - name: Checkout code
        uses: actions/checkout@v4
        with:
          lfs: true

      - name: Get version
        id: get_version
        run: |
          if [[ $GITHUB_REF == refs/tags/* ]]; then
            if [[ $GITHUB_REF == refs/tags/backend-* ]]; then
              echo "VERSION=${GITHUB_REF#refs/tags/backend-}" >> $GITHUB_OUTPUT
            else
              echo "VERSION=${GITHUB_REF#refs/tags/}" >> $GITHUB_OUTPUT
            fi
          else
            echo "VERSION=${GITHUB_SHA::7}" >> $GITHUB_OUTPUT
          fi

      - name: Set up QEMU
        uses: docker/setup-qemu-action@v3
        with:
          platforms: 'arm64,amd64'

      - name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v3

      - name: Build
        uses: docker/build-push-action@v5
        with:
          context: ./backend
          file: ./backend/Dockerfile.${{ matrix.service }}
          push: false
          platforms: linux/amd64, linux/arm64
          tags: chaitin-registry.cn-hangzhou.cr.aliyuncs.com/chaitin/panda-wiki-${{ matrix.service }}:${{ steps.get_version.outputs.VERSION }}
          build-args: |
            VERSION=${{ steps.get_version.outputs.VERSION }}
          cache-from: |
            type=gha,scope=${{ matrix.service }}
          cache-to: |
            type=gha,scope=${{ matrix.service }},mode=max


================================================
FILE: .github/workflows/web.yml
================================================
name: Web Build and Push

on:
  push:
    branches:
      - frontend-*
      - admin-*
      - app-*
    tags:
      - 'admin-v[0-9]+.[0-9]+.[0-9]+*'
      - 'app-v[0-9]+.[0-9]+.[0-9]+*'
      - 'v[0-9]+.[0-9]+.[0-9]+*'
  pull_request:
    branches:
      - main
    paths:
      - 'web/**'

jobs:
  version:
    runs-on: ubuntu-latest
    outputs:
      version: ${{ steps.get_version.outputs.VERSION }}

    steps:
      - name: Get version
        id: get_version
        run: |
          if [[ $GITHUB_REF == refs/tags/* ]]; then
            # 支持 admin-v* / app-v* / v*
            if [[ $GITHUB_REF == refs/tags/admin-v* ]]; then
              echo "VERSION=${GITHUB_REF#refs/tags/admin-v}" >> $GITHUB_OUTPUT
            elif [[ $GITHUB_REF == refs/tags/app-v* ]]; then
              echo "VERSION=${GITHUB_REF#refs/tags/app-v}" >> $GITHUB_OUTPUT
            else
              echo "VERSION=${GITHUB_REF#refs/tags/v}" >> $GITHUB_OUTPUT
            fi
          else
            echo "VERSION=${GITHUB_SHA::7}" >> $GITHUB_OUTPUT
          fi

  build:
    runs-on: ubuntu-latest
    needs: [version]

    steps:
      - name: Checkout code
        uses: actions/checkout@v4

      - name: Set up Node.js
        uses: actions/setup-node@v4
        with:
          node-version: '20'

      - name: Install pnpm
        uses: pnpm/action-setup@v2
        with:
          version: 10

      - name: Get pnpm store directory
        shell: bash
        run: |
          echo "STORE_PATH=$(pnpm store path --silent)" >> $GITHUB_ENV

      - name: Setup pnpm cache
        uses: actions/cache@v3
        with:
          path: ${{ env.STORE_PATH }}
          key: ${{ runner.os }}-pnpm-store-${{ hashFiles('web/pnpm-lock.yaml') }}
          restore-keys: |
            ${{ runner.os }}-pnpm-store-

      - name: Install dependencies
        run: |
          cd web
          pnpm install --frozen-lockfile --prefer-offline

      - name: Setup Env for admin
        run: |
          cd web/admin
          echo "VITE_APP_VERSION=${{ needs.version.outputs.version }}" >> .env.production

      - name: Build admin and app (parallel)
        env:
          SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }}
        run: |
          cd web
          pnpm run build

      - name: 'Tar admin files'
        run: tar -cvf web/admin/dist.tar web/admin/dist

      - name: Upload admin build artifacts
        uses: actions/upload-artifact@v4
        with:
          name: admin-build
          path: web/admin/dist.tar
          if-no-files-found: error
          include-hidden-files: true

      - name: 'Tar app files'
        run: tar -cvf web/app/dist.tar web/app/dist

      - name: Upload app build artifacts
        uses: actions/upload-artifact@v4
        with:
          name: app-build
          path: web/app/dist.tar
          if-no-files-found: error
          include-hidden-files: true

  package:
    needs: [build, version]
    runs-on: ubuntu-latest
    strategy:
      matrix:
        project: [admin, app]
    if: startsWith(github.ref, 'refs/tags/')

    steps:
      - name: Checkout code
        uses: actions/checkout@v4

      - name: Download build artifacts
        uses: actions/download-artifact@v4
        with:
          name: ${{ matrix.project }}-build

      - name: Extract files
        run: |
          tar -xvf dist.tar

      - name: Check file structure
        run: |
          echo "Current directory: $(pwd)"
          echo "Listing web/${{ matrix.project }} directory:"
          ls -la web/${{ matrix.project }}
          echo "Listing web/${{ matrix.project }}/dist directory:"
          ls -la web/${{ matrix.project }}/dist

      - name: Set up QEMU
        uses: docker/setup-qemu-action@v3

      - name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v3

      - name: Login to Aliyun Container Registry
        uses: docker/login-action@v3
        with:
          registry: chaitin-registry.cn-hangzhou.cr.aliyuncs.com
          username: ${{ secrets.CT_ALIYUN_USER }}
          password: ${{ secrets.CT_ALIYUN_PASS }}

      - name: Package and push
        uses: docker/build-push-action@v5
        with:
          context: ./web/${{ matrix.project }}
          file: ./web/${{ matrix.project }}/Dockerfile
          push: true
          platforms: linux/amd64, linux/arm64
          tags: chaitin-registry.cn-hangzhou.cr.aliyuncs.com/chaitin/panda-wiki-${{ matrix.project == 'admin' && 'nginx' || 'app' }}:v${{ needs.version.outputs.version }}
          cache-from: type=gha
          cache-to: type=gha,mode=max


================================================
FILE: .gitignore
================================================
# If you prefer the allow list template instead of the deny list, see community template:
# https://github.com/github/gitignore/blob/main/community/Golang/Go.AllowList.gitignore
#
# Binaries for programs and plugins
*.exe
*.exe~
*.dll
*.so
*.dylib

# Test binary, built with `go test -c`
*.test

# Output of the go coverage tool, specifically when used with LiteIDE
*.out

# Dependency directories (remove the comment below to include it)
# vendor/

# Go workspace file
go.work
go.work.sum

# env file
.env

**/.DS_Store

.vscode

deploy
local

.idea
__debug*


================================================
FILE: .gitmodules
================================================
[submodule "backend/pro"]
	path = backend/pro
	url = git@github.com:chaitin/PandaWikiPro.git


================================================
FILE: CODE_OF_CONDUCT.md
================================================
# Contributor Covenant Code of Conduct

## Our Pledge

We as members, contributors, and leaders pledge to make participation in our
community a harassment-free experience for everyone, regardless of age, body
size, visible or invisible disability, ethnicity, sex characteristics, gender
identity and expression, level of experience, education, socio-economic status,
nationality, personal appearance, race, religion, or sexual identity
and orientation.

We pledge to act and interact in ways that contribute to an open, welcoming,
diverse, inclusive, and healthy community.

## Our Standards

Examples of behavior that contributes to a positive environment for our
community include:

* Demonstrating empathy and kindness toward other people
* Being respectful of differing opinions, viewpoints, and experiences
* Giving and gracefully accepting constructive feedback
* Accepting responsibility and apologizing to those affected by our mistakes,
  and learning from the experience
* Focusing on what is best not just for us as individuals, but for the
  overall community

Examples of unacceptable behavior include:

* The use of sexualized language or imagery, and sexual attention or
  advances of any kind
* Trolling, insulting or derogatory comments, and personal or political attacks
* Public or private harassment
* Publishing others' private information, such as a physical or email
  address, without their explicit permission
* Other conduct which could reasonably be considered inappropriate in a
  professional setting

## Enforcement Responsibilities

Community leaders are responsible for clarifying and enforcing our standards of
acceptable behavior and will take appropriate and fair corrective action in
response to any behavior that they deem inappropriate, threatening, offensive,
or harmful.

Community leaders have the right and responsibility to remove, edit, or reject
comments, commits, code, wiki edits, issues, and other contributions that are
not aligned to this Code of Conduct, and will communicate reasons for moderation
decisions when appropriate.

## Scope

This Code of Conduct applies within all community spaces, and also applies when
an individual is officially representing the community in public spaces.
Examples of representing our community include using an official e-mail address,
posting via an official social media account, or acting as an appointed
representative at an online or offline event.

## Enforcement

Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported to the community leaders responsible for enforcement at
.
All complaints will be reviewed and investigated promptly and fairly.

All community leaders are obligated to respect the privacy and security of the
reporter of any incident.

## Enforcement Guidelines

Community leaders will follow these Community Impact Guidelines in determining
the consequences for any action they deem in violation of this Code of Conduct:

### 1. Correction

**Community Impact**: Use of inappropriate language or other behavior deemed
unprofessional or unwelcome in the community.

**Consequence**: A private, written warning from community leaders, providing
clarity around the nature of the violation and an explanation of why the
behavior was inappropriate. A public apology may be requested.

### 2. Warning

**Community Impact**: A violation through a single incident or series
of actions.

**Consequence**: A warning with consequences for continued behavior. No
interaction with the people involved, including unsolicited interaction with
those enforcing the Code of Conduct, for a specified period of time. This
includes avoiding interactions in community spaces as well as external channels
like social media. Violating these terms may lead to a temporary or
permanent ban.

### 3. Temporary Ban

**Community Impact**: A serious violation of community standards, including
sustained inappropriate behavior.

**Consequence**: A temporary ban from any sort of interaction or public
communication with the community for a specified period of time. No public or
private interaction with the people involved, including unsolicited interaction
with those enforcing the Code of Conduct, is allowed during this period.
Violating these terms may lead to a permanent ban.

### 4. Permanent Ban

**Community Impact**: Demonstrating a pattern of violation of community
standards, including sustained inappropriate behavior,  harassment of an
individual, or aggression toward or disparagement of classes of individuals.

**Consequence**: A permanent ban from any sort of public interaction within
the community.

## Attribution

This Code of Conduct is adapted from the [Contributor Covenant][homepage],
version 2.0, available at
https://www.contributor-covenant.org/version/2/0/code_of_conduct.html.

Community Impact Guidelines were inspired by [Mozilla's code of conduct
enforcement ladder](https://github.com/mozilla/diversity).

[homepage]: https://www.contributor-covenant.org

For answers to common questions about this code of conduct, see the FAQ at
https://www.contributor-covenant.org/faq. Translations are available at
https://www.contributor-covenant.org/translations.


================================================
FILE: CONTRIBUTING.md
================================================
# 贡献指南

欢迎为 PandaWiki 项目做贡献!本指南将帮助你开始贡献代码。


## 代码提交流程

1. 创建新的功能分支:
```bash
git checkout -b feat/your-feature-name
```

2. 提交代码前请确保:
- 已通过所有测试
- 已格式化代码
- 已更新相关文档

3. 创建 Pull Request:
- 确保 PR 有清晰的标题和描述
- 关联相关 Issue
- 遵循 PR 模板要求

## 代码风格

1. **Go 代码**:
- 使用 gofmt 格式化代码
- 遵循 effective go 指南
- 保持函数简洁 (<80 行)

2. **TypeScript 代码**:
- 使用 ESLint 检查代码
- 遵循标准 React 实践
- 使用 Prettier 格式化

## 测试要求

1. 后端:
- 所有主要功能应有单元测试
- 覆盖率不应低于 80%
- 运行 `make test` 来执行测试

2. 前端:
- 组件应包含基本测试
- 重要交互逻辑应有测试
- 运行 `npm test` 来执行测试

## 其他指南

- 提交消息应清晰且有意义
- 大功能实现应先创建设计文档
- 问题讨论可以在 GitHub Issues 中进行
- 遇到问题随时提问

================================================
FILE: LICENSE
================================================
                    GNU AFFERO GENERAL PUBLIC LICENSE
                       Version 3, 19 November 2007

 Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
 Everyone is permitted to copy and distribute verbatim copies
 of this license document, but changing it is not allowed.

                            Preamble

  The GNU Affero General Public License is a free, copyleft license for
software and other kinds of works, specifically designed to ensure
cooperation with the community in the case of network server software.

  The licenses for most software and other practical works are designed
to take away your freedom to share and change the works.  By contrast,
our General Public Licenses are intended to guarantee your freedom to
share and change all versions of a program--to make sure it remains free
software for all its users.

  When we speak of free software, we are referring to freedom, not
price.  Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
them if you wish), that you receive source code or can get it if you
want it, that you can change the software or use pieces of it in new
free programs, and that you know you can do these things.

  Developers that use our General Public Licenses protect your rights
with two steps: (1) assert copyright on the software, and (2) offer
you this License which gives you legal permission to copy, distribute
and/or modify the software.

  A secondary benefit of defending all users' freedom is that
improvements made in alternate versions of the program, if they
receive widespread use, become available for other developers to
incorporate.  Many developers of free software are heartened and
encouraged by the resulting cooperation.  However, in the case of
software used on network servers, this result may fail to come about.
The GNU General Public License permits making a modified version and
letting the public access it on a server without ever releasing its
source code to the public.

  The GNU Affero General Public License is designed specifically to
ensure that, in such cases, the modified source code becomes available
to the community.  It requires the operator of a network server to
provide the source code of the modified version running there to the
users of that server.  Therefore, public use of a modified version, on
a publicly accessible server, gives the public access to the source
code of the modified version.

  An older license, called the Affero General Public License and
published by Affero, was designed to accomplish similar goals.  This is
a different license, not a version of the Affero GPL, but Affero has
released a new version of the Affero GPL which permits relicensing under
this license.

  The precise terms and conditions for copying, distribution and
modification follow.

                       TERMS AND CONDITIONS

  0. Definitions.

  "This License" refers to version 3 of the GNU Affero General Public License.

  "Copyright" also means copyright-like laws that apply to other kinds of
works, such as semiconductor masks.

  "The Program" refers to any copyrightable work licensed under this
License.  Each licensee is addressed as "you".  "Licensees" and
"recipients" may be individuals or organizations.

  To "modify" a work means to copy from or adapt all or part of the work
in a fashion requiring copyright permission, other than the making of an
exact copy.  The resulting work is called a "modified version" of the
earlier work or a work "based on" the earlier work.

  A "covered work" means either the unmodified Program or a work based
on the Program.

  To "propagate" a work means to do anything with it that, without
permission, would make you directly or secondarily liable for
infringement under applicable copyright law, except executing it on a
computer or modifying a private copy.  Propagation includes copying,
distribution (with or without modification), making available to the
public, and in some countries other activities as well.

  To "convey" a work means any kind of propagation that enables other
parties to make or receive copies.  Mere interaction with a user through
a computer network, with no transfer of a copy, is not conveying.

  An interactive user interface displays "Appropriate Legal Notices"
to the extent that it includes a convenient and prominently visible
feature that (1) displays an appropriate copyright notice, and (2)
tells the user that there is no warranty for the work (except to the
extent that warranties are provided), that licensees may convey the
work under this License, and how to view a copy of this License.  If
the interface presents a list of user commands or options, such as a
menu, a prominent item in the list meets this criterion.

  1. Source Code.

  The "source code" for a work means the preferred form of the work
for making modifications to it.  "Object code" means any non-source
form of a work.

  A "Standard Interface" means an interface that either is an official
standard defined by a recognized standards body, or, in the case of
interfaces specified for a particular programming language, one that
is widely used among developers working in that language.

  The "System Libraries" of an executable work include anything, other
than the work as a whole, that (a) is included in the normal form of
packaging a Major Component, but which is not part of that Major
Component, and (b) serves only to enable use of the work with that
Major Component, or to implement a Standard Interface for which an
implementation is available to the public in source code form.  A
"Major Component", in this context, means a major essential component
(kernel, window system, and so on) of the specific operating system
(if any) on which the executable work runs, or a compiler used to
produce the work, or an object code interpreter used to run it.

  The "Corresponding Source" for a work in object code form means all
the source code needed to generate, install, and (for an executable
work) run the object code and to modify the work, including scripts to
control those activities.  However, it does not include the work's
System Libraries, or general-purpose tools or generally available free
programs which are used unmodified in performing those activities but
which are not part of the work.  For example, Corresponding Source
includes interface definition files associated with source files for
the work, and the source code for shared libraries and dynamically
linked subprograms that the work is specifically designed to require,
such as by intimate data communication or control flow between those
subprograms and other parts of the work.

  The Corresponding Source need not include anything that users
can regenerate automatically from other parts of the Corresponding
Source.

  The Corresponding Source for a work in source code form is that
same work.

  2. Basic Permissions.

  All rights granted under this License are granted for the term of
copyright on the Program, and are irrevocable provided the stated
conditions are met.  This License explicitly affirms your unlimited
permission to run the unmodified Program.  The output from running a
covered work is covered by this License only if the output, given its
content, constitutes a covered work.  This License acknowledges your
rights of fair use or other equivalent, as provided by copyright law.

  You may make, run and propagate covered works that you do not
convey, without conditions so long as your license otherwise remains
in force.  You may convey covered works to others for the sole purpose
of having them make modifications exclusively for you, or provide you
with facilities for running those works, provided that you comply with
the terms of this License in conveying all material for which you do
not control copyright.  Those thus making or running the covered works
for you must do so exclusively on your behalf, under your direction
and control, on terms that prohibit them from making any copies of
your copyrighted material outside their relationship with you.

  Conveying under any other circumstances is permitted solely under
the conditions stated below.  Sublicensing is not allowed; section 10
makes it unnecessary.

  3. Protecting Users' Legal Rights From Anti-Circumvention Law.

  No covered work shall be deemed part of an effective technological
measure under any applicable law fulfilling obligations under article
11 of the WIPO copyright treaty adopted on 20 December 1996, or
similar laws prohibiting or restricting circumvention of such
measures.

  When you convey a covered work, you waive any legal power to forbid
circumvention of technological measures to the extent such circumvention
is effected by exercising rights under this License with respect to
the covered work, and you disclaim any intention to limit operation or
modification of the work as a means of enforcing, against the work's
users, your or third parties' legal rights to forbid circumvention of
technological measures.

  4. Conveying Verbatim Copies.

  You may convey verbatim copies of the Program's source code as you
receive it, in any medium, provided that you conspicuously and
appropriately publish on each copy an appropriate copyright notice;
keep intact all notices stating that this License and any
non-permissive terms added in accord with section 7 apply to the code;
keep intact all notices of the absence of any warranty; and give all
recipients a copy of this License along with the Program.

  You may charge any price or no price for each copy that you convey,
and you may offer support or warranty protection for a fee.

  5. Conveying Modified Source Versions.

  You may convey a work based on the Program, or the modifications to
produce it from the Program, in the form of source code under the
terms of section 4, provided that you also meet all of these conditions:

    a) The work must carry prominent notices stating that you modified
    it, and giving a relevant date.

    b) The work must carry prominent notices stating that it is
    released under this License and any conditions added under section
    7.  This requirement modifies the requirement in section 4 to
    "keep intact all notices".

    c) You must license the entire work, as a whole, under this
    License to anyone who comes into possession of a copy.  This
    License will therefore apply, along with any applicable section 7
    additional terms, to the whole of the work, and all its parts,
    regardless of how they are packaged.  This License gives no
    permission to license the work in any other way, but it does not
    invalidate such permission if you have separately received it.

    d) If the work has interactive user interfaces, each must display
    Appropriate Legal Notices; however, if the Program has interactive
    interfaces that do not display Appropriate Legal Notices, your
    work need not make them do so.

  A compilation of a covered work with other separate and independent
works, which are not by their nature extensions of the covered work,
and which are not combined with it such as to form a larger program,
in or on a volume of a storage or distribution medium, is called an
"aggregate" if the compilation and its resulting copyright are not
used to limit the access or legal rights of the compilation's users
beyond what the individual works permit.  Inclusion of a covered work
in an aggregate does not cause this License to apply to the other
parts of the aggregate.

  6. Conveying Non-Source Forms.

  You may convey a covered work in object code form under the terms
of sections 4 and 5, provided that you also convey the
machine-readable Corresponding Source under the terms of this License,
in one of these ways:

    a) Convey the object code in, or embodied in, a physical product
    (including a physical distribution medium), accompanied by the
    Corresponding Source fixed on a durable physical medium
    customarily used for software interchange.

    b) Convey the object code in, or embodied in, a physical product
    (including a physical distribution medium), accompanied by a
    written offer, valid for at least three years and valid for as
    long as you offer spare parts or customer support for that product
    model, to give anyone who possesses the object code either (1) a
    copy of the Corresponding Source for all the software in the
    product that is covered by this License, on a durable physical
    medium customarily used for software interchange, for a price no
    more than your reasonable cost of physically performing this
    conveying of source, or (2) access to copy the
    Corresponding Source from a network server at no charge.

    c) Convey individual copies of the object code with a copy of the
    written offer to provide the Corresponding Source.  This
    alternative is allowed only occasionally and noncommercially, and
    only if you received the object code with such an offer, in accord
    with subsection 6b.

    d) Convey the object code by offering access from a designated
    place (gratis or for a charge), and offer equivalent access to the
    Corresponding Source in the same way through the same place at no
    further charge.  You need not require recipients to copy the
    Corresponding Source along with the object code.  If the place to
    copy the object code is a network server, the Corresponding Source
    may be on a different server (operated by you or a third party)
    that supports equivalent copying facilities, provided you maintain
    clear directions next to the object code saying where to find the
    Corresponding Source.  Regardless of what server hosts the
    Corresponding Source, you remain obligated to ensure that it is
    available for as long as needed to satisfy these requirements.

    e) Convey the object code using peer-to-peer transmission, provided
    you inform other peers where the object code and Corresponding
    Source of the work are being offered to the general public at no
    charge under subsection 6d.

  A separable portion of the object code, whose source code is excluded
from the Corresponding Source as a System Library, need not be
included in conveying the object code work.

  A "User Product" is either (1) a "consumer product", which means any
tangible personal property which is normally used for personal, family,
or household purposes, or (2) anything designed or sold for incorporation
into a dwelling.  In determining whether a product is a consumer product,
doubtful cases shall be resolved in favor of coverage.  For a particular
product received by a particular user, "normally used" refers to a
typical or common use of that class of product, regardless of the status
of the particular user or of the way in which the particular user
actually uses, or expects or is expected to use, the product.  A product
is a consumer product regardless of whether the product has substantial
commercial, industrial or non-consumer uses, unless such uses represent
the only significant mode of use of the product.

  "Installation Information" for a User Product means any methods,
procedures, authorization keys, or other information required to install
and execute modified versions of a covered work in that User Product from
a modified version of its Corresponding Source.  The information must
suffice to ensure that the continued functioning of the modified object
code is in no case prevented or interfered with solely because
modification has been made.

  If you convey an object code work under this section in, or with, or
specifically for use in, a User Product, and the conveying occurs as
part of a transaction in which the right of possession and use of the
User Product is transferred to the recipient in perpetuity or for a
fixed term (regardless of how the transaction is characterized), the
Corresponding Source conveyed under this section must be accompanied
by the Installation Information.  But this requirement does not apply
if neither you nor any third party retains the ability to install
modified object code on the User Product (for example, the work has
been installed in ROM).

  The requirement to provide Installation Information does not include a
requirement to continue to provide support service, warranty, or updates
for a work that has been modified or installed by the recipient, or for
the User Product in which it has been modified or installed.  Access to a
network may be denied when the modification itself materially and
adversely affects the operation of the network or violates the rules and
protocols for communication across the network.

  Corresponding Source conveyed, and Installation Information provided,
in accord with this section must be in a format that is publicly
documented (and with an implementation available to the public in
source code form), and must require no special password or key for
unpacking, reading or copying.

  7. Additional Terms.

  "Additional permissions" are terms that supplement the terms of this
License by making exceptions from one or more of its conditions.
Additional permissions that are applicable to the entire Program shall
be treated as though they were included in this License, to the extent
that they are valid under applicable law.  If additional permissions
apply only to part of the Program, that part may be used separately
under those permissions, but the entire Program remains governed by
this License without regard to the additional permissions.

  When you convey a copy of a covered work, you may at your option
remove any additional permissions from that copy, or from any part of
it.  (Additional permissions may be written to require their own
removal in certain cases when you modify the work.)  You may place
additional permissions on material, added by you to a covered work,
for which you have or can give appropriate copyright permission.

  Notwithstanding any other provision of this License, for material you
add to a covered work, you may (if authorized by the copyright holders of
that material) supplement the terms of this License with terms:

    a) Disclaiming warranty or limiting liability differently from the
    terms of sections 15 and 16 of this License; or

    b) Requiring preservation of specified reasonable legal notices or
    author attributions in that material or in the Appropriate Legal
    Notices displayed by works containing it; or

    c) Prohibiting misrepresentation of the origin of that material, or
    requiring that modified versions of such material be marked in
    reasonable ways as different from the original version; or

    d) Limiting the use for publicity purposes of names of licensors or
    authors of the material; or

    e) Declining to grant rights under trademark law for use of some
    trade names, trademarks, or service marks; or

    f) Requiring indemnification of licensors and authors of that
    material by anyone who conveys the material (or modified versions of
    it) with contractual assumptions of liability to the recipient, for
    any liability that these contractual assumptions directly impose on
    those licensors and authors.

  All other non-permissive additional terms are considered "further
restrictions" within the meaning of section 10.  If the Program as you
received it, or any part of it, contains a notice stating that it is
governed by this License along with a term that is a further
restriction, you may remove that term.  If a license document contains
a further restriction but permits relicensing or conveying under this
License, you may add to a covered work material governed by the terms
of that license document, provided that the further restriction does
not survive such relicensing or conveying.

  If you add terms to a covered work in accord with this section, you
must place, in the relevant source files, a statement of the
additional terms that apply to those files, or a notice indicating
where to find the applicable terms.

  Additional terms, permissive or non-permissive, may be stated in the
form of a separately written license, or stated as exceptions;
the above requirements apply either way.

  8. Termination.

  You may not propagate or modify a covered work except as expressly
provided under this License.  Any attempt otherwise to propagate or
modify it is void, and will automatically terminate your rights under
this License (including any patent licenses granted under the third
paragraph of section 11).

  However, if you cease all violation of this License, then your
license from a particular copyright holder is reinstated (a)
provisionally, unless and until the copyright holder explicitly and
finally terminates your license, and (b) permanently, if the copyright
holder fails to notify you of the violation by some reasonable means
prior to 60 days after the cessation.

  Moreover, your license from a particular copyright holder is
reinstated permanently if the copyright holder notifies you of the
violation by some reasonable means, this is the first time you have
received notice of violation of this License (for any work) from that
copyright holder, and you cure the violation prior to 30 days after
your receipt of the notice.

  Termination of your rights under this section does not terminate the
licenses of parties who have received copies or rights from you under
this License.  If your rights have been terminated and not permanently
reinstated, you do not qualify to receive new licenses for the same
material under section 10.

  9. Acceptance Not Required for Having Copies.

  You are not required to accept this License in order to receive or
run a copy of the Program.  Ancillary propagation of a covered work
occurring solely as a consequence of using peer-to-peer transmission
to receive a copy likewise does not require acceptance.  However,
nothing other than this License grants you permission to propagate or
modify any covered work.  These actions infringe copyright if you do
not accept this License.  Therefore, by modifying or propagating a
covered work, you indicate your acceptance of this License to do so.

  10. Automatic Licensing of Downstream Recipients.

  Each time you convey a covered work, the recipient automatically
receives a license from the original licensors, to run, modify and
propagate that work, subject to this License.  You are not responsible
for enforcing compliance by third parties with this License.

  An "entity transaction" is a transaction transferring control of an
organization, or substantially all assets of one, or subdividing an
organization, or merging organizations.  If propagation of a covered
work results from an entity transaction, each party to that
transaction who receives a copy of the work also receives whatever
licenses to the work the party's predecessor in interest had or could
give under the previous paragraph, plus a right to possession of the
Corresponding Source of the work from the predecessor in interest, if
the predecessor has it or can get it with reasonable efforts.

  You may not impose any further restrictions on the exercise of the
rights granted or affirmed under this License.  For example, you may
not impose a license fee, royalty, or other charge for exercise of
rights granted under this License, and you may not initiate litigation
(including a cross-claim or counterclaim in a lawsuit) alleging that
any patent claim is infringed by making, using, selling, offering for
sale, or importing the Program or any portion of it.

  11. Patents.

  A "contributor" is a copyright holder who authorizes use under this
License of the Program or a work on which the Program is based.  The
work thus licensed is called the contributor's "contributor version".

  A contributor's "essential patent claims" are all patent claims
owned or controlled by the contributor, whether already acquired or
hereafter acquired, that would be infringed by some manner, permitted
by this License, of making, using, or selling its contributor version,
but do not include claims that would be infringed only as a
consequence of further modification of the contributor version.  For
purposes of this definition, "control" includes the right to grant
patent sublicenses in a manner consistent with the requirements of
this License.

  Each contributor grants you a non-exclusive, worldwide, royalty-free
patent license under the contributor's essential patent claims, to
make, use, sell, offer for sale, import and otherwise run, modify and
propagate the contents of its contributor version.

  In the following three paragraphs, a "patent license" is any express
agreement or commitment, however denominated, not to enforce a patent
(such as an express permission to practice a patent or covenant not to
sue for patent infringement).  To "grant" such a patent license to a
party means to make such an agreement or commitment not to enforce a
patent against the party.

  If you convey a covered work, knowingly relying on a patent license,
and the Corresponding Source of the work is not available for anyone
to copy, free of charge and under the terms of this License, through a
publicly available network server or other readily accessible means,
then you must either (1) cause the Corresponding Source to be so
available, or (2) arrange to deprive yourself of the benefit of the
patent license for this particular work, or (3) arrange, in a manner
consistent with the requirements of this License, to extend the patent
license to downstream recipients.  "Knowingly relying" means you have
actual knowledge that, but for the patent license, your conveying the
covered work in a country, or your recipient's use of the covered work
in a country, would infringe one or more identifiable patents in that
country that you have reason to believe are valid.

  If, pursuant to or in connection with a single transaction or
arrangement, you convey, or propagate by procuring conveyance of, a
covered work, and grant a patent license to some of the parties
receiving the covered work authorizing them to use, propagate, modify
or convey a specific copy of the covered work, then the patent license
you grant is automatically extended to all recipients of the covered
work and works based on it.

  A patent license is "discriminatory" if it does not include within
the scope of its coverage, prohibits the exercise of, or is
conditioned on the non-exercise of one or more of the rights that are
specifically granted under this License.  You may not convey a covered
work if you are a party to an arrangement with a third party that is
in the business of distributing software, under which you make payment
to the third party based on the extent of your activity of conveying
the work, and under which the third party grants, to any of the
parties who would receive the covered work from you, a discriminatory
patent license (a) in connection with copies of the covered work
conveyed by you (or copies made from those copies), or (b) primarily
for and in connection with specific products or compilations that
contain the covered work, unless you entered into that arrangement,
or that patent license was granted, prior to 28 March 2007.

  Nothing in this License shall be construed as excluding or limiting
any implied license or other defenses to infringement that may
otherwise be available to you under applicable patent law.

  12. No Surrender of Others' Freedom.

  If conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License.  If you cannot convey a
covered work so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you may
not convey it at all.  For example, if you agree to terms that obligate you
to collect a royalty for further conveying from those to whom you convey
the Program, the only way you could satisfy both those terms and this
License would be to refrain entirely from conveying the Program.

  13. Remote Network Interaction; Use with the GNU General Public License.

  Notwithstanding any other provision of this License, if you modify the
Program, your modified version must prominently offer all users
interacting with it remotely through a computer network (if your version
supports such interaction) an opportunity to receive the Corresponding
Source of your version by providing access to the Corresponding Source
from a network server at no charge, through some standard or customary
means of facilitating copying of software.  This Corresponding Source
shall include the Corresponding Source for any work covered by version 3
of the GNU General Public License that is incorporated pursuant to the
following paragraph.

  Notwithstanding any other provision of this License, you have
permission to link or combine any covered work with a work licensed
under version 3 of the GNU General Public License into a single
combined work, and to convey the resulting work.  The terms of this
License will continue to apply to the part which is the covered work,
but the work with which it is combined will remain governed by version
3 of the GNU General Public License.

  14. Revised Versions of this License.

  The Free Software Foundation may publish revised and/or new versions of
the GNU Affero General Public License from time to time.  Such new versions
will be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.

  Each version is given a distinguishing version number.  If the
Program specifies that a certain numbered version of the GNU Affero General
Public License "or any later version" applies to it, you have the
option of following the terms and conditions either of that numbered
version or of any later version published by the Free Software
Foundation.  If the Program does not specify a version number of the
GNU Affero General Public License, you may choose any version ever published
by the Free Software Foundation.

  If the Program specifies that a proxy can decide which future
versions of the GNU Affero General Public License can be used, that proxy's
public statement of acceptance of a version permanently authorizes you
to choose that version for the Program.

  Later license versions may give you additional or different
permissions.  However, no additional obligations are imposed on any
author or copyright holder as a result of your choosing to follow a
later version.

  15. Disclaimer of Warranty.

  THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
APPLICABLE LAW.  EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
IS WITH YOU.  SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.

  16. Limitation of Liability.

  IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
SUCH DAMAGES.

  17. Interpretation of Sections 15 and 16.

  If the disclaimer of warranty and limitation of liability provided
above cannot be given local legal effect according to their terms,
reviewing courts shall apply local law that most closely approximates
an absolute waiver of all civil liability in connection with the
Program, unless a warranty or assumption of liability accompanies a
copy of the Program in return for a fee.

                     END OF TERMS AND CONDITIONS

            How to Apply These Terms to Your New Programs

  If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.

  To do so, attach the following notices to the program.  It is safest
to attach them to the start of each source file to most effectively
state the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.

    <one line to give the program's name and a brief idea of what it does.>
    Copyright (C) <year>  <name of author>

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU Affero General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU Affero General Public License for more details.

    You should have received a copy of the GNU Affero General Public License
    along with this program.  If not, see <https://www.gnu.org/licenses/>.

Also add information on how to contact you by electronic and paper mail.

  If your software can interact with users remotely through a computer
network, you should also make sure that it provides a way for users to
get its source.  For example, if your program is a web application, its
interface could display a "Source" link that leads users to an archive
of the code.  There are many ways you could offer source, and different
solutions will be better for different programs; see section 13 for the
specific requirements.

  You should also get your employer (if you work as a programmer) or school,
if any, to sign a "copyright disclaimer" for the program, if necessary.
For more information on this, and how to apply and follow the GNU AGPL, see
<https://www.gnu.org/licenses/>.


================================================
FILE: PROJECT_STRUCTURE.md
================================================
# PandaWiki 项目结构文档

## 项目概述

PandaWiki 是一个由 AI 大模型驱动的开源知识库搭建系统。该项目采用前后端分离的架构,包含后端服务、前端管理界面、前端用户界面以及 SDK。

## 根目录结构

```
/workspace/
├── .github/              # GitHub 相关配置 (如 workflows, issue templates)
├── backend/              # 后端服务代码 (Go 语言)
├── images/               # 项目相关的图片资源 (如 README 中使用的图片)
├── sdk/                  # 软件开发工具包 (SDK)
├── web/                  # 前端代码 (Node.js/React)
├── .gitattributes        # Git 属性配置
├── .gitignore            # Git 忽略文件配置
├── .gitmodules           # Git 子模块配置
├── CODE_OF_CONDUCT.md    # 行为准则
├── CONTRIBUTING.md       # 贡献指南
├── LICENSE               # 许可证 (AGPL-3.0)
├── README.md             # 项目介绍和使用指南
└── SECURITY.md           # 安全策略
```

## 后端 (backend/) 结构

后端服务使用 Go 语言编写,主要负责 API 提供、业务逻辑处理、数据存储等。

```
/workspace/backend/
├── api/                  # API 定义和接口实现
├── apm/                  # 应用性能管理 (APM) 相关代码
├── cmd/                  # 应用程序入口点 (main 函数)
├── config/               # 配置文件解析和管理
├── consts/               # 常量定义
├── docs/                 # 项目内部文档
├── domain/               # 领域模型和核心业务逻辑
├── handler/              # HTTP 请求处理器
├── log/                  # 日志管理
├── middleware/           # 中间件 (如认证、日志记录)
├── migration/            # 数据库迁移脚本
├── mq/                   # 消息队列相关代码
├── pkg/                  # 公共包和工具库
├── pro/                  # 专业版功能相关代码
├── repo/                 # 数据访问层 (Repository)
├── server/               # 服务器初始化和启动逻辑
├── setup/                # 安装和初始化相关代码
├── store/                # 存储层抽象和实现
├── telemetry/            # 遥测和监控相关代码
├── usecase/              # 用例层 (业务逻辑的具体实现)
├── utils/                # 工具函数
├── .dockerignore         # Docker 构建忽略文件
├── .golangci.toml        # Go 语言 lint 工具配置
├── cSpell.json           # 拼写检查配置
├── Dockerfile.api        # API 服务的 Dockerfile
├── Dockerfile.api.pro    # 专业版 API 服务的 Dockerfile
├── Dockerfile.consumer   # 消费者服务的 Dockerfile
├── Dockerfile.consumer.pro # 专业版消费者服务的 Dockerfile
├── go.mod                # Go 模块依赖管理
├── go.sum                # Go 模块依赖校验
├── Makefile              # 构建脚本
├── pro_imports.go        # 专业版功能导入
└── project-words.txt     # 项目特定词汇列表 (用于拼写检查)
```

## 前端 (web/) 结构

前端使用 Node.js 和 React 构建,采用 monorepo 结构管理多个应用。

```
/workspace/web/
├── .husky/               # Git hooks 配置
├── admin/                # 管理后台前端代码
├── app/                  # 用户端 Wiki 网站前端代码
├── packages/             # 共享的组件库和工具包
├── .gitignore            # Git 忽略文件配置
├── .prettierignore       # Prettier 格式化忽略文件
├── package.json          # Node.js 项目配置
├── pnpm-lock.yaml        # pnpm 依赖锁定文件
├── pnpm-workspace.yaml   # pnpm 工作区配置
└── prettier.config.js    # Prettier 代码格式化配置
```

## SDK (sdk/) 结构

SDK 提供了与 PandaWiki 系统交互的工具包。

```
/workspace/sdk/
└── rag/                  # RAG (Retrieval-Augmented Generation) 相关 SDK
```

================================================
FILE: README.md
================================================
<p align="center">
  <img src="/images/banner.png" width="400" />
</p>

<p align="center">
  <a target="_blank" href="https://ly.safepoint.cloud/Br48PoX">📖 官方网站</a> &nbsp; | &nbsp;
  <a target="_blank" href="/images/wechat.png">🙋‍♂️ 微信交流群</a>
</p>

## 👋 项目介绍

PandaWiki 是一款 AI 大模型驱动的**开源知识库搭建系统**,帮助你快速构建智能化的 **产品文档、技术文档、FAQ、博客系统**,借助大模型的力量为你提供 **AI 创作、AI 问答、AI 搜索** 等能力。

<p align="center">
  <img src="/images/setup.png" width="800" />
</p>

## ⚡️ 界面展示

| PandaWiki 控制台                                 | Wiki 网站前台                                    |
| ------------------------------------------------ | ------------------------------------------------ |
| <img src="/images/screenshot-1.png" width=370 /> | <img src="/images/screenshot-2.png" width=370 /> |
| <img src="/images/screenshot-3.png" width=370 /> | <img src="/images/screenshot-4.png" width=370 /> |

## 🔥 功能与特色

- AI 驱动智能化:AI 辅助创作、AI 辅助问答、AI 辅助搜索。
- 强大的富文本编辑能力:兼容 Markdown 和 HTML,支持导出为 word、pdf、markdown 等多种格式。
- 轻松与第三方应用进行集成:支持做成网页挂件挂在其他网站上,支持做成钉钉、飞书、企业微信等聊天机器人。
- 通过第三方来源导入内容:根据网页 URL 导入、通过网站 Sitemap 导入、通过 RSS 订阅、通过离线文件导入等。

## 🚀 上手指南

### 安装 PandaWiki

你需要一台支持 Docker 20.x 以上版本的 Linux 系统来安装 PandaWiki。

使用 root 权限登录你的服务器,然后执行以下命令。

```bash
bash -c "$(curl -fsSLk https://release.baizhi.cloud/panda-wiki/manager.sh)"
```

根据命令提示的选项进行安装,命令执行过程将会持续几分钟,请耐心等待。

> 关于安装与部署的更多细节请参考 [安装 PandaWiki](https://pandawiki.docs.baizhi.cloud/node/01971602-bb4e-7c90-99df-6d3c38cfd6d5)。

### 登录 PandaWiki

在上一步中,安装命令执行结束后,你的终端会输出以下内容。

```
SUCCESS  控制台信息:
SUCCESS    访问地址(内网): http://*.*.*.*:2443
SUCCESS    访问地址(外网): http://*.*.*.*:2443
SUCCESS    用户名: admin
SUCCESS    密码: **********************
```

使用浏览器打开上述内容中的 “访问地址”,你将看到 PandaWiki 的控制台登录入口,使用上述内容中的 “用户名” 和 “密码” 登录即可。

### 配置 AI 模型

> PandaWiki 是由 AI 大模型驱动的 Wiki 系统,在未配置大模型的情况下 AI 创作、AI 问答、AI 搜索 等功能无法正常使用。
> 
首次登录时会提示需要先配置 AI 模型,可自行选择一键配置或手动配置。

<div align="center">
  <img src="/images/model-config-1.png" width="800" />
  <p><em>一键自动配置 AI 模型</em></p>

  <img src="/images/model-config-2.png" width="800" />
  <p><em>手动自定义配置 AI 模型</em></p>
</div>



> 推荐使用 [百智云模型广场](https://baizhi.cloud/) 快速接入 AI 模型,注册即可获赠 5 元的模型使用额度。
> 关于大模型的更多配置细节请参考 [接入 AI 模型](https://pandawiki.docs.baizhi.cloud/node/01971616-811c-70e1-82d9-706a202b8498)。

### 创建知识库

“知识库” 是一组文档的集合,PandaWiki 将会根据知识库中的文档,为不同的知识库分别创建 “Wiki 网站”。
<img src="/images/createkb.png" width="800" />

### 💪 开始使用

如果你顺利完成了以上步骤,那么恭喜你,属于你的 PandaWiki 搭建成功,你可以:

- 访问 **控制台** 来管理你的知识库并上传文档等待学习成功
- 访问 **Wiki 网站** 使用知识库并测试AI问答效果
<img src="/images/AI-QA.png" width="700" />

### 💬 遇到问题

如在使用产品过程中遇到问题,可通过以下方式获取帮助:
- 📘查阅官方文档:[常见问题](https://pandawiki.docs.baizhi.cloud/node/019b4952-4ed3-7514-ba57-c93a8ca13608),更多内容请参考文档目录。
- 🤖不想翻文档?试试 [AI 问答](https://pandawiki.docs.baizhi.cloud/node/0197160c-782c-74ad-a4b7-857dae148f84),快速获取答案。
- 🤝加入社区:扫码加入下方企业微信群,与更多用户及官方人员交流经验、获得帮助。


## 社区交流

欢迎加入我们的微信群进行交流。

<img src="/images/wechat.png" width="300" />

## 🙋‍♂️ 贡献

欢迎提交 [Pull Request](https://github.com/chaitin/PandaWiki/pulls) 或创建 [Issue](https://github.com/chaitin/PandaWiki/issues) 来帮助改进项目。

## 📝 许可证

本项目采用 GNU Affero General Public License v3.0 (AGPL-3.0) 许可证。这意味着:

- 你可以自由使用、修改和分发本软件
- 你必须以相同的许可证开源你的修改
- 如果你通过网络提供服务,也必须开源你的代码
- 商业使用需要遵守相同的开源要求


## Star History

[![Star History Chart](https://api.star-history.com/svg?repos=chaitin/PandaWiki&type=Date)](https://www.star-history.com/#chaitin/PandaWiki&Date)


================================================
FILE: SECURITY.md
================================================
# 安全策略

## 受支持的版本

PandaWiki 采用 rolling release 的方式进行发行,非最新版 release 中存在的安全问题不在本计划的考虑范围之内。

## 报告安全漏洞
说明如何报告安全问题。建议使用私下报告方式(如 GitHub Security Advisory 或专用邮箱):

1. **私下报告**:请通过 [GitHub Security Advisory](https://github.com/chaitin/PandaWiki/security/advisories) 提交漏洞。
2. 我们会在 **3 个工作日内**确认收到,并在 **7 天内**提供修复时间表。
3. 修复完成后,我们会发布安全公告并感谢报告者(除非您希望匿名)。


================================================
FILE: backend/.dockerignore
================================================
deploy


================================================
FILE: backend/.golangci.toml
================================================
version = "2"

linters.default = "standard"

[[linters.exclusions.rules]]
linters = [ "errcheck" ]
source = "^\\s*defer\\s+"

[formatters]
enable = ["gofmt", "goimports"]

================================================
FILE: backend/Dockerfile.api
================================================
FROM --platform=$BUILDPLATFORM golang:1.24.3-alpine AS builder

WORKDIR /src
ENV CGO_ENABLED=0

COPY go.mod go.sum ./
RUN --mount=type=cache,target=/go/pkg/mod \
    go mod download

COPY . .

ARG TARGETOS TARGETARCH VERSION
RUN --mount=type=cache,target=/root/.cache/go-build \
    --mount=type=cache,target=/go/pkg/mod \
    GOOS=$TARGETOS GOARCH=$TARGETARCH go build -ldflags "-s -w -extldflags '-static' -X github.com/chaitin/panda-wiki/telemetry.Version=${VERSION}" -o /build/panda-wiki-api cmd/api/main.go cmd/api/wire_gen.go \
    && GOOS=$TARGETOS GOARCH=$TARGETARCH go build -ldflags "-s -w -extldflags '-static' -X github.com/chaitin/panda-wiki/telemetry.Version=${VERSION}" -o /build/panda-wiki-migrate cmd/migrate/main.go cmd/migrate/wire_gen.go 
FROM alpine:3.21 AS api

RUN apk update \
    && apk upgrade \
    && apk add --no-cache ca-certificates tzdata \
    && update-ca-certificates 2>/dev/null || true \
    && rm -rf /var/cache/apk/*

WORKDIR /app

COPY --from=builder /build/panda-wiki-api /app/panda-wiki-api
COPY --from=builder /build/panda-wiki-migrate /app/panda-wiki-migrate
COPY --from=builder /src/store/pg/migration /app/migration

CMD ["sh", "-c", "/app/panda-wiki-migrate && /app/panda-wiki-api"]


================================================
FILE: backend/Dockerfile.api.pro
================================================
FROM --platform=$BUILDPLATFORM golang:1.24.3-alpine AS builder

WORKDIR /src
ENV CGO_ENABLED=0

COPY go.mod go.sum ./
RUN --mount=type=cache,target=/go/pkg/mod \
    go mod download

COPY . .

ARG TARGETOS TARGETARCH VERSION
RUN --mount=type=cache,target=/root/.cache/go-build \
    --mount=type=cache,target=/go/pkg/mod \
    GOOS=$TARGETOS GOARCH=$TARGETARCH go build -ldflags "-s -w -extldflags '-static' -X github.com/chaitin/panda-wiki/telemetry.Version=${VERSION}" -o /build/panda-wiki-api pro/cmd/api_pro/main.go pro/cmd/api_pro/wire_gen.go \
    && GOOS=$TARGETOS GOARCH=$TARGETARCH go build -ldflags "-s -w -extldflags '-static' -X github.com/chaitin/panda-wiki/telemetry.Version=${VERSION}" -o /build/panda-wiki-migrate cmd/migrate/main.go cmd/migrate/wire_gen.go

FROM alpine:3.21 AS api

RUN apk update \
    && apk upgrade \
    && apk add --no-cache ca-certificates tzdata \
    && update-ca-certificates 2>/dev/null || true \
    && rm -rf /var/cache/apk/*

WORKDIR /app

COPY --from=builder /build/panda-wiki-api /app/panda-wiki-api
COPY --from=builder /build/panda-wiki-migrate /app/panda-wiki-migrate
COPY --from=builder /src/store/pg/migration /app/migration

CMD ["sh", "-c", "/app/panda-wiki-migrate && /app/panda-wiki-api"]


================================================
FILE: backend/Dockerfile.consumer
================================================
FROM --platform=$BUILDPLATFORM golang:1.24.3-alpine AS builder

WORKDIR /src
ENV CGO_ENABLED=0

COPY go.mod go.sum ./
RUN --mount=type=cache,target=/go/pkg/mod \
    go mod download

COPY . .

ARG TARGETOS TARGETARCH
RUN --mount=type=cache,target=/root/.cache/go-build \
    --mount=type=cache,target=/go/pkg/mod \
    GOOS=$TARGETOS GOARCH=$TARGETARCH go build -ldflags "-s -w -extldflags '-static'" -o /build/panda-wiki-consumer cmd/consumer/main.go cmd/consumer/wire_gen.go

FROM alpine:3.21 AS consumer

RUN apk update \
    && apk upgrade \
    && apk add --no-cache ca-certificates tzdata \
    && update-ca-certificates 2>/dev/null || true \
    && rm -rf /var/cache/apk/*

WORKDIR /app
COPY --from=builder /build/panda-wiki-consumer /app/panda-wiki-consumer
COPY --from=builder /src/store/pg/migration /app/migration

CMD ["./panda-wiki-consumer"]


================================================
FILE: backend/Dockerfile.consumer.pro
================================================
FROM --platform=$BUILDPLATFORM golang:1.24.3-alpine AS builder

WORKDIR /src
ENV CGO_ENABLED=0

COPY go.mod go.sum ./
RUN --mount=type=cache,target=/go/pkg/mod \
    go mod download

COPY . .

ARG TARGETOS TARGETARCH
RUN --mount=type=cache,target=/root/.cache/go-build \
    --mount=type=cache,target=/go/pkg/mod \
    GOOS=$TARGETOS GOARCH=$TARGETARCH go build -ldflags "-s -w -extldflags '-static'" -o /build/panda-wiki-consumer pro/cmd/consumer_pro/main.go pro/cmd/consumer_pro/wire_gen.go

FROM alpine:3.21 AS consumer

RUN apk update \
    && apk upgrade \
    && apk add --no-cache ca-certificates tzdata \
    && update-ca-certificates 2>/dev/null || true \
    && rm -rf /var/cache/apk/*

WORKDIR /app
COPY --from=builder /build/panda-wiki-consumer /app/panda-wiki-consumer
COPY --from=builder /src/store/pg/migration /app/migration

CMD ["./panda-wiki-consumer"]


================================================
FILE: backend/Makefile
================================================
generate:
	swag fmt --dir handler && swag init --exclude pro -g cmd/api/main.go --pd \
	&& wire cmd/api/wire.go \
	&& wire cmd/consumer/wire.go \
	&& wire cmd/migrate/wire.go

generate_pro:
	wire cmd/migrate/wire.go \
	&& cd pro \
	&& swag fmt --dir handler && swag init --instanceName pro -g cmd/api_pro/main.go --pd \
	&& wire cmd/api_pro/wire.go \
	&& wire cmd/consumer_pro/wire.go

lint:generate generate_pro
	go mod tidy && golangci-lint run

SEQ_NAME=init
migrate_sql:
	migrate create -ext sql -dir store/pg/migration -seq ${SEQ_NAME}

image:
	docker buildx build \
	  --platform ${PLATFORM} \
	  --tag ${IMAGE_NAME} \
	  --build-arg VERSION=${VERSION} \
	  --output ${OUTPUT} \
	  --progress plain \
	  --file ${DOCKERFILE} \
	  .

TAG=$(shell git describe --tags 2>/dev/null || echo "latest")
push-prod-images:
	make image PLATFORM=linux/amd64,linux/arm64 DOCKERFILE=Dockerfile.api IMAGE_NAME=chaitin-registry.cn-hangzhou.cr.aliyuncs.com/chaitin/panda-wiki-api:${TAG} OUTPUT=type=registry VERSION=${TAG} \
	&& make image PLATFORM=linux/amd64,linux/arm64 DOCKERFILE=Dockerfile.consumer IMAGE_NAME=chaitin-registry.cn-hangzhou.cr.aliyuncs.com/chaitin/panda-wiki-consumer:${TAG} OUTPUT=type=registry VERSION=${TAG}

COMMIT_HASH=$(shell git rev-parse --short HEAD)
LOCAL_PLATFORM=linux/$(shell uname -m)
#LOCAL_PLATFORM=linux/amd64
dev:generate
	make image PLATFORM=${LOCAL_PLATFORM} DOCKERFILE=Dockerfile.api IMAGE_NAME=chaitin-registry.cn-hangzhou.cr.aliyuncs.com/chaitin/panda-wiki-api:latest OUTPUT=type=docker VERSION=${COMMIT_HASH} \
	&& make image PLATFORM=${LOCAL_PLATFORM} DOCKERFILE=Dockerfile.consumer IMAGE_NAME=chaitin-registry.cn-hangzhou.cr.aliyuncs.com/chaitin/panda-wiki-consumer:latest OUTPUT=type=docker VERSION=${COMMIT_HASH} \
	&& cd deploy && docker compose up -d

pro:generate_pro
	make image PLATFORM=${LOCAL_PLATFORM} DOCKERFILE=Dockerfile.api.pro IMAGE_NAME=chaitin-registry.cn-hangzhou.cr.aliyuncs.com/chaitin/panda-wiki-api:latest OUTPUT=type=docker VERSION=${COMMIT_HASH} \
	&& make image PLATFORM=${LOCAL_PLATFORM} DOCKERFILE=Dockerfile.consumer.pro IMAGE_NAME=chaitin-registry.cn-hangzhou.cr.aliyuncs.com/chaitin/panda-wiki-consumer:latest OUTPUT=type=docker VERSION=${COMMIT_HASH} \
	&& cd deploy && docker compose up -d

================================================
FILE: backend/api/auth/v1/auth.go
================================================
package v1

import (
	"time"

	"github.com/chaitin/panda-wiki/consts"
)

type AuthGetReq struct {
	KBID       string            `json:"kb_id,omitempty"  query:"kb_id"`
	SourceType consts.SourceType `query:"source_type"  json:"source_type" validate:"required,oneof=github"`
}

type AuthGetResp struct {
	ClientID     string            `json:"client_id"`
	ClientSecret string            `json:"client_secret"`
	Proxy        string            `json:"proxy"`
	SourceType   consts.SourceType `json:"source_type"`
	Auths        []AuthItem        `json:"auths"`
}

type AuthItem struct {
	ID            uint              `gorm:"primaryKey;column:id" json:"id,omitempty"`
	Username      string            `gorm:"column:username;not null" json:"username,omitempty"`
	AvatarUrl     string            `json:"avatar_url"`
	IP            string            `gorm:"column:ip;not null" json:"ip,omitempty"`
	SourceType    consts.SourceType `gorm:"column:source_type;not null" json:"source_type,omitempty"`
	LastLoginTime time.Time         `gorm:"column:last_login_time" json:"last_login_time,omitempty"`
	CreatedAt     time.Time         `gorm:"column:created_at;not null;default:now()" json:"created_at"`
}

type AuthSetReq struct {
	KBID         string            `json:"kb_id,omitempty"`
	SourceType   consts.SourceType `query:"source_type"  json:"source_type" validate:"required,oneof=github"`
	ClientID     string            `json:"client_id"`
	ClientSecret string            `json:"client_secret"`
	Proxy        string            `json:"proxy"`
}

type AuthSetResp struct{}

type AuthDeleteReq struct {
	ID   int64  `query:"id" json:"id"`
	KbID string `query:"kb_id" json:"kb_id"`
}

type AuthDeleteResp struct {
}


================================================
FILE: backend/api/conversation/v1/conversation.go
================================================
package v1

type GetConversationDetailReq struct {
	KbId string `query:"kb_id" json:"kb_id" validate:"required"`
	ID   string `query:"id" json:"id" validate:"required"`
}

type GetConversationDetailResp struct {
}

type GetMessageDetailReq struct {
	KbId string `query:"kb_id" json:"kb_id" validate:"required"`
	ID   string `query:"id" json:"id" validate:"required"`
}

type GetMessageDetailResp struct {
}


================================================
FILE: backend/api/crawler/v1/confluence.go
================================================
package v1

type ConfluenceParseReq struct {
	KbID string `json:"kb_id" validate:"required"`
}

type ConfluenceParseItem struct {
	ID    string `json:"id"`
	Title string `json:"title"`
	URL   string `json:"url"`
}

type ConfluenceParseResp struct {
	ID   string                `json:"id"`
	Docs []ConfluenceParseItem `json:"docs"`
}

type ConfluenceScrapeReq struct {
	KbID  string `json:"kb_id" validate:"required"`
	ID    string `json:"id" validate:"required"`
	DocID string `json:"doc_id" validate:"required"`
}

type ConfluenceScrapeResp struct {
	Content string `json:"content"`
}


================================================
FILE: backend/api/crawler/v1/crawler.go
================================================
package v1

import (
	"github.com/chaitin/panda-wiki/consts"
	"github.com/chaitin/panda-wiki/pkg/anydoc"
)

type CrawlerParseReq struct {
	Key             string                 `json:"key"`
	KbID            string                 `json:"kb_id" validate:"required"`
	CrawlerSource   consts.CrawlerSource   `json:"crawler_source" validate:"required"`
	Filename        string                 `json:"filename"`
	FeishuSetting   anydoc.FeishuSetting   `json:"feishu_setting"`
	DingtalkSetting anydoc.DingtalkSetting `json:"dingtalk_setting"`
}

type CrawlerParseResp struct {
	ID   string       `json:"id"`
	Docs anydoc.Child `json:"docs"`
}

type CrawlerExportReq struct {
	KbID     string `json:"kb_id" validate:"required"`
	ID       string `json:"id" validate:"required"`
	DocID    string `json:"doc_id" validate:"required"`
	SpaceId  string `json:"space_id"`
	FileType string `json:"file_type"`
}

type CrawlerExportResp struct {
	TaskId string `json:"task_id"`
}

type CrawlerResultReq struct {
	TaskId string `json:"task_id"  query:"task_id" validate:"required"`
}

type CrawlerResultResp struct {
	Status  consts.CrawlerStatus `json:"status" validate:"required"`
	Content string               `json:"content"`
}

type CrawlerResultsReq struct {
	TaskIds []string `json:"task_ids"  validate:"required"`
}

type CrawlerResultsResp struct {
	Status consts.CrawlerStatus `json:"status"`
	List   []CrawlerResultItem  `json:"list"`
}
type CrawlerResultItem struct {
	TaskId  string               `json:"task_id"`
	Status  consts.CrawlerStatus `json:"status"`
	Content string               `json:"content"`
}


================================================
FILE: backend/api/crawler/v1/epub.go
================================================
package v1

type EpubParseReq struct {
	KbID     string `json:"kb_id" validate:"required"`
	Filename string `json:"filename" validate:"required"`
	Key      string `json:"key" validate:"required"`
}

type EpubParseResp struct {
	TaskID string `json:"task_id"`
}


================================================
FILE: backend/api/crawler/v1/feishu.go
================================================
package v1

type FeishuSpaceListReq struct {
	UserAccessToken string `json:"user_access_token" validate:"required"`
	AppID           string `json:"app_id" validate:"required"`
	AppSecret       string `json:"app_secret" validate:"required"`
}
type FeishuSpaceListResp struct {
	Name    string `json:"name"`
	SpaceId string `json:"space_id"`
}

type FeishuSearchWikiReq struct {
	UserAccessToken string `json:"user_access_token" validate:"required"`
	AppID           string `json:"app_id" validate:"required"`
	AppSecret       string `json:"app_secret" validate:"required"`
	SpaceId         string `json:"space_id"`
}

type FeishuSearchWikiResp struct {
	ID       string `json:"id" validate:"required"`
	DocId    string `json:"doc_id" validate:"required"`
	Title    string `json:"title"`
	FileType string `json:"file_type"`
	SpaceId  string `json:"space_id"`
}

type FeishuListCloudDocReq struct {
	UserAccessToken string `json:"user_access_token" validate:"required"`
	AppID           string `json:"app_id" validate:"required"`
	AppSecret       string `json:"app_secret" validate:"required"`
}

type FeishuListCloudDocResp struct {
	ID       string `json:"id" validate:"required"`
	DocId    string `json:"doc_id" validate:"required"`
	Title    string `json:"title"`
	FileType string `json:"file_type"`
	SpaceId  string `json:"space_id"`
}

type FeishuGetDocReq struct {
	KbID     string `json:"kb_id" validate:"required"`
	ID       string `json:"id" validate:"required"`
	DocId    string `json:"doc_id" validate:"required"`
	FileType string `json:"file_type"`
	SpaceId  string `json:"space_id"`
}

type FeishuGetDocResp struct {
	Content string `json:"content"`
}


================================================
FILE: backend/api/crawler/v1/mindoc.go
================================================
package v1

type MindocParseReq struct {
	KbID string `json:"kb_id" validate:"required"`
}

type MindocParseItem struct {
	ID    string `json:"id"`
	Title string `json:"title"`
	URL   string `json:"url"`
}

type MindocParseResp struct {
	ID   string            `json:"id"`
	Docs []MindocParseItem `json:"docs"`
}

type MindocScrapeReq struct {
	KbID  string `json:"kb_id" validate:"required"`
	ID    string `json:"id" validate:"required"`
	DocID string `json:"doc_id" validate:"required"`
}

type MindocScrapeResp struct {
	Content string `json:"content"`
}


================================================
FILE: backend/api/crawler/v1/notion.go
================================================
package v1

type NotionParseReq struct {
	Integration string `json:"integration" validate:"required"`
}
type NotionParseResp struct {
	ID   string            `json:"id"`
	Docs []NotionParseItem `json:"docs"`
}

type NotionParseItem struct {
	ID    string `json:"id"`
	Title string `json:"title"`
}

type NotionScrapeReq struct {
	KbID  string `json:"kb_id" validate:"required"`
	ID    string `json:"id" validate:"required"`
	DocId string `json:"doc_id" validate:"required"`
}

type NotionScrapeResp struct {
	Content string `json:"content"`
}


================================================
FILE: backend/api/crawler/v1/siyuan.go
================================================
package v1

type SiyuanParseReq struct {
	KbID string `json:"kb_id" validate:"required"`
}

type SiyuanParseItem struct {
	ID    string `json:"id"`
	Title string `json:"title"`
	URL   string `json:"url"`
}

type SiyuanParseResp struct {
	ID   string            `json:"id"`
	Docs []SiyuanParseItem `json:"docs"`
}

type SiyuanScrapeReq struct {
	KbID  string `json:"kb_id" validate:"required"`
	ID    string `json:"id" validate:"required"`
	DocID string `json:"doc_id" validate:"required"`
}

type SiyuanScrapeResp struct {
	Content string `json:"content"`
}


================================================
FILE: backend/api/crawler/v1/wikijs.go
================================================
package v1

type WikijsParseReq struct {
	KbID string `json:"kb_id" validate:"required"`
}

type WikijsParseItem struct {
	ID    string `json:"id"`
	Title string `json:"title"`
}

type WikijsParseResp struct {
	ID   string            `json:"id"`
	Docs []WikijsParseItem `json:"docs"`
}

type WikijsScrapeReq struct {
	KbID  string `json:"kb_id" validate:"required"`
	ID    string `json:"id" validate:"required"`
	DocID string `json:"doc_id" validate:"required"`
}

type WikijsScrapeResp struct {
	Content string `json:"content"`
}


================================================
FILE: backend/api/crawler/v1/yuque.go
================================================
package v1

type YuqueParseReq struct {
	KbID     string `json:"kb_id" validate:"required"`
	Filename string `json:"filename" validate:"required"`
	Key      string `json:"key" validate:"required"`
}

type YuqueParseResp struct {
	List []YuqueParseItem `json:"list"`
}

type YuqueParseItem struct {
	TaskID string `json:"task_id"`
	Title  string `json:"title"`
}


================================================
FILE: backend/api/kb/v1/kb.go
================================================
package v1

import (
	"github.com/chaitin/panda-wiki/consts"
)

type KBUserListReq struct {
	KBId string `json:"kb_id" query:"kb_id"`
}

type KBUserListItemResp struct {
	ID      string                  `json:"id"`
	Account string                  `json:"account"`
	Role    consts.UserRole         `json:"role"`
	Perm    consts.UserKBPermission `json:"perms"`
}

type KBUserInviteReq struct {
	KBId   string                  `json:"kb_id" validate:"required"`
	UserId string                  `json:"user_id" validate:"required"`
	Perm   consts.UserKBPermission `json:"perm" validate:"required,oneof=full_control doc_manage data_operate"`
}

type KBUserInviteResp struct {
}

type KBUserUpdateReq struct {
	KBId   string                  `json:"kb_id" validate:"required"`
	UserId string                  `json:"user_id" validate:"required"`
	Perm   consts.UserKBPermission `json:"perm" validate:"required,oneof=full_control doc_manage data_operate"`
}

type KBUserUpdateResp struct {
}

type KBUserDeleteReq struct {
	KBId   string `json:"kb_id" query:"kb_id" validate:"required"`
	UserId string `json:"user_id" query:"user_id" validate:"required"`
}

type KBUserDeleteResp struct {
}


================================================
FILE: backend/api/nav/v1/nav.go
================================================
package v1

import "time"

type NavListReq struct {
	KbId string `json:"kb_id" query:"kb_id" validate:"required"`
}

type NavAddReq struct {
	KbId     string   `json:"kb_id" query:"kb_id" validate:"required"`
	Name     string   `json:"name" validate:"required"`
	Position *float64 `json:"position"`
}

type NavUpdateReq struct {
	KbId string `json:"kb_id" query:"kb_id" validate:"required"`
	ID   string `json:"id" validate:"required"`
	Name string `json:"name" validate:"required"`
}

type NavDeleteReq struct {
	KbId string `json:"kb_id" query:"kb_id" validate:"required"`
	ID   string `json:"id" query:"id" validate:"required"`
}

type NavMoveReq struct {
	KbId   string `json:"kb_id" validate:"required"`
	ID     string `json:"id" validate:"required"`
	PrevID string `json:"prev_id"`
	NextID string `json:"next_id"`
}

type NavListResp struct {
	ID        string    `json:"id"`
	Name      string    `json:"name"`
	Position  float64   `json:"position"`
	CreatedAt time.Time `json:"created_at"`
	UpdatedAt time.Time `json:"updated_at"`
}


================================================
FILE: backend/api/node/v1/node.go
================================================
package v1

import (
	"time"

	"github.com/chaitin/panda-wiki/domain"
)

type GetNodeDetailReq struct {
	KbId   string `query:"kb_id" json:"kb_id" validate:"required"`
	ID     string `query:"id" json:"id" validate:"required"`
	Format string `query:"format" json:"format"`
}

type NodeDetailResp struct {
	ID               string                 `json:"id"`
	KbID             string                 `json:"kb_id"`
	NavId            string                 `json:"nav_id"`
	Type             domain.NodeType        `json:"type"`
	Status           domain.NodeStatus      `json:"status"`
	Name             string                 `json:"name"`
	Content          string                 `json:"content"`
	Meta             domain.NodeMeta        `json:"meta"`
	ParentID         string                 `json:"parent_id"`
	CreatedAt        time.Time              `json:"created_at"`
	UpdatedAt        time.Time              `json:"updated_at"`
	Permissions      domain.NodePermissions `json:"permissions"`
	CreatorId        string                 `json:"creator_id"`
	EditorId         string                 `json:"editor_id"`
	PublisherId      string                 `json:"publisher_id" gorm:"-"`
	CreatorAccount   string                 `json:"creator_account"`
	EditorAccount    string                 `json:"editor_account"`
	PublisherAccount string                 `json:"publisher_account" gorm:"-"`
	PV               int64                  `json:"pv" gorm:"-"`
}

type NodePermissionReq struct {
	KbId string `query:"kb_id" json:"kb_id" validate:"required"`
	ID   string `query:"id" json:"id" validate:"required"`
}

type NodePermissionResp struct {
	ID               string                   `json:"id"`
	Permissions      domain.NodePermissions   `json:"permissions"`
	AnswerableGroups []domain.NodeGroupDetail `json:"answerable_groups"` // 可被问答
	VisitableGroups  []domain.NodeGroupDetail `json:"visitable_groups"`  // 可被访问
	VisibleGroups    []domain.NodeGroupDetail `json:"visible_groups"`    // 导航内可见
}

type NodePermissionEditReq struct {
	KbId             string                  `query:"kb_id" json:"kb_id" validate:"required"`
	IDs              []string                `query:"ids" json:"ids" validate:"required"`
	Permissions      *domain.NodePermissions `json:"permissions"`
	AnswerableGroups *[]int                  `json:"answerable_groups"` // 可被问答
	VisitableGroups  *[]int                  `json:"visitable_groups"`  // 可被访问
	VisibleGroups    *[]int                  `json:"visible_groups"`    // 导航内可见
}

type NodePermissionEditResp struct {
}

type NodeRestudyReq struct {
	NodeIds []string `json:"node_ids" validate:"required,min=1"`
	KbId    string   `json:"kb_id" validate:"required"`
}

type NodeRestudyResp struct {
}

type NodeStatsReq struct {
	KbId string `query:"kb_id" json:"kb_id" validate:"required"`
}

type NodeStatsResp struct {
	UnpublishedCount   int64 `json:"unpublished_count"`    // 未发布的文档数
	UnstudiedCount     int64 `json:"unstudied_count"`      // 未学习的文档数
	UnreleasedNavCount int64 `json:"unreleased_nav_count"` // 未发布目录数量
}

type NodeMoveNavReq struct {
	IDs   []string `json:"ids" query:"[]ids" validate:"required,min=1"`
	KbID  string   `json:"kb_id" validate:"required"`
	NavID string   `json:"nav_id" validate:"required"`
}

type NodeListGroupNavReq struct {
	KbId   string `json:"kb_id" query:"kb_id" validate:"required"`
	Search string `json:"search" query:"search"`
	Status string `json:"status" query:"status" validate:"omitempty,oneof=unpublished unstudied"`
}

type NodeListGroupNavResp struct {
	NavName    string                    `json:"nav_name"`
	NavID      string                    `json:"nav_id"`
	Position   float64                   `json:"position"`
	Count      int64                     `json:"count"`
	IsReleased bool                      `json:"is_released"`
	List       []domain.NodeListItemResp `json:"list"`
}


================================================
FILE: backend/api/openapi/v1/openapi.go
================================================
package v1

type GitHubCallbackReq struct {
	Code  string `json:"code" query:"code"`
	State string `json:"state" query:"state"`
}

type GitHubCallbackResp struct {
}


================================================
FILE: backend/api/share/v1/auth.go
================================================
package v1

import "github.com/chaitin/panda-wiki/consts"

type AuthLoginSimpleReq struct {
	Password string `json:"password" validate:"required"`
}

type AuthLoginSimpleResp struct {
}

type AuthGetReq struct {
}
type AuthGetResp struct {
	AuthType       consts.AuthType       `json:"auth_type"`
	SourceType     consts.SourceType     `json:"source_type"`
	LicenseEdition consts.LicenseEdition `json:"license_edition"`
}

type AuthGitHubReq struct {
	KbID        string `json:"kb_id"`
	RedirectUrl string `json:"redirect_url"`
}

type AuthGitHubResp struct {
	Url string `json:"url"`
}

type GitHubCallbackReq struct {
	Code  string `json:"code" query:"code"`
	State string `json:"state" query:"state"`
}

type GitHubCallbackResp struct {
}


================================================
FILE: backend/api/share/v1/common.go
================================================
package v1

type ShareFileUploadReq struct {
	KbId         string `json:"-"`
	File         string `form:"file"`
	CaptchaToken string `form:"captcha_token" json:"captcha_token" validate:"required"`
}

type FileUploadResp struct {
	Key string `json:"key"`
}

type ShareFileUploadUrlReq struct {
	KbId         string `json:"-"`
	Url          string `json:"url" validate:"required,url"`
	CaptchaToken string `json:"captcha_token" validate:"required"`
}

type ShareFileUploadUrlResp struct {
	Key string `json:"key"`
}


================================================
FILE: backend/api/share/v1/nav.go
================================================
package v1

type ShareNavListReq struct {
	KbId string `json:"kb_id" query:"kb_id" validate:"required"`
}


================================================
FILE: backend/api/share/v1/node.go
================================================
package v1

import (
	"time"

	"github.com/chaitin/panda-wiki/domain"
)

type ShareNodeDetailResp struct {
	ID               string                        `json:"id"`
	KbID             string                        `json:"kb_id"`
	Type             domain.NodeType               `json:"type"`
	Status           domain.NodeStatus             `json:"status"`
	Name             string                        `json:"name"`
	Content          string                        `json:"content"`
	Meta             domain.NodeMeta               `json:"meta"`
	ParentID         string                        `json:"parent_id"`
	CreatedAt        time.Time                     `json:"created_at"`
	UpdatedAt        time.Time                     `json:"updated_at"`
	Permissions      domain.NodePermissions        `json:"permissions"`
	CreatorId        string                        `json:"creator_id"`
	EditorId         string                        `json:"editor_id"`
	PublisherId      string                        `json:"publisher_id"`
	CreatorAccount   string                        `json:"creator_account"`
	EditorAccount    string                        `json:"editor_account"`
	PublisherAccount string                        `json:"publisher_account"`
	List             []*domain.ShareNodeDetailItem `json:"list" gorm:"-"`
	PV               int64                         `json:"pv" gorm:"-"`
}

type NodeListGroupNavResp struct {
	NavName  string                         `json:"nav_name"`
	NavID    string                         `json:"nav_id"`
	Position float64                        `json:"position"`
	Count    int64                          `json:"count"`
	List     []domain.ShareNodeListItemResp `json:"list"`
}


================================================
FILE: backend/api/share/v1/wechat.go
================================================
package v1

type WechatAppInfoResp struct {
	WeChatAppIsEnabled bool     `json:"wechat_app_is_enabled"`
	FeedbackEnable     bool     `json:"feedback_enable"`
	FeedbackType       []string `json:"feedback_type"`
	DisclaimerContent  string   `json:"disclaimer_content"`
}


================================================
FILE: backend/api/stat/v1/stat.go
================================================
package v1

import (
	"github.com/chaitin/panda-wiki/consts"
	"github.com/chaitin/panda-wiki/domain"
)

type StatInstantCountReq struct {
	KbID string `json:"kb_id" query:"kb_id" validate:"required"`
}

type StatInstantPagesReq struct {
	KbID string `json:"kb_id" query:"kb_id" validate:"required"`
}

type StatHotPagesReq struct {
	KbID string         `json:"kb_id" query:"kb_id" validate:"required"`
	Day  consts.StatDay `json:"day" query:"day" validate:"omitempty,oneof=1 7 30 90"`
}

type StatCountReq struct {
	Day  consts.StatDay `json:"day" query:"day" validate:"omitempty,oneof=1 7 30 90"`
	KbID string         `json:"kb_id" query:"kb_id" validate:"required"`
}

type StatCountResp struct {
	IPCount           int64 `json:"ip_count"`
	SessionCount      int64 `json:"session_count"`
	PageVisitCount    int64 `json:"page_visit_count"`
	ConversationCount int64 `json:"conversation_count"`
}

type StatRefererHostsReq struct {
	KbID string         `json:"kb_id" query:"kb_id" validate:"required"`
	Day  consts.StatDay `json:"day" query:"day" validate:"omitempty,oneof=1 7 30 90"`
}

type StatBrowsersReq struct {
	KbID string         `json:"kb_id" query:"kb_id" validate:"required"`
	Day  consts.StatDay `json:"day" query:"day" validate:"omitempty,oneof=1 7 30 90"`
}

type StatGeoCountReq struct {
	KbID string         `json:"kb_id" query:"kb_id" validate:"required"`
	Day  consts.StatDay `json:"day" query:"day" validate:"omitempty,oneof=1 7 30 90"`
}

type StatConversationDistributionReq struct {
	KbID string         `json:"kb_id" query:"kb_id" validate:"required"`
	Day  consts.StatDay `json:"day" query:"day" validate:"omitempty,oneof=1 7 30 90"`
}

type StatConversationDistributionResp struct {
	AppType domain.AppType `json:"app_type"`
	Count   int64          `json:"count"`
}


================================================
FILE: backend/api/user/v1/user.go
================================================
package v1

import (
	"time"

	"github.com/chaitin/panda-wiki/consts"
)

type CreateUserReq struct {
	Account  string          `json:"account" validate:"required"`
	Password string          `json:"password" validate:"required,min=8"`
	Role     consts.UserRole `json:"role" validate:"required,oneof=admin user"`
}

type CreateUserResp struct {
	ID string `json:"id"`
}

type UserInfoResp struct {
	ID         string          `json:"id"`
	Account    string          `json:"account"`
	Role       consts.UserRole `json:"role"`
	IsToken    bool            `json:"is_token"`
	LastAccess *time.Time      `json:"last_access,omitempty"`
	CreatedAt  time.Time       `json:"created_at"`
}

type UserListReq struct {
}

type UserListItemResp struct {
	ID         string          `json:"id"`
	Account    string          `json:"account"`
	Role       consts.UserRole `json:"role"`
	LastAccess *time.Time      `json:"last_access"`
	CreatedAt  *time.Time      `json:"created_at"`
}

type LoginReq struct {
	Account  string `json:"account" validate:"required"`
	Password string `json:"password" validate:"required"`
}

type LoginResp struct {
	Token string `json:"token"`
}

type UserListResp struct {
	Users []UserListItemResp `json:"users"`
}

type ResetPasswordReq struct {
	ID          string `json:"id" validate:"required"`
	NewPassword string `json:"new_password" validate:"required,min=8"`
}

type DeleteUserReq struct {
	UserID string `json:"user_id" query:"user_id" validate:"required"`
}


================================================
FILE: backend/apm/provider.go
================================================
package apm

import "github.com/google/wire"

var ProviderSet = wire.NewSet(NewTracer)


================================================
FILE: backend/apm/trace.go
================================================
package apm

import (
	"context"
	"log"
	"strings"

	"go.opentelemetry.io/otel"
	"go.opentelemetry.io/otel/attribute"
	"go.opentelemetry.io/otel/exporters/otlp/otlptrace"
	"go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc"
	"go.opentelemetry.io/otel/sdk/resource"
	sdktrace "go.opentelemetry.io/otel/sdk/trace"
	"google.golang.org/grpc/credentials"

	"github.com/chaitin/panda-wiki/config"
)

type Tracer struct {
	Shutdown func(context.Context) error
}

func NewTracer(config *config.Config) (*Tracer, error) {
	serviceName := config.GetString("apm.service_name")
	collectorURL := config.GetString("apm.otel_exporter_otlp_endpoint")
	insecure := config.GetString("apm.insecure")
	var secureOption otlptracegrpc.Option

	if strings.ToLower(insecure) == "false" || insecure == "0" || strings.ToLower(insecure) == "f" {
		secureOption = otlptracegrpc.WithTLSCredentials(credentials.NewClientTLSFromCert(nil, ""))
	} else {
		secureOption = otlptracegrpc.WithInsecure()
	}

	exporter, err := otlptrace.New(
		context.Background(),
		otlptracegrpc.NewClient(
			secureOption,
			otlptracegrpc.WithEndpoint(collectorURL),
		),
	)
	if err != nil {
		log.Fatalf("Failed to create exporter: %v", err)
	}
	resources, err := resource.New(
		context.Background(),
		resource.WithAttributes(
			attribute.String("service.name", serviceName),
			attribute.String("library.language", "go"),
		),
	)
	if err != nil {
		log.Fatalf("Could not set resources: %v", err)
	}

	otel.SetTracerProvider(
		sdktrace.NewTracerProvider(
			sdktrace.WithSampler(sdktrace.AlwaysSample()),
			sdktrace.WithBatcher(exporter),
			sdktrace.WithResource(resources),
		),
	)

	return &Tracer{Shutdown: exporter.Shutdown}, nil
}


================================================
FILE: backend/cSpell.json
================================================
{
    "$schema": "https://raw.githubusercontent.com/streetsidesoftware/cspell/main/cspell.schema.json",
    "version": "0.2",
    "dictionaryDefinitions": [
        {
            "name": "project-words",
            "path": "./project-words.txt",
            "addWords": true
        }
    ],
    "dictionaries": ["project-words"],
    "ignorePaths": ["node_modules", "/project-words.txt"],
}

================================================
FILE: backend/cmd/api/main.go
================================================
package main

import (
	"fmt"

	"github.com/chaitin/panda-wiki/setup"
)

// @title panda-wiki API
// @version 1.0
// @description panda-wiki API documentation
// @BasePath /
// @securityDefinitions.apikey	bearerAuth
// @in	header
// @name	Authorization
// @description	Type "Bearer" + a space + your token to authorize
func main() {
	app, err := createApp()
	if err != nil {
		panic(err)
	}
	if err := setup.CheckInitCert(); err != nil {
		panic(err)
	}
	port := app.Config.HTTP.Port
	app.Logger.Info(fmt.Sprintf("Starting server on port %d", port))
	app.HTTPServer.Echo.Logger.Fatal(app.HTTPServer.Echo.Start(fmt.Sprintf(":%d", port)))
}


================================================
FILE: backend/cmd/api/wire.go
================================================
//go:build wireinject

package main

import (
	"github.com/google/wire"

	"github.com/chaitin/panda-wiki/config"
	share "github.com/chaitin/panda-wiki/handler/share"
	v1 "github.com/chaitin/panda-wiki/handler/v1"
	"github.com/chaitin/panda-wiki/log"
	"github.com/chaitin/panda-wiki/server/http"
	"github.com/chaitin/panda-wiki/telemetry"
)

func createApp() (*App, error) {
	wire.Build(
		wire.Struct(new(App), "*"),
		wire.NewSet(
			config.ProviderSet,
			log.ProviderSet,
			telemetry.ProviderSet,

			http.ProviderSet,
			v1.ProviderSet,
			share.ProviderSet,
		),
	)
	return &App{}, nil
}

type App struct {
	HTTPServer    *http.HTTPServer
	Handlers      *v1.APIHandlers
	ShareHandlers *share.ShareHandler
	Config        *config.Config
	Logger        *log.Logger
	Telemetry     *telemetry.Client
}


================================================
FILE: backend/cmd/api/wire_gen.go
================================================
// Code generated by Wire. DO NOT EDIT.

//go:generate go run -mod=mod github.com/google/wire/cmd/wire
//go:build !wireinject
// +build !wireinject

package main

import (
	"github.com/chaitin/panda-wiki/config"
	"github.com/chaitin/panda-wiki/handler"
	"github.com/chaitin/panda-wiki/handler/share"
	"github.com/chaitin/panda-wiki/handler/v1"
	"github.com/chaitin/panda-wiki/log"
	"github.com/chaitin/panda-wiki/middleware"
	"github.com/chaitin/panda-wiki/mq"
	"github.com/chaitin/panda-wiki/pkg/captcha"
	cache2 "github.com/chaitin/panda-wiki/repo/cache"
	ipdb2 "github.com/chaitin/panda-wiki/repo/ipdb"
	mq2 "github.com/chaitin/panda-wiki/repo/mq"
	pg2 "github.com/chaitin/panda-wiki/repo/pg"
	"github.com/chaitin/panda-wiki/server/http"
	"github.com/chaitin/panda-wiki/store/cache"
	"github.com/chaitin/panda-wiki/store/ipdb"
	"github.com/chaitin/panda-wiki/store/pg"
	"github.com/chaitin/panda-wiki/store/rag"
	"github.com/chaitin/panda-wiki/store/s3"
	"github.com/chaitin/panda-wiki/telemetry"
	"github.com/chaitin/panda-wiki/usecase"
)

// Injectors from wire.go:

func createApp() (*App, error) {
	configConfig, err := config.NewConfig()
	if err != nil {
		return nil, err
	}
	logger := log.NewLogger(configConfig)
	readOnlyMiddleware := middleware.NewReadonlyMiddleware(logger)
	cacheCache, err := cache.NewCache(configConfig)
	if err != nil {
		return nil, err
	}
	sessionMiddleware, err := middleware.NewSessionMiddleware(logger, configConfig, cacheCache)
	if err != nil {
		return nil, err
	}
	echo := http.NewEcho(logger, configConfig, readOnlyMiddleware, sessionMiddleware)
	httpServer := &http.HTTPServer{
		Echo: echo,
	}
	db, err := pg.NewDB(configConfig)
	if err != nil {
		return nil, err
	}
	userAccessRepository := pg2.NewUserAccessRepository(db, logger)
	apiTokenRepo := pg2.NewAPITokenRepo(db, logger, cacheCache)
	authMiddleware, err := middleware.NewAuthMiddleware(configConfig, logger, userAccessRepository, apiTokenRepo)
	if err != nil {
		return nil, err
	}
	ragService, err := rag.NewRAGService(configConfig, logger)
	if err != nil {
		return nil, err
	}
	knowledgeBaseRepository := pg2.NewKnowledgeBaseRepository(db, configConfig, logger, ragService)
	nodeRepository := pg2.NewNodeRepository(db, logger)
	navRepository := pg2.NewNavRepository(db, logger)
	mqProducer, err := mq.NewMQProducer(configConfig, logger)
	if err != nil {
		return nil, err
	}
	ragRepository := mq2.NewRAGRepository(mqProducer)
	userRepository := pg2.NewUserRepository(db, logger)
	kbRepo := cache2.NewKBRepo(cacheCache)
	knowledgeBaseUsecase, err := usecase.NewKnowledgeBaseUsecase(knowledgeBaseRepository, nodeRepository, navRepository, ragRepository, userRepository, ragService, kbRepo, logger, configConfig)
	if err != nil {
		return nil, err
	}
	shareAuthMiddleware := middleware.NewShareAuthMiddleware(logger, knowledgeBaseUsecase)
	captchaCaptcha := captcha.NewCaptcha()
	baseHandler := handler.NewBaseHandler(echo, logger, configConfig, authMiddleware, shareAuthMiddleware, captchaCaptcha)
	userUsecase, err := usecase.NewUserUsecase(userRepository, logger, configConfig)
	if err != nil {
		return nil, err
	}
	userHandler := v1.NewUserHandler(echo, baseHandler, logger, userUsecase, authMiddleware, configConfig, cacheCache)
	conversationRepository := pg2.NewConversationRepository(db, logger)
	modelRepository := pg2.NewModelRepository(db, logger)
	promptRepo := pg2.NewPromptRepo(db, logger)
	llmUsecase := usecase.NewLLMUsecase(configConfig, ragService, conversationRepository, knowledgeBaseRepository, nodeRepository, modelRepository, promptRepo, logger)
	knowledgeBaseHandler := v1.NewKnowledgeBaseHandler(baseHandler, echo, knowledgeBaseUsecase, llmUsecase, authMiddleware, logger)
	appRepository := pg2.NewAppRepository(db, logger)
	minioClient, err := s3.NewMinioClient(configConfig)
	if err != nil {
		return nil, err
	}
	authRepo := pg2.NewAuthRepo(db, logger, cacheCache)
	systemSettingRepo := pg2.NewSystemSettingRepo(db, logger)
	modelUsecase := usecase.NewModelUsecase(modelRepository, nodeRepository, ragRepository, ragService, logger, configConfig, knowledgeBaseRepository, systemSettingRepo)
	nodeUsecase := usecase.NewNodeUsecase(nodeRepository, navRepository, appRepository, ragRepository, userRepository, knowledgeBaseRepository, llmUsecase, ragService, logger, minioClient, modelRepository, authRepo, modelUsecase)
	nodeHandler := v1.NewNodeHandler(baseHandler, echo, nodeUsecase, authMiddleware, logger)
	geoRepo := cache2.NewGeoCache(cacheCache, db, logger)
	ipdbIPDB, err := ipdb.NewIPDB(configConfig, logger)
	if err != nil {
		return nil, err
	}
	ipAddressRepo := ipdb2.NewIPAddressRepo(ipdbIPDB, logger)
	conversationUsecase := usecase.NewConversationUsecase(conversationRepository, nodeRepository, geoRepo, logger, ipAddressRepo, authRepo)
	blockWordRepo := pg2.NewBlockWordRepo(db, logger)
	chatUsecase, err := usecase.NewChatUsecase(llmUsecase, knowledgeBaseRepository, conversationUsecase, modelUsecase, appRepository, blockWordRepo, nodeRepository, authRepo, logger)
	if err != nil {
		return nil, err
	}
	appUsecase := usecase.NewAppUsecase(appRepository, authRepo, nodeRepository, knowledgeBaseRepository, nodeUsecase, logger, configConfig, chatUsecase, cacheCache)
	appHandler := v1.NewAppHandler(echo, baseHandler, logger, authMiddleware, appUsecase, modelUsecase, conversationUsecase, configConfig)
	fileUsecase := usecase.NewFileUsecase(logger, minioClient, configConfig, systemSettingRepo)
	fileHandler := v1.NewFileHandler(echo, baseHandler, logger, authMiddleware, minioClient, configConfig, fileUsecase)
	modelHandler := v1.NewModelHandler(echo, baseHandler, logger, authMiddleware, modelUsecase, llmUsecase)
	conversationHandler := v1.NewConversationHandler(echo, baseHandler, logger, authMiddleware, conversationUsecase)
	mqConsumer, err := mq.NewMQConsumer(configConfig, logger)
	if err != nil {
		return nil, err
	}
	crawlerUsecase, err := usecase.NewCrawlerUsecase(logger, mqConsumer, cacheCache)
	if err != nil {
		return nil, err
	}
	crawlerHandler := v1.NewCrawlerHandler(echo, baseHandler, authMiddleware, logger, configConfig, crawlerUsecase, fileUsecase)
	creationUsecase := usecase.NewCreationUsecase(logger, llmUsecase, modelUsecase)
	creationHandler := v1.NewCreationHandler(echo, baseHandler, logger, creationUsecase)
	statRepository := pg2.NewStatRepository(db, cacheCache)
	statUseCase := usecase.NewStatUseCase(statRepository, nodeRepository, conversationRepository, appRepository, ipAddressRepo, geoRepo, authRepo, knowledgeBaseRepository, logger)
	statHandler := v1.NewStatHandler(baseHandler, echo, statUseCase, logger, authMiddleware)
	commentRepository := pg2.NewCommentRepository(db, logger)
	commentUsecase := usecase.NewCommentUsecase(commentRepository, logger, nodeRepository, ipAddressRepo, authRepo)
	commentHandler := v1.NewCommentHandler(echo, baseHandler, logger, authMiddleware, commentUsecase)
	authUsecase, err := usecase.NewAuthUsecase(authRepo, logger, knowledgeBaseRepository, cacheCache)
	if err != nil {
		return nil, err
	}
	authV1Handler := v1.NewAuthV1Handler(echo, baseHandler, logger, authUsecase)
	navUsecase := usecase.NewNavUsecase(navRepository, nodeRepository, ragRepository, logger)
	navHandler := v1.NewNavHandler(baseHandler, echo, navUsecase, authMiddleware, logger)
	apiHandlers := &v1.APIHandlers{
		UserHandler:          userHandler,
		KnowledgeBaseHandler: knowledgeBaseHandler,
		NodeHandler:          nodeHandler,
		AppHandler:           appHandler,
		FileHandler:          fileHandler,
		ModelHandler:         modelHandler,
		ConversationHandler:  conversationHandler,
		CrawlerHandler:       crawlerHandler,
		CreationHandler:      creationHandler,
		StatHandler:          statHandler,
		CommentHandler:       commentHandler,
		AuthV1Handler:        authV1Handler,
		NavHandler:           navHandler,
	}
	shareNodeHandler := share.NewShareNodeHandler(baseHandler, echo, nodeUsecase, logger)
	shareNavHandler := share.NewShareNavHandler(baseHandler, echo, navUsecase, logger)
	shareAppHandler := share.NewShareAppHandler(echo, baseHandler, logger, appUsecase)
	shareChatHandler := share.NewShareChatHandler(echo, baseHandler, logger, appUsecase, chatUsecase, authUsecase, conversationUsecase, modelUsecase)
	sitemapUsecase := usecase.NewSitemapUsecase(nodeRepository, knowledgeBaseRepository, logger)
	shareSitemapHandler := share.NewShareSitemapHandler(echo, baseHandler, sitemapUsecase, appUsecase, logger)
	shareStatHandler := share.NewShareStatHandler(baseHandler, echo, statUseCase, logger)
	shareCommentHandler := share.NewShareCommentHandler(echo, baseHandler, logger, commentUsecase, appUsecase)
	shareAuthHandler := share.NewShareAuthHandler(echo, baseHandler, logger, knowledgeBaseUsecase, authUsecase)
	shareConversationHandler := share.NewShareConversationHandler(baseHandler, echo, conversationUsecase, logger)
	wechatRepository := pg2.NewWechatRepository(db, logger)
	wechatServiceUsecase := usecase.NewWechatUsecase(logger, appUsecase, chatUsecase, wechatRepository, authRepo)
	wecomUsecase := usecase.NewWecomUsecase(logger, cacheCache, appUsecase, chatUsecase, authRepo)
	wechatAppUsecase := usecase.NewWechatAppUsecase(logger, appUsecase, chatUsecase, wechatRepository, authRepo, appRepository)
	shareWechatHandler := share.NewShareWechatHandler(echo, baseHandler, logger, appUsecase, conversationUsecase, wechatServiceUsecase, wecomUsecase, wechatAppUsecase)
	shareCaptchaHandler := share.NewShareCaptchaHandler(baseHandler, echo, logger)
	openapiV1Handler := share.NewOpenapiV1Handler(echo, baseHandler, logger, authUsecase, appUsecase)
	shareCommonHandler := share.NewShareCommonHandler(echo, baseHandler, logger, fileUsecase)
	shareHandler := &share.ShareHandler{
		ShareNodeHandler:         shareNodeHandler,
		ShareNavHandler:          shareNavHandler,
		ShareAppHandler:          shareAppHandler,
		ShareChatHandler:         shareChatHandler,
		ShareSitemapHandler:      shareSitemapHandler,
		ShareStatHandler:         shareStatHandler,
		ShareCommentHandler:      shareCommentHandler,
		ShareAuthHandler:         shareAuthHandler,
		ShareConversationHandler: shareConversationHandler,
		ShareWechatHandler:       shareWechatHandler,
		ShareCaptchaHandler:      shareCaptchaHandler,
		OpenapiV1Handler:         openapiV1Handler,
		ShareCommonHandler:       shareCommonHandler,
	}
	mcpRepository := pg2.NewMCPRepository(db, logger)
	client, err := telemetry.NewClient(logger, knowledgeBaseRepository, modelUsecase, userUsecase, nodeRepository, conversationRepository, mcpRepository, configConfig)
	if err != nil {
		return nil, err
	}
	app := &App{
		HTTPServer:    httpServer,
		Handlers:      apiHandlers,
		ShareHandlers: shareHandler,
		Config:        configConfig,
		Logger:        logger,
		Telemetry:     client,
	}
	return app, nil
}

// wire.go:

type App struct {
	HTTPServer    *http.HTTPServer
	Handlers      *v1.APIHandlers
	ShareHandlers *share.ShareHandler
	Config        *config.Config
	Logger        *log.Logger
	Telemetry     *telemetry.Client
}


================================================
FILE: backend/cmd/consumer/main.go
================================================
package main

import (
	"context"
)

func main() {
	app, err := createApp()
	if err != nil {
		panic(err)
	}
	if err := app.MQConsumer.StartConsumerHandlers(context.Background()); err != nil {
		panic(err)
	}
	if err := app.MQConsumer.Close(); err != nil {
		panic(err)
	}
}


================================================
FILE: backend/cmd/consumer/wire.go
================================================
//go:build wireinject

package main

import (
	"github.com/google/wire"

	"github.com/chaitin/panda-wiki/config"
	handler "github.com/chaitin/panda-wiki/handler/mq"
	"github.com/chaitin/panda-wiki/log"
	"github.com/chaitin/panda-wiki/mq"
)

func createApp() (*App, error) {
	wire.Build(
		wire.Struct(new(App), "*"),
		wire.NewSet(
			config.ProviderSet,
			log.ProviderSet,
			handler.ProviderSet,
		),
	)
	return &App{}, nil
}

type App struct {
	MQConsumer      mq.MQConsumer
	Config          *config.Config
	MQHandlers      *handler.MQHandlers
	StatCronHandler *handler.CronHandler
}


================================================
FILE: backend/cmd/consumer/wire_gen.go
================================================
// Code generated by Wire. DO NOT EDIT.

//go:generate go run -mod=mod github.com/google/wire/cmd/wire
//go:build !wireinject
// +build !wireinject

package main

import (
	"github.com/chaitin/panda-wiki/config"
	mq3 "github.com/chaitin/panda-wiki/handler/mq"
	"github.com/chaitin/panda-wiki/log"
	"github.com/chaitin/panda-wiki/mq"
	cache2 "github.com/chaitin/panda-wiki/repo/cache"
	ipdb2 "github.com/chaitin/panda-wiki/repo/ipdb"
	mq2 "github.com/chaitin/panda-wiki/repo/mq"
	pg2 "github.com/chaitin/panda-wiki/repo/pg"
	"github.com/chaitin/panda-wiki/store/cache"
	"github.com/chaitin/panda-wiki/store/ipdb"
	"github.com/chaitin/panda-wiki/store/pg"
	"github.com/chaitin/panda-wiki/store/rag"
	"github.com/chaitin/panda-wiki/store/s3"
	"github.com/chaitin/panda-wiki/usecase"
)

// Injectors from wire.go:

func createApp() (*App, error) {
	configConfig, err := config.NewConfig()
	if err != nil {
		return nil, err
	}
	logger := log.NewLogger(configConfig)
	mqConsumer, err := mq.NewMQConsumer(configConfig, logger)
	if err != nil {
		return nil, err
	}
	ragService, err := rag.NewRAGService(configConfig, logger)
	if err != nil {
		return nil, err
	}
	db, err := pg.NewDB(configConfig)
	if err != nil {
		return nil, err
	}
	nodeRepository := pg2.NewNodeRepository(db, logger)
	knowledgeBaseRepository := pg2.NewKnowledgeBaseRepository(db, configConfig, logger, ragService)
	conversationRepository := pg2.NewConversationRepository(db, logger)
	modelRepository := pg2.NewModelRepository(db, logger)
	promptRepo := pg2.NewPromptRepo(db, logger)
	llmUsecase := usecase.NewLLMUsecase(configConfig, ragService, conversationRepository, knowledgeBaseRepository, nodeRepository, modelRepository, promptRepo, logger)
	mqProducer, err := mq.NewMQProducer(configConfig, logger)
	if err != nil {
		return nil, err
	}
	ragRepository := mq2.NewRAGRepository(mqProducer)
	systemSettingRepo := pg2.NewSystemSettingRepo(db, logger)
	modelUsecase := usecase.NewModelUsecase(modelRepository, nodeRepository, ragRepository, ragService, logger, configConfig, knowledgeBaseRepository, systemSettingRepo)
	ragmqHandler, err := mq3.NewRAGMQHandler(mqConsumer, logger, ragService, nodeRepository, knowledgeBaseRepository, llmUsecase, modelUsecase)
	if err != nil {
		return nil, err
	}
	ragDocUpdateHandler, err := mq3.NewRagDocUpdateHandler(mqConsumer, logger, nodeRepository)
	if err != nil {
		return nil, err
	}
	cacheCache, err := cache.NewCache(configConfig)
	if err != nil {
		return nil, err
	}
	statRepository := pg2.NewStatRepository(db, cacheCache)
	appRepository := pg2.NewAppRepository(db, logger)
	ipdbIPDB, err := ipdb.NewIPDB(configConfig, logger)
	if err != nil {
		return nil, err
	}
	ipAddressRepo := ipdb2.NewIPAddressRepo(ipdbIPDB, logger)
	geoRepo := cache2.NewGeoCache(cacheCache, db, logger)
	authRepo := pg2.NewAuthRepo(db, logger, cacheCache)
	statUseCase := usecase.NewStatUseCase(statRepository, nodeRepository, conversationRepository, appRepository, ipAddressRepo, geoRepo, authRepo, knowledgeBaseRepository, logger)
	navRepository := pg2.NewNavRepository(db, logger)
	userRepository := pg2.NewUserRepository(db, logger)
	minioClient, err := s3.NewMinioClient(configConfig)
	if err != nil {
		return nil, err
	}
	nodeUsecase := usecase.NewNodeUsecase(nodeRepository, navRepository, appRepository, ragRepository, userRepository, knowledgeBaseRepository, llmUsecase, ragService, logger, minioClient, modelRepository, authRepo, modelUsecase)
	cronHandler, err := mq3.NewCronHandler(logger, statRepository, nodeRepository, statUseCase, nodeUsecase)
	if err != nil {
		return nil, err
	}
	mqHandlers := &mq3.MQHandlers{
		RAGMQHandler:        ragmqHandler,
		RagDocUpdateHandler: ragDocUpdateHandler,
		StatCronHandler:     cronHandler,
	}
	app := &App{
		MQConsumer:      mqConsumer,
		Config:          configConfig,
		MQHandlers:      mqHandlers,
		StatCronHandler: cronHandler,
	}
	return app, nil
}

// wire.go:

type App struct {
	MQConsumer      mq.MQConsumer
	Config          *config.Config
	MQHandlers      *mq3.MQHandlers
	StatCronHandler *mq3.CronHandler
}


================================================
FILE: backend/cmd/migrate/main.go
================================================
package main

func main() {
	app, err := createApp()
	if err != nil {
		panic(err)
	}
	if err := app.MigrationManager.Execute(); err != nil {
		panic(err)
	}
}


================================================
FILE: backend/cmd/migrate/wire.go
================================================
//go:build wireinject

package main

import (
	"github.com/google/wire"

	"github.com/chaitin/panda-wiki/config"
	"github.com/chaitin/panda-wiki/log"
	"github.com/chaitin/panda-wiki/migration"
)

func createApp() (*App, error) {
	wire.Build(
		wire.Struct(new(App), "*"),
		wire.NewSet(
			config.ProviderSet,
			log.ProviderSet,
			migration.ProviderSet,
		),
	)
	return &App{}, nil
}

type App struct {
	Config           *config.Config
	MigrationManager *migration.Manager
}


================================================
FILE: backend/cmd/migrate/wire_gen.go
================================================
// Code generated by Wire. DO NOT EDIT.

//go:generate go run -mod=mod github.com/google/wire/cmd/wire
//go:build !wireinject
// +build !wireinject

package main

import (
	"github.com/chaitin/panda-wiki/config"
	"github.com/chaitin/panda-wiki/log"
	"github.com/chaitin/panda-wiki/migration"
	"github.com/chaitin/panda-wiki/migration/fns"
	"github.com/chaitin/panda-wiki/mq"
	cache2 "github.com/chaitin/panda-wiki/repo/cache"
	mq2 "github.com/chaitin/panda-wiki/repo/mq"
	pg2 "github.com/chaitin/panda-wiki/repo/pg"
	"github.com/chaitin/panda-wiki/store/cache"
	"github.com/chaitin/panda-wiki/store/pg"
	"github.com/chaitin/panda-wiki/store/rag"
	"github.com/chaitin/panda-wiki/store/s3"
	"github.com/chaitin/panda-wiki/usecase"
)

// Injectors from wire.go:

func createApp() (*App, error) {
	configConfig, err := config.NewConfig()
	if err != nil {
		return nil, err
	}
	db, err := pg.NewDB(configConfig)
	if err != nil {
		return nil, err
	}
	logger := log.NewLogger(configConfig)
	nodeRepository := pg2.NewNodeRepository(db, logger)
	navRepository := pg2.NewNavRepository(db, logger)
	appRepository := pg2.NewAppRepository(db, logger)
	mqProducer, err := mq.NewMQProducer(configConfig, logger)
	if err != nil {
		return nil, err
	}
	ragRepository := mq2.NewRAGRepository(mqProducer)
	userRepository := pg2.NewUserRepository(db, logger)
	ragService, err := rag.NewRAGService(configConfig, logger)
	if err != nil {
		return nil, err
	}
	knowledgeBaseRepository := pg2.NewKnowledgeBaseRepository(db, configConfig, logger, ragService)
	conversationRepository := pg2.NewConversationRepository(db, logger)
	modelRepository := pg2.NewModelRepository(db, logger)
	promptRepo := pg2.NewPromptRepo(db, logger)
	llmUsecase := usecase.NewLLMUsecase(configConfig, ragService, conversationRepository, knowledgeBaseRepository, nodeRepository, modelRepository, promptRepo, logger)
	minioClient, err := s3.NewMinioClient(configConfig)
	if err != nil {
		return nil, err
	}
	cacheCache, err := cache.NewCache(configConfig)
	if err != nil {
		return nil, err
	}
	authRepo := pg2.NewAuthRepo(db, logger, cacheCache)
	systemSettingRepo := pg2.NewSystemSettingRepo(db, logger)
	modelUsecase := usecase.NewModelUsecase(modelRepository, nodeRepository, ragRepository, ragService, logger, configConfig, knowledgeBaseRepository, systemSettingRepo)
	nodeUsecase := usecase.NewNodeUsecase(nodeRepository, navRepository, appRepository, ragRepository, userRepository, knowledgeBaseRepository, llmUsecase, ragService, logger, minioClient, modelRepository, authRepo, modelUsecase)
	kbRepo := cache2.NewKBRepo(cacheCache)
	knowledgeBaseUsecase, err := usecase.NewKnowledgeBaseUsecase(knowledgeBaseRepository, nodeRepository, navRepository, ragRepository, userRepository, ragService, kbRepo, logger, configConfig)
	if err != nil {
		return nil, err
	}
	migrationNodeVersion := fns.NewMigrationNodeVersion(logger, nodeUsecase, knowledgeBaseUsecase, ragRepository)
	migrationCreateBotAuth := fns.NewMigrationCreateBotAuth(logger)
	migrationFixGroupIds := fns.NewMigrationFixGroupIds(logger, ragRepository)
	migrationUpdateNodeStatusUnreleased := fns.NewMigrationUpdateNodeStatusUnreleased(logger)
	migrationCreateFirstNavs := fns.NewMigrationCreateFirstNavs(logger)
	migrationFuncs := &migration.MigrationFuncs{
		NodeMigration:                       migrationNodeVersion,
		BotAuthMigration:                    migrationCreateBotAuth,
		FixGroupIdsMigration:                migrationFixGroupIds,
		UpdateNodeStatusUnreleasedMigration: migrationUpdateNodeStatusUnreleased,
		CreateFirstNavs:                     migrationCreateFirstNavs,
	}
	manager, err := migration.NewManager(db, logger, migrationFuncs)
	if err != nil {
		return nil, err
	}
	app := &App{
		Config:           configConfig,
		MigrationManager: manager,
	}
	return app, nil
}

// wire.go:

type App struct {
	Config           *config.Config
	MigrationManager *migration.Manager
}


================================================
FILE: backend/config/config.go
================================================
package config

import (
	"fmt"
	"os"
	"strconv"

	"github.com/spf13/viper"
)

type Config struct {
	Log           LogConfig    `mapstructure:"log"`
	HTTP          HTTPConfig   `mapstructure:"http"`
	AdminPassword string       `mapstructure:"admin_password"`
	PG            PGConfig     `mapstructure:"pg"`
	MQ            MQConfig     `mapstructure:"mq"`
	RAG           RAGConfig    `mapstructure:"rag"`
	Redis         RedisConfig  `mapstructure:"redis"`
	Auth          AuthConfig   `mapstructure:"auth"`
	S3            S3Config     `mapstructure:"s3"`
	Sentry        SentryConfig `mapstructure:"sentry"`
	CaddyAPI      string       `mapstructure:"caddy_api"`
	SubnetPrefix  string       `mapstructure:"subnet_prefix"`
}

type LogConfig struct {
	Level int `mapstructure:"level"`
}

type HTTPConfig struct {
	Port int `mapstructure:"port"`
}

type PGConfig struct {
	DSN string `mapstructure:"dsn"`
}

type MQConfig struct {
	Type string     `mapstructure:"type"`
	NATS NATSConfig `mapstructure:"nats"`
}

type NATSConfig struct {
	Server   string `mapstructure:"server"`
	User     string `mapstructure:"user"`
	Password string `mapstructure:"password"`
}

type RAGConfig struct {
	Provider string      `mapstructure:"provider"`
	CTRAG    CTRAGConfig `mapstructure:"ct_rag"`
}

type CTRAGConfig struct {
	BaseURL string `mapstructure:"base_url"`
	APIKey  string `mapstructure:"api_key"`
}

type RedisConfig struct {
	Addr     string `mapstructure:"addr"`
	Password string `mapstructure:"password"`
}

type AuthConfig struct {
	Type string    `mapstructure:"type"`
	JWT  JWTConfig `mapstructure:"jwt"`
}

type JWTConfig struct {
	Secret string `mapstructure:"secret"`
}

type S3Config struct {
	Endpoint  string `mapstructure:"endpoint"`
	AccessKey string `mapstructure:"access_key"`
	SecretKey string `mapstructure:"secret_key"`
}

type SentryConfig struct {
	Enabled bool   `mapstructure:"enabled"`
	DSN     string `mapstructure:"dsn"`
}

func NewConfig() (*Config, error) {
	// set default config
	SUBNET_PREFIX := os.Getenv("SUBNET_PREFIX")
	if SUBNET_PREFIX == "" {
		SUBNET_PREFIX = "169.254.15"
	}
	defaultConfig := &Config{
		Log: LogConfig{
			Level: 0,
		},
		AdminPassword: "",
		HTTP: HTTPConfig{
			Port: 8000,
		},
		PG: PGConfig{
			DSN: "host=panda-wiki-postgres user=panda-wiki password=panda-wiki-secret dbname=panda-wiki port=5432 sslmode=disable TimeZone=Asia/Shanghai",
		},
		MQ: MQConfig{
			Type: "nats",
			NATS: NATSConfig{
				Server:   fmt.Sprintf("nats://%s.13:4222", SUBNET_PREFIX),
				User:     "panda-wiki",
				Password: "",
			},
		},
		RAG: RAGConfig{
			Provider: "ct",
			CTRAG: CTRAGConfig{
				BaseURL: fmt.Sprintf("http://%s.18:5050", SUBNET_PREFIX),
				APIKey:  "sk-1234567890",
			},
		},
		Redis: RedisConfig{
			Addr:     "panda-wiki-redis:6379",
			Password: "",
		},
		Auth: AuthConfig{
			Type: "jwt",
			JWT:  JWTConfig{Secret: ""},
		},
		S3: S3Config{
			Endpoint:  "panda-wiki-minio:9000",
			AccessKey: "s3panda-wiki",
			SecretKey: "",
		},
		Sentry: SentryConfig{
			Enabled: true,
			DSN:     "https://2a4cff1ae04b624ffc72663f523024ff@sentry.baizhi.cloud/4",
		},
		CaddyAPI:     "/app/run/caddy-admin.sock",
		SubnetPrefix: "169.254.15",
	}

	viper.AddConfigPath(".")
	viper.AddConfigPath("./config")
	viper.SetConfigName("config")
	viper.SetConfigType("yml")

	// try to read config file
	if err := viper.ReadInConfig(); err != nil {
		if _, ok := err.(viper.ConfigFileNotFoundError); !ok {
			// if config file not found, return default config
			return nil, err
		}
	}

	// merge config file values to default config
	if err := viper.Unmarshal(defaultConfig); err != nil {
		return nil, err
	}

	// finally, override sensitive info with env variables
	overrideWithEnv(defaultConfig)

	return defaultConfig, nil
}

// overrideWithEnv override sensitive info with env variables
func overrideWithEnv(c *Config) {
	if env := os.Getenv("POSTGRES_PASSWORD"); env != "" {
		c.PG.DSN = fmt.Sprintf("host=panda-wiki-postgres user=panda-wiki password=%s dbname=panda-wiki port=5432 sslmode=disable TimeZone=Asia/Shanghai", env)
	}
	if env := os.Getenv("NATS_PASSWORD"); env != "" {
		c.MQ.NATS.Password = env
	}
	if env := os.Getenv("REDIS_PASSWORD"); env != "" {
		c.Redis.Password = env
	}
	if env := os.Getenv("JWT_SECRET"); env != "" {
		c.Auth.JWT.Secret = env
	}
	if env := os.Getenv("S3_SECRET_KEY"); env != "" {
		c.S3.SecretKey = env
	}
	if env := os.Getenv("ADMIN_PASSWORD"); env != "" {
		c.AdminPassword = env
	}
	if env := os.Getenv("SUBNET_PREFIX"); env != "" {
		c.SubnetPrefix = env
	}
	// pg
	if env := os.Getenv("PG_DSN"); env != "" {
		c.PG.DSN = env
	}
	// nats
	if env := os.Getenv("MQ_NATS_SERVER"); env != "" {
		c.MQ.NATS.Server = env
	}
	// rag
	if env := os.Getenv("RAG_CT_RAG_BASE_URL"); env != "" {
		c.RAG.CTRAG.BaseURL = env
	}
	// redis
	if env := os.Getenv("REDIS_ADDR"); env != "" {
		c.Redis.Addr = env
	}
	// s3
	if env := os.Getenv("S3_ENDPOINT"); env != "" {
		c.S3.Endpoint = env
	}
	// sentry
	if env := os.Getenv("SENTRY_ENABLED"); env != "" {
		c.Sentry.Enabled = env == "true"
	}
	if env := os.Getenv("SENTRY_DSN"); env != "" {
		c.Sentry.DSN = env
	}
	// caddy api
	if env := os.Getenv("CADDY_API"); env != "" {
		c.CaddyAPI = env
	}
	// log level
	if env := os.Getenv("LOG_LEVEL"); env != "" {
		if i, err := strconv.Atoi(env); err == nil {
			// -4: debug
			// 0: info
			// 4: warn
			// 8: error
			c.Log.Level = i
		} else {
			fmt.Fprintf(os.Stderr, "Invalid log level: %s with err: %s\n", env, err)
		}
	}
}

func (*Config) GetString(key string) string {
	return viper.GetString(key)
}

func (*Config) GetInt(key string) int {
	return viper.GetInt(key)
}

func (*Config) GetUint64(key string) uint64 {
	return viper.GetUint64(key)
}

func (*Config) GetBool(key string) bool {
	return viper.GetBool(key)
}

func (*Config) GetStringSlice(key string) []string {
	return viper.GetStringSlice(key)
}

func (*Config) GetFloat64(key string) float64 {
	return viper.GetFloat64(key)
}


================================================
FILE: backend/config/provider.go
================================================
package config

import "github.com/google/wire"

var ProviderSet = wire.NewSet(NewConfig)


================================================
FILE: backend/consts/admin.go
================================================
package consts

type UserKBPermission string

const (
	UserKBPermissionNull        UserKBPermission = ""             // 无权限
	UserKBPermissionNotNull     UserKBPermission = "not null"     // 有权限
	UserKBPermissionFullControl UserKBPermission = "full_control" // 完全控制
	UserKBPermissionDocManage   UserKBPermission = "doc_manage"   // 文档管理
	UserKBPermissionDataOperate UserKBPermission = "data_operate" // 数据运营
)

type UserRole string

const (
	UserRoleAdmin UserRole = "admin" // 管理员
	UserRoleUser  UserRole = "user"  // 普通用户
)


================================================
FILE: backend/consts/app.go
================================================
package consts

type CopySetting string

const (
	CopySettingNone     CopySetting = ""         // 无限制
	CopySettingAppend   CopySetting = "append"   // 增加内容尾巴
	CopySettingDisabled CopySetting = "disabled" // 禁止复制内容
)

type WatermarkSetting string

const (
	WatermarkDisabled WatermarkSetting = ""        // 未开启水印
	WatermarkHidden   WatermarkSetting = "hidden"  // 隐形水印
	WatermarkVisible  WatermarkSetting = "visible" // 显性水印
)

type HomePageSetting string

const (
	HomePageSettingDoc    HomePageSetting = "doc"    // 文档页面
	HomePageSettingCustom HomePageSetting = "custom" // 自定义首页
)


================================================
FILE: backend/consts/auth.go
================================================
package consts

type SourceType string

var (
	BotSourceTypes = []SourceType{SourceTypeWidget, SourceTypeDingtalkBot, SourceTypeFeishuBot, SourceTypeLarkBot, SourceTypeWechatBot, SourceTypeWechatServiceBot, SourceTypeDiscordBot, SourceTypeWechatOfficialAccount}
)

const (
	SourceTypeDingTalk              SourceType = "dingtalk"
	SourceTypeFeishu                SourceType = "feishu"
	SourceTypeWeCom                 SourceType = "wecom"
	SourceTypeOAuth                 SourceType = "oauth"
	SourceTypeGitHub                SourceType = "github"
	SourceTypeCAS                   SourceType = "cas"
	SourceTypeLDAP                  SourceType = "ldap"
	SourceTypeWidget                SourceType = "widget"
	SourceTypeDingtalkBot           SourceType = "dingtalk_bot"
	SourceTypeFeishuBot             SourceType = "feishu_bot"
	SourceTypeLarkBot               SourceType = "lark_bot"
	SourceTypeWechatBot             SourceType = "wechat_bot"
	SourceTypeWecomAIBot            SourceType = "wecom_ai_bot"
	SourceTypeWechatServiceBot      SourceType = "wechat_service_bot"
	SourceTypeDiscordBot            SourceType = "discord_bot"
	SourceTypeWechatOfficialAccount SourceType = "wechat_official_account"
	SourceTypeOpenAIAPI             SourceType = "openai_api"
	SourceTypeMcpServer             SourceType = "mcp_server"
)

func (s SourceType) Name() string {
	switch s {
	case SourceTypeWidget:
		return "网页挂件机器人"
	case SourceTypeDingtalkBot:
		return "钉钉机器人"
	case SourceTypeFeishuBot:
		return "飞书机器人"
	case SourceTypeLarkBot:
		return "Lark机器人"
	case SourceTypeWechatBot:
		return "企业微信机器人"
	case SourceTypeWecomAIBot:
		return "企业微信智能机器人"
	case SourceTypeWechatServiceBot:
		return "企业微信客服"
	case SourceTypeDiscordBot:
		return "Discord 机器人"
	case SourceTypeWechatOfficialAccount:
		return "微信公众号"
	case SourceTypeMcpServer:
		return "MCP 服务器"
	default:
		return ""
	}
}

type AuthType string

const (
	AuthTypeNull       AuthType = ""           // 无认证
	AuthTypeSimple     AuthType = "simple"     // 简单口令
	AuthTypeEnterprise AuthType = "enterprise" // 企业认证

)


================================================
FILE: backend/consts/captcha.go
================================================
package consts

type RedeemCaptchaReq struct {
	Token     string  `json:"token"`
	Solutions []int64 `json:"solutions"`
}


================================================
FILE: backend/consts/consts.go
================================================
package consts

type StatDay int

const (
	StatDay1  StatDay = 1
	StatDay7  StatDay = 7
	StatDay30 StatDay = 30
	StatDay90 StatDay = 90
)


================================================
FILE: backend/consts/contribute.go
================================================
package consts

type ContributeStatus string

const (
	ContributeStatusPending  ContributeStatus = "pending"
	ContributeStatusApproved ContributeStatus = "approved"
	ContributeStatusRejected ContributeStatus = "rejected"
)

type ContributeType string

const (
	ContributeTypeAdd  ContributeType = "add"
	ContributeTypeEdit ContributeType = "edit"
)


================================================
FILE: backend/consts/crawler.go
================================================
package consts

type CrawlerStatus string

const (
	CrawlerStatusPending   CrawlerStatus = "pending"
	CrawlerStatusInProcess CrawlerStatus = "in_process"
	CrawlerStatusCompleted CrawlerStatus = "completed"
	CrawlerStatusFailed    CrawlerStatus = "failed"
)


================================================
FILE: backend/consts/license.go
================================================
package consts

import (
	"github.com/labstack/echo/v4"
)

type contextKey string

const ContextKeyEdition contextKey = "edition"

type LicenseEdition int32

const (
	LicenseEditionFree       LicenseEdition = 0 // 开源版
	LicenseEditionProfession LicenseEdition = 1 // 专业版
	LicenseEditionEnterprise LicenseEdition = 2 // 企业版
	LicenseEditionBusiness   LicenseEdition = 3 // 商业版
)

func GetLicenseEdition(c echo.Context) LicenseEdition {
	edition, _ := c.Get("edition").(LicenseEdition)
	return edition
}


================================================
FILE: backend/consts/model.go
================================================
package consts

type AutoModeDefaultModel string

const (
	AutoModeDefaultChatModel       AutoModeDefaultModel = "deepseek-chat"
	AutoModeDefaultEmbeddingModel  AutoModeDefaultModel = "bge-m3"
	AutoModeDefaultRerankModel     AutoModeDefaultModel = "bge-reranker-v2-m3"
	AutoModeDefaultAnalysisModel   AutoModeDefaultModel = "qwen2.5-3b-instruct"
	AutoModeDefaultAnalysisVLModel AutoModeDefaultModel = "qwen-vl-max-latest"
)

func GetAutoModeDefaultModel(modelType string) string {
	switch modelType {
	case "chat":
		return string(AutoModeDefaultChatModel)
	case "embedding":
		return string(AutoModeDefaultEmbeddingModel)
	case "rerank":
		return string(AutoModeDefaultRerankModel)
	case "analysis":
		return string(AutoModeDefaultAnalysisModel)
	case "analysis-vl":
		return string(AutoModeDefaultAnalysisVLModel)
	default:
		return string(AutoModeDefaultChatModel)
	}
}

type ModelSettingMode string

const (
	ModelSettingModeManual ModelSettingMode = "manual"
	ModelSettingModeAuto   ModelSettingMode = "auto"
)

const (
	AutoModeBaseURL = "https://model-square.app.baizhi.cloud/v1"
)


================================================
FILE: backend/consts/node.go
================================================
package consts

type NodeAccessPerm string

const (
	NodeAccessPermOpen    NodeAccessPerm = "open"    // 完全开放
	NodeAccessPermPartial NodeAccessPerm = "partial" // 部分开放
	NodeAccessPermClosed  NodeAccessPerm = "closed"  // 完全禁止
)

type NodePermName string

const (
	NodePermNameVisible    NodePermName = "visible"    // 导航内可见
	NodePermNameVisitable  NodePermName = "visitable"  // 可被访问
	NodePermNameAnswerable NodePermName = "answerable" // 可被问答
)

type NodeRagInfoStatus string

const (
	NodeRagStatusPending    NodeRagInfoStatus = "PENDING"   // 等待处理
	NodeRagStatusRunning    NodeRagInfoStatus = "RUNNING"   // 正在进行处理(文本分割、向量化等)
	NodeRagStatusFailed     NodeRagInfoStatus = "FAILED"    // 处理失败
	NodeRagStatusSucceeded  NodeRagInfoStatus = "SUCCEEDED" // 处理成功
	NodeRagStatusReindexing NodeRagInfoStatus = "REINDEX"   // 重新索引中
)


================================================
FILE: backend/consts/parse.go
================================================
package consts

type CrawlerSource string

const (
	// CrawlerSourceUrl key或url形式 直接走parse接口
	CrawlerSourceUrl      CrawlerSource = "url"
	CrawlerSourceRSS      CrawlerSource = "rss"
	CrawlerSourceSitemap  CrawlerSource = "sitemap"
	CrawlerSourceNotion   CrawlerSource = "notion"
	CrawlerSourceFeishu   CrawlerSource = "feishu"
	CrawlerSourceDingtalk CrawlerSource = "dingtalk"

	// CrawlerSourceFile file形式 需要先走upload接口先上传文件
	CrawlerSourceFile       CrawlerSource = "file"
	CrawlerSourceEpub       CrawlerSource = "epub"
	CrawlerSourceYuque      CrawlerSource = "yuque"
	CrawlerSourceSiyuan     CrawlerSource = "siyuan"
	CrawlerSourceMindoc     CrawlerSource = "mindoc"
	CrawlerSourceWikijs     CrawlerSource = "wikijs"
	CrawlerSourceConfluence CrawlerSource = "confluence"
)

type CrawlerSourceType string

const (
	CrawlerSourceTypeFile CrawlerSourceType = "file"
	CrawlerSourceTypeUrl  CrawlerSourceType = "url"
	CrawlerSourceTypeKey  CrawlerSourceType = "key"
)

func (c CrawlerSource) Type() CrawlerSourceType {
	switch c {
	case CrawlerSourceNotion, CrawlerSourceFeishu, CrawlerSourceDingtalk:
		return CrawlerSourceTypeKey
	case CrawlerSourceUrl, CrawlerSourceRSS, CrawlerSourceSitemap:
		return CrawlerSourceTypeUrl
	case CrawlerSourceFile, CrawlerSourceEpub, CrawlerSourceYuque, CrawlerSourceSiyuan, CrawlerSourceMindoc, CrawlerSourceWikijs, CrawlerSourceConfluence:
		return CrawlerSourceTypeFile
	default:
		return ""
	}
}


================================================
FILE: backend/consts/system_setting.go
================================================
package consts

type SystemSettingKey string

const (
	SystemSettingModelMode SystemSettingKey = "model_setting_mode"
	SystemSettingUpload    SystemSettingKey = "upload"
)


================================================
FILE: backend/docs/docs.go
================================================
// Package docs Code generated by swaggo/swag. DO NOT EDIT
package docs

import "github.com/swaggo/swag"

const docTemplate = `{
    "schemes": {{ marshal .Schemes }},
    "swagger": "2.0",
    "info": {
        "description": "{{escape .Description}}",
        "title": "{{.Title}}",
        "contact": {},
        "version": "{{.Version}}"
    },
    "host": "{{.Host}}",
    "basePath": "{{.BasePath}}",
    "paths": {
        "/api/v1/app": {
            "put": {
                "security": [
                    {
                        "bearerAuth": []
                    }
                ],
                "description": "Update app",
                "consumes": [
                    "application/json"
                ],
                "produces": [
                    "application/json"
                ],
                "tags": [
                    "app"
                ],
                "summary": "Update app",
                "parameters": [
                    {
                        "type": "string",
                        "description": "id",
                        "name": "id",
                        "in": "query",
                        "required": true
                    },
                    {
                        "description": "app",
                        "name": "app",
                        "in": "body",
                        "required": true,
                        "schema": {
                            "$ref": "#/definitions/domain.UpdateAppReq"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK",
                        "schema": {
                            "$ref": "#/definitions/domain.Response"
                        }
                    }
                }
            },
            "delete": {
                "security": [
                    {
                        "bearerAuth": []
                    }
                ],
                "description": "Delete app",
                "consumes": [
                    "application/json"
                ],
                "tags": [
                    "app"
                ],
                "summary": "Delete app",
                "parameters": [
                    {
                        "type": "string",
                        "description": "kb id",
                        "name": "kb_id",
                        "in": "query",
                        "required": true
                    },
                    {
                        "type": "string",
                        "description": "app id",
                        "name": "id",
                        "in": "query",
                        "required": true
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK",
                        "schema": {
                            "$ref": "#/definitions/domain.Response"
                        }
                    }
                }
            }
        },
        "/api/v1/app/detail": {
            "get": {
                "security": [
                    {
                        "bearerAuth": []
                    }
                ],
                "description": "Get app detail",
                "consumes": [
                    "application/json"
                ],
                "produces": [
                    "application/json"
                ],
                "tags": [
                    "app"
                ],
                "summary": "Get app detail",
                "parameters": [
                    {
                        "type": "string",
                        "description": "kb id",
                        "name": "kb_id",
                        "in": "query",
                        "required": true
                    },
                    {
                        "type": "string",
                        "description": "app type",
                        "name": "type",
                        "in": "query",
                        "required": true
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK",
                        "schema": {
                            "allOf": [
                                {
                                    "$ref": "#/definitions/domain.PWResponse"
                                },
                                {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "$ref": "#/definitions/domain.AppDetailResp"
                                        }
                                    }
                                }
                            ]
                        }
                    }
                }
            }
        },
        "/api/v1/auth/delete": {
            "delete": {
                "security": [
                    {
                        "bearerAuth": []
                    }
                ],
                "description": "删除授权信息",
                "consumes": [
                    "application/json"
                ],
                "produces": [
                    "application/json"
                ],
                "tags": [
                    "Auth"
                ],
                "summary": "删除授权信息",
                "operationId": "v1-OpenAuthDelete",
                "parameters": [
                    {
                        "type": "integer",
                        "name": "id",
                        "in": "query"
                    },
                    {
                        "type": "string",
                        "name": "kb_id",
                        "in": "query"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK",
                        "schema": {
                            "$ref": "#/definitions/domain.Response"
                        }
                    }
                }
            }
        },
        "/api/v1/auth/get": {
            "get": {
                "security": [
                    {
                        "bearerAuth": []
                    }
                ],
                "description": "获取授权信息",
                "consumes": [
                    "application/json"
                ],
                "produces": [
                    "application/json"
                ],
                "tags": [
                    "Auth"
                ],
                "summary": "获取授权信息",
                "operationId": "v1-OpenAuthGet",
                "parameters": [
                    {
                        "type": "string",
                        "name": "kb_id",
                        "in": "query"
                    },
                    {
                        "enum": [
                            "dingtalk",
                            "feishu",
                            "wecom",
                            "oauth",
                            "github",
                            "cas",
                            "ldap",
                            "widget",
                            "dingtalk_bot",
                            "feishu_bot",
                            "lark_bot",
                            "wechat_bot",
                            "wecom_ai_bot",
                            "wechat_service_bot",
                            "discord_bot",
                            "wechat_official_account",
                            "openai_api",
                            "mcp_server"
                        ],
                        "type": "string",
                        "x-enum-varnames": [
                            "SourceTypeDingTalk",
                            "SourceTypeFeishu",
                            "SourceTypeWeCom",
                            "SourceTypeOAuth",
                            "SourceTypeGitHub",
                            "SourceTypeCAS",
                            "SourceTypeLDAP",
                            "SourceTypeWidget",
                            "SourceTypeDingtalkBot",
                            "SourceTypeFeishuBot",
                            "SourceTypeLarkBot",
                            "SourceTypeWechatBot",
                            "SourceTypeWecomAIBot",
                            "SourceTypeWechatServiceBot",
                            "SourceTypeDiscordBot",
                            "SourceTypeWechatOfficialAccount",
                            "SourceTypeOpenAIAPI",
                            "SourceTypeMcpServer"
                        ],
                        "name": "source_type",
                        "in": "query",
                        "required": true
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK",
                        "schema": {
                            "allOf": [
                                {
                                    "$ref": "#/definitions/domain.PWResponse"
                                },
                                {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "$ref": "#/definitions/github_com_chaitin_panda-wiki_api_auth_v1.AuthGetResp"
                                        }
                                    }
                                }
                            ]
                        }
                    }
                }
            }
        },
        "/api/v1/auth/set": {
            "post": {
                "security": [
                    {
                        "bearerAuth": []
                    }
                ],
                "description": "设置授权信息",
                "consumes": [
                    "application/json"
                ],
                "produces": [
                    "application/json"
                ],
                "tags": [
                    "Auth"
                ],
                "summary": "设置授权信息",
                "operationId": "v1-OpenAuthSet",
                "parameters": [
                    {
                        "description": "para",
                        "name": "param",
                        "in": "body",
                        "required": true,
                        "schema": {
                            "$ref": "#/definitions/v1.AuthSetReq"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK",
                        "schema": {
                            "$ref": "#/definitions/domain.Response"
                        }
                    }
                }
            }
        },
        "/api/v1/comment": {
            "get": {
                "description": "GetCommentModeratedList",
                "consumes": [
                    "application/json"
                ],
                "produces": [
                    "application/json"
                ],
                "tags": [
                    "comment"
                ],
                "summary": "GetCommentModeratedList",
                "parameters": [
                    {
                        "type": "string",
                        "name": "kb_id",
                        "in": "query",
                        "required": true
                    },
                    {
                        "minimum": 1,
                        "type": "integer",
                        "name": "page",
                        "in": "query",
                        "required": true
                    },
                    {
                        "minimum": 1,
                        "type": "integer",
                        "name": "per_page",
                        "in": "query",
                        "required": true
                    },
                    {
                        "enum": [
                            -1,
                            0,
                            1
                        ],
                        "type": "integer",
                        "format": "int32",
                        "x-enum-varnames": [
                            "CommentStatusReject",
                            "CommentStatusPending",
                            "CommentStatusAccepted"
                        ],
                        "name": "status",
                        "in": "query"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "conversationList",
                        "schema": {
                            "allOf": [
                                {
                                    "$ref": "#/definitions/domain.PWResponse"
                                },
                                {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "$ref": "#/definitions/v1.CommentLists"
                                        }
                                    }
                                }
                            ]
                        }
                    }
                }
            }
        },
        "/api/v1/comment/list": {
            "delete": {
                "description": "DeleteCommentList",
                "consumes": [
                    "application/json"
                ],
                "produces": [
                    "application/json"
                ],
                "tags": [
                    "comment"
                ],
                "summary": "DeleteCommentList",
                "parameters": [
                    {
                        "type": "array",
                        "items": {
                            "type": "string"
                        },
                        "collectionFormat": "csv",
                        "name": "ids",
                        "in": "query"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "total",
                        "schema": {
                            "$ref": "#/definitions/domain.Response"
                        }
                    }
                }
            }
        },
        "/api/v1/conversation": {
            "get": {
                "description": "get conversation list",
                "consumes": [
                    "application/json"
                ],
                "produces": [
                    "application/json"
                ],
                "tags": [
                    "conversation"
                ],
                "summary": "get conversation list",
                "parameters": [
                    {
                        "type": "string",
                        "name": "app_id",
                        "in": "query"
                    },
                    {
                        "type": "string",
                        "name": "kb_id",
                        "in": "query",
                        "required": true
                    },
                    {
                        "minimum": 1,
                        "type": "integer",
                        "name": "page",
                        "in": "query",
                        "required": true
                    },
                    {
                        "minimum": 1,
                        "type": "integer",
                        "name": "per_page",
                        "in": "query",
                        "required": true
                    },
                    {
                        "type": "string",
                        "name": "remote_ip",
                        "in": "query"
                    },
                    {
                        "type": "string",
                        "name": "subject",
                        "in": "query"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK",
                        "schema": {
                            "allOf": [
                                {
                                    "$ref": "#/definitions/domain.PWResponse"
                                },
                                {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "$ref": "#/definitions/v1.ConversationListItems"
                                        }
                                    }
                                }
                            ]
                        }
                    }
                }
            }
        },
        "/api/v1/conversation/detail": {
            "get": {
                "description": "get conversation detail",
                "consumes": [
                    "application/json"
                ],
                "produces": [
                    "application/json"
                ],
                "tags": [
                    "conversation"
                ],
                "summary": "get conversation detail",
                "parameters": [
                    {
                        "type": "string",
                        "name": "id",
                        "in": "query",
                        "required": true
                    },
                    {
                        "type": "string",
                        "name": "kb_id",
                        "in": "query",
                        "required": true
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK",
                        "schema": {
                            "allOf": [
                                {
                                    "$ref": "#/definitions/domain.PWResponse"
                                },
                                {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "$ref": "#/definitions/domain.ConversationDetailResp"
                                        }
                                    }
                                }
                            ]
                        }
                    }
                }
            }
        },
        "/api/v1/conversation/message/detail": {
            "get": {
                "description": "Get message detail",
                "consumes": [
                    "application/json"
                ],
                "produces": [
                    "application/json"
                ],
                "tags": [
                    "Message"
                ],
                "summary": "Get message detail",
                "parameters": [
                    {
                        "type": "string",
                        "name": "id",
                        "in": "query",
                        "required": true
                    },
                    {
                        "type": "string",
                        "name": "kb_id",
                        "in": "query",
                        "required": true
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK",
                        "schema": {
                            "allOf": [
                                {
                                    "$ref": "#/definitions/domain.PWResponse"
                                },
                                {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "$ref": "#/definitions/domain.ConversationMessage"
                                        }
                                    }
                                }
                            ]
                        }
                    }
                }
            }
        },
        "/api/v1/conversation/message/list": {
            "get": {
                "description": "GetMessageFeedBackList",
                "consumes": [
                    "application/json"
                ],
                "produces": [
                    "application/json"
                ],
                "tags": [
                    "Message"
                ],
                "summary": "GetMessageFeedBackList",
                "parameters": [
                    {
                        "type": "string",
                        "name": "kb_id",
                        "in": "query",
                        "required": true
                    },
                    {
                        "minimum": 1,
                        "type": "integer",
                        "name": "page",
                        "in": "query",
                        "required": true
                    },
                    {
                        "minimum": 1,
                        "type": "integer",
                        "name": "per_page",
                        "in": "query",
                        "required": true
                    }
                ],
                "responses": {
                    "200": {
                        "description": "MessageList",
                        "schema": {
                            "allOf": [
                                {
                                    "$ref": "#/definitions/domain.PWResponse"
                                },
                                {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "$ref": "#/definitions/domain.PaginatedResult-array_domain_ConversationMessageListItem"
                                        }
                                    }
                                }
                            ]
                        }
                    }
                }
            }
        },
        "/api/v1/crawler/export": {
            "post": {
                "description": "CrawlerExport",
                "consumes": [
                    "application/json"
                ],
                "produces": [
                    "application/json"
                ],
                "tags": [
                    "crawler"
                ],
                "summary": "CrawlerExport",
                "parameters": [
                    {
                        "description": "Scrape",
                        "name": "body",
                        "in": "body",
                        "required": true,
                        "schema": {
                            "$ref": "#/definitions/v1.CrawlerExportReq"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK",
                        "schema": {
                            "allOf": [
                                {
                                    "$ref": "#/definitions/domain.PWResponse"
                                },
                                {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "$ref": "#/definitions/v1.CrawlerExportResp"
                                        }
                                    }
                                }
                            ]
                        }
                    }
                }
            }
        },
        "/api/v1/crawler/parse": {
            "post": {
                "description": "解析文档树",
                "consumes": [
                    "application/json"
                ],
                "produces": [
                    "application/json"
                ],
                "tags": [
                    "crawler"
                ],
                "summary": "解析文档树",
                "parameters": [
                    {
                        "description": "Scrape",
                        "name": "body",
                        "in": "body",
                        "required": true,
                        "schema": {
                            "$ref": "#/definitions/v1.CrawlerParseReq"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK",
                        "schema": {
                            "allOf": [
                                {
                                    "$ref": "#/definitions/domain.PWResponse"
                                },
                                {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "$ref": "#/definitions/v1.CrawlerParseResp"
                                        }
                                    }
                                }
                            ]
                        }
                    }
                }
            }
        },
        "/api/v1/crawler/result": {
            "get": {
                "description": "Retrieve the result of a previously started scraping task",
                "consumes": [
                    "application/json"
                ],
                "produces": [
                    "application/json"
                ],
                "tags": [
                    "crawler"
                ],
                "summary": "Get Crawler Result",
                "parameters": [
                    {
                        "description": "Crawler Result Request",
                        "name": "body",
                        "in": "body",
                        "required": true,
                        "schema": {
                            "$ref": "#/definitions/v1.CrawlerResultReq"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK",
                        "schema": {
                            "allOf": [
                                {
                                    "$ref": "#/definitions/domain.PWResponse"
                                },
                                {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "$ref": "#/definitions/v1.CrawlerResultResp"
                                        }
                                    }
                                }
                            ]
                        }
                    }
                }
            }
        },
        "/api/v1/crawler/results": {
            "post": {
                "description": "Retrieve the results of a previously started scraping task",
                "consumes": [
                    "application/json"
                ],
                "produces": [
                    "application/json"
                ],
                "tags": [
                    "crawler"
                ],
                "summary": "Get Crawler Results",
                "parameters": [
                    {
                        "description": "Crawler Results Request",
                        "name": "param",
                        "in": "body",
                        "required": true,
                        "schema": {
                            "$ref": "#/definitions/v1.CrawlerResultsReq"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK",
                        "schema": {
                            "allOf": [
                                {
                                    "$ref": "#/definitions/domain.PWResponse"
                                },
                                {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "$ref": "#/definitions/v1.CrawlerResultsResp"
                                        }
                                    }
                                }
                            ]
                        }
                    }
                }
            }
        },
        "/api/v1/creation/tab-complete": {
            "post": {
                "description": "Tab-based document completion similar to AI coding's FIM (Fill in Middle)",
                "consumes": [
                    "application/json"
                ],
                "produces": [
                    "application/json"
                ],
                "tags": [
                    "creation"
                ],
                "summary": "Tab-based document completion",
                "parameters": [
                    {
                        "description": "tab completion request",
                        "name": "body",
                        "in": "body",
                        "required": true,
                        "schema": {
                            "$ref": "#/definitions/domain.CompleteReq"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "success",
                        "schema": {
                            "type": "string"
                        }
                    }
                }
            }
        },
        "/api/v1/creation/text": {
            "post": {
                "description": "Text creation",
                "consumes": [
                    "application/json"
                ],
                "produces": [
                    "application/json"
                ],
                "tags": [
                    "creation"
                ],
                "summary": "Text creation",
                "parameters": [
                    {
                        "description": "text creation request",
                        "name": "body",
                        "in": "body",
                        "required": true,
                        "schema": {
                            "$ref": "#/definitions/domain.TextReq"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "success",
                        "schema": {
                            "type": "string"
                        }
                    }
                }
            }
        },
        "/api/v1/file/upload": {
            "post": {
                "description": "Upload File",
                "consumes": [
                    "multipart/form-data"
                ],
                "tags": [
                    "file"
                ],
                "summary": "Upload File",
                "parameters": [
                    {
                        "type": "file",
                        "description": "File",
                        "name": "file",
                        "in": "formData",
                        "required": true
                    },
                    {
                        "type": "string",
                        "description": "Knowledge Base ID",
                        "name": "kb_id",
                        "in": "formData"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK",
                        "schema": {
                            "$ref": "#/definitions/domain.ObjectUploadResp"
                        }
                    }
                }
            }
        },
        "/api/v1/file/upload/anydoc": {
            "post": {
                "description": "Upload Anydoc File",
                "consumes": [
                    "multipart/form-data"
                ],
                "tags": [
                    "file"
                ],
                "summary": "Upload Anydoc File",
                "parameters": [
                    {
                        "type": "file",
                        "description": "File",
                        "name": "file",
                        "in": "formData",
                        "required": true
                    },
                    {
                        "type": "string",
                        "description": "File Path",
                        "name": "path",
                        "in": "formData",
                        "required": true
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK",
                        "schema": {
                            "$ref": "#/definitions/domain.AnydocUploadResp"
                        }
                    }
                }
            }
        },
        "/api/v1/file/upload/url": {
            "post": {
                "description": "Upload File By Url",
                "consumes": [
                    "application/json"
                ],
                "produces": [
                    "application/json"
                ],
                "tags": [
                    "file"
                ],
                "summary": "Upload File By Url",
                "parameters": [
                    {
                        "description": "Request Body",
                        "name": "body",
                        "in": "body",
                        "required": true,
                        "schema": {
                            "$ref": "#/definitions/domain.UploadByUrlReq"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK",
                        "schema": {
                            "allOf": [
                                {
                                    "$ref": "#/definitions/domain.Response"
                                },
                                {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "$ref": "#/definitions/domain.ObjectUploadResp"
                                        }
                                    }
                                }
                            ]
                        }
                    }
                }
            }
        },
        "/api/v1/knowledge_base": {
            "post": {
                "description": "CreateKnowledgeBase",
                "consumes": [
                    "application/json"
                ],
                "produces": [
                    "application/json"
                ],
                "tags": [
                    "knowledge_base"
                ],
                "summary": "CreateKnowledgeBase",
                "parameters": [
                    {
                        "description": "CreateKnowledgeBase Request",
                        "name": "body",
                        "in": "body",
                        "required": true,
                        "schema": {
                            "$ref": "#/definitions/domain.CreateKnowledgeBaseReq"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK",
                        "schema": {
                            "$ref": "#/definitions/domain.Response"
                        }
                    }
                }
            }
        },
        "/api/v1/knowledge_base/detail": {
            "get": {
                "security": [
                    {
                        "bearerAuth": []
                    }
                ],
                "description": "GetKnowledgeBaseDetail",
                "consumes": [
                    "application/json"
                ],
                "produces": [
                    "application/json"
                ],
                "tags": [
                    "knowledge_base"
                ],
                "summary": "GetKnowledgeBaseDetail",
                "parameters": [
                    {
                        "type": "string",
                        "description": "Knowledge Base ID",
                        "name": "id",
                        "in": "query",
                        "required": true
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK",
                        "schema": {
                            "allOf": [
                                {
                                    "$ref": "#/definitions/domain.PWResponse"
                                },
                                {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "$ref": "#/definitions/domain.KnowledgeBaseDetail"
                                        }
                                    }
                                }
                            ]
                        }
                    }
                }
            },
            "put": {
                "description": "UpdateKnowledgeBase",
                "consumes": [
                    "application/json"
                ],
                "produces": [
                    "application/json"
                ],
                "tags": [
                    "knowledge_base"
                ],
                "summary": "UpdateKnowledgeBase",
                "parameters": [
                    {
                        "description": "UpdateKnowledgeBase Request",
                        "name": "body",
                        "in": "body",
                        "required": true,
                        "schema": {
                            "$ref": "#/definitions/domain.UpdateKnowledgeBaseReq"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK",
                        "schema": {
                            "$ref": "#/definitions/domain.Response"
                        }
                    }
                }
            },
            "delete": {
                "description": "DeleteKnowledgeBase",
                "consumes": [
                    "application/json"
                ],
                "produces": [
                    "application/json"
                ],
                "tags": [
                    "knowledge_base"
                ],
                "summary": "DeleteKnowledgeBase",
                "parameters": [
                    {
                        "type": "string",
                        "description": "Knowledge Base ID",
                        "name": "id",
                        "in": "query",
                        "required": true
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK",
                        "schema": {
                            "$ref": "#/definitions/domain.Response"
                        }
                    }
                }
            }
        },
        "/api/v1/knowledge_base/list": {
            "get": {
                "description": "GetKnowledgeBaseList",
                "consumes": [
                    "application/json"
                ],
                "produces": [
                    "application/json"
                ],
                "tags": [
                    "knowledge_base"
                ],
                "summary": "GetKnowledgeBaseList",
                "responses": {
                    "200": {
                        "description": "OK",
                        "schema": {
                            "allOf": [
                                {
                                    "$ref": "#/definitions/domain.PWResponse"
                                },
                                {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "type": "array",
                                            "items": {
                                                "$ref": "#/definitions/domain.KnowledgeBaseListItem"
                                            }
                                        }
                                    }
                                }
                            ]
                        }
                    }
                }
            }
        },
        "/api/v1/knowledge_base/release": {
            "post": {
                "description": "CreateKBRelease",
                "consumes": [
                    "application/json"
                ],
                "produces": [
                    "application/json"
                ],
                "tags": [
                    "knowledge_base"
                ],
                "summary": "CreateKBRelease",
                "parameters": [
                    {
                        "description": "CreateKBRelease Request",
                        "name": "body",
                        "in": "body",
                        "required": true,
                        "schema": {
                            "$ref": "#/definitions/domain.CreateKBReleaseReq"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK",
                        "schema": {
                            "$ref": "#/definitions/domain.Response"
                        }
                    }
                }
            }
        },
        "/api/v1/knowledge_base/release/list": {
            "get": {
                "description": "GetKBReleaseList",
                "consumes": [
                    "application/json"
                ],
                "produces": [
                    "application/json"
                ],
                "tags": [
                    "knowledge_base"
                ],
                "summary": "GetKBReleaseList",
                "parameters": [
                    {
                        "type": "string",
                        "description": "Knowledge Base ID",
                        "name": "kb_id",
                        "in": "query",
                        "required": true
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK",
                        "schema": {
                            "allOf": [
                                {
                                    "$ref": "#/definitions/domain.PWResponse"
                                },
                                {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "$ref": "#/definitions/domain.GetKBReleaseListResp"
                                        }
                                    }
                                }
                            ]
                        }
                    }
                }
            }
        },
        "/api/v1/knowledge_base/user/delete": {
            "delete": {
                "security": [
                    {
                        "bearerAuth": []
                    }
                ],
                "description": "Remove user from knowledge base",
                "consumes": [
                    "application/json"
                ],
                "produces": [
                    "application/json"
                ],
                "tags": [
                    "knowledge_base"
                ],
                "summary": "KBUserDelete",
                "parameters": [
                    {
                        "type": "string",
                        "name": "kb_id",
                        "in": "query",
                        "required": true
                    },
                    {
                        "type": "string",
                        "name": "user_id",
                        "in": "query",
                        "required": true
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK",
                        "schema": {
                            "$ref": "#/definitions/domain.Response"
                        }
                    }
                }
            }
        },
        "/api/v1/knowledge_base/user/invite": {
            "post": {
                "security": [
                    {
                        "bearerAuth": []
                    }
                ],
                "description": "Invite user to knowledge base",
                "consumes": [
                    "application/json"
                ],
                "produces": [
                    "application/json"
                ],
                "tags": [
                    "knowledge_base"
                ],
                "summary": "KBUserInvite",
                "parameters": [
                    {
                        "description": "Invite User Request",
                        "name": "param",
                        "in": "body",
                        "required": true,
                        "schema": {
                            "$ref": "#/definitions/v1.KBUserInviteReq"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK",
                        "schema": {
                            "$ref": "#/definitions/domain.Response"
                        }
                    }
                }
            }
        },
        "/api/v1/knowledge_base/user/list": {
            "get": {
                "security": [
                    {
                        "bearerAuth": []
                    }
                ],
                "description": "KBUserList",
                "consumes": [
                    "application/json"
                ],
                "produces": [
                    "application/json"
                ],
                "tags": [
                    "knowledge_base"
                ],
                "summary": "KBUserList",
                "parameters": [
                    {
                        "type": "string",
                        "description": "Knowledge Base ID",
                        "name": "kb_id",
                        "in": "query",
                        "required": true
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK",
                        "schema": {
                            "allOf": [
                                {
                                    "$ref": "#/definitions/domain.PWResponse"
                                },
                                {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "type": "array",
                                            "items": {
                                                "$ref": "#/definitions/v1.KBUserListItemResp"
                                            }
                                        }
                                    }
                                }
                            ]
                        }
                    }
                }
            }
        },
        "/api/v1/knowledge_base/user/update": {
            "patch": {
                "security": [
                    {
                        "bearerAuth": []
                    }
                ],
                "description": "Update user permission in knowledge base",
                "consumes": [
                    "application/json"
                ],
                "produces": [
                    "application/json"
                ],
                "tags": [
                    "knowledge_base"
                ],
                "summary": "KBUserUpdate",
                "parameters": [
                    {
                        "description": "Update User Permission Request",
                        "name": "param",
                        "in": "body",
                        "required": true,
                        "schema": {
                            "$ref": "#/definitions/v1.KBUserUpdateReq"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK",
                        "schema": {
                            "$ref": "#/definitions/domain.Response"
                        }
                    }
                }
            }
        },
        "/api/v1/model": {
            "put": {
                "description": "update model",
                "consumes": [
                    "application/json"
                ],
                "produces": [
                    "application/json"
                ],
                "tags": [
                    "model"
                ],
                "parameters": [
                    {
                        "description": "update model request",
                        "name": "model",
                        "in": "body",
                        "required": true,
                        "schema": {
                            "$ref": "#/definitions/domain.UpdateModelReq"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK",
                        "schema": {
                            "$ref": "#/definitions/domain.Response"
                        }
                    }
                }
            },
            "post": {
                "description": "create model",
                "consumes": [
                    "application/json"
                ],
                "produces": [
                    "application/json"
                ],
                "tags": [
                    "model"
                ],
                "summary": "create model",
                "parameters": [
                    {
                        "description": "create model request",
                        "name": "model",
                        "in": "body",
                        "required": true,
                        "schema": {
                            "$ref": "#/definitions/domain.CreateModelReq"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK",
                        "schema": {
                            "$ref": "#/definitions/domain.Response"
                        }
                    }
                }
            }
        },
        "/api/v1/model/check": {
            "post": {
                "description": "check model",
                "consumes": [
                    "application/json"
                ],
                "produces": [
                    "application/json"
                ],
                "tags": [
                    "model"
                ],
                "summary": "check model",
                "parameters": [
                    {
                        "description": "check model request",
                        "name": "model",
                        "in": "body",
                        "required": true,
                        "schema": {
                            "$ref": "#/definitions/github_com_chaitin_panda-wiki_domain.CheckModelReq"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK",
                        "schema": {
                            "allOf": [
                                {
                                    "$ref": "#/definitions/domain.Response"
                                },
                                {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "$ref": "#/definitions/github_com_chaitin_panda-wiki_domain.CheckModelResp"
                                        }
                                    }
                                }
                            ]
                        }
                    }
                }
            }
        },
        "/api/v1/model/list": {
            "get": {
                "description": "get model list",
                "consumes": [
                    "application/json"
                ],
                "produces": [
                    "application/json"
                ],
                "tags": [
                    "model"
                ],
                "summary": "get model list",
                "responses": {
                    "200": {
                        "description": "OK",
                        "schema": {
                            "allOf": [
                                {
                                    "$ref": "#/definitions/domain.PWResponse"
                                },
                                {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "$ref": "#/definitions/github_com_chaitin_panda-wiki_domain.ModelListItem"
                                        }
                                    }
                                }
                            ]
                        }
                    }
                }
            }
        },
        "/api/v1/model/mode-setting": {
            "get": {
                "description": "get current model mode setting including mode, API key and chat model",
                "consumes": [
                    "application/json"
                ],
                "produces": [
                    "application/json"
                ],
                "tags": [
                    "model"
                ],
                "summary": "get model mode setting",
                "responses": {
                    "200": {
                        "description": "OK",
                        "schema": {
                            "allOf": [
                                {
                                    "$ref": "#/definitions/domain.Response"
                                },
                                {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "$ref": "#/definitions/domain.ModelModeSetting"
                                        }
                                    }
                                }
                            ]
                        }
                    }
                }
            }
        },
        "/api/v1/model/provider/supported": {
            "post": {
                "description": "get provider supported model list",
                "consumes": [
                    "application/json"
                ],
                "produces": [
                    "application/json"
                ],
                "tags": [
                    "model"
                ],
                "summary": "get provider supported model list",
                "parameters": [
                    {
                        "description": "get supported model list request",
                        "name": "params",
                        "in": "body",
                        "required": true,
                        "schema": {
                            "$ref": "#/definitions/domain.GetProviderModelListReq"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK",
                        "schema": {
                            "allOf": [
                                {
                                    "$ref": "#/definitions/domain.PWResponse"
                                },
                                {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "$ref": "#/definitions/domain.GetProviderModelListResp"
                                        }
                                    }
                                }
                            ]
                        }
                    }
                }
            }
        },
        "/api/v1/model/switch-mode": {
            "post": {
                "description": "switch model mode between manual and auto",
                "consumes": [
                    "application/json"
                ],
                "produces": [
                    "application/json"
                ],
                "tags": [
                    "model"
                ],
                "summary": "switch mode",
                "parameters": [
                    {
                        "description": "switch mode request",
                        "name": "request",
                        "in": "body",
                        "required": true,
                        "schema": {
                            "$ref": "#/definitions/domain.SwitchModeReq"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK",
                        "schema": {
                            "allOf": [
                                {
                                    "$ref": "#/definitions/domain.Response"
                                },
                                {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "$ref": "#/definitions/domain.SwitchModeResp"
                                        }
                                    }
                                }
                            ]
                        }
                    }
                }
            }
        },
        "/api/v1/nav/add": {
            "post": {
                "security": [
                    {
                        "bearerAuth": []
                    }
                ],
                "description": "Add Nav",
                "consumes": [
                    "application/json"
                ],
                "produces": [
                    "application/json"
                ],
                "tags": [
                    "Nav"
                ],
                "summary": "添加分栏",
                "parameters": [
                    {
                        "description": "Params",
                        "name": "body",
                        "in": "body",
                        "required": true,
                        "schema": {
                            "$ref": "#/definitions/v1.NavAddReq"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK",
                        "schema": {
                            "$ref": "#/definitions/domain.PWResponse"
                        }
                    }
                }
            }
        },
        "/api/v1/nav/delete": {
            "delete": {
                "security": [
                    {
                        "bearerAuth": []
                    }
                ],
                "description": "DeleteNav Nav",
                "consumes": [
                    "application/json"
                ],
                "produces": [
                    "application/json"
                ],
                "tags": [
                    "Nav"
                ],
                "summary": "删除栏目",
                "parameters": [
                    {
                        "type": "string",
                        "name": "id",
                        "in": "query",
                        "required": true
                    },
                    {
                        "type": "string",
                        "name": "kb_id",
                        "in": "query",
                        "required": true
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK",
                        "schema": {
                            "$ref": "#/definitions/domain.PWResponse"
                        }
                    }
                }
            }
        },
        "/api/v1/nav/list": {
            "get": {
                "security": [
                    {
                        "bearerAuth": []
                    }
                ],
                "description": "Get Nav List",
                "consumes": [
                    "application/json"
                ],
                "produces": [
                    "application/json"
                ],
                "tags": [
                    "Nav"
                ],
                "summary": "获取分栏列表",
                "parameters": [
                    {
                        "type": "string",
                        "name": "kb_id",
                        "in": "query",
                        "required": true
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK",
                        "schema": {
                            "allOf": [
                                {
                                    "$ref": "#/definitions/domain.PWResponse"
                                },
                                {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "type": "array",
                                            "items": {
                                                "$ref": "#/definitions/v1.NavListResp"
                                            }
                                        }
                                    }
                                }
                            ]
                        }
                    }
                }
            }
        },
        "/api/v1/nav/move": {
            "post": {
                "security": [
                    {
                        "bearerAuth": []
                    }
                ],
                "description": "Move Nav",
                "consumes": [
                    "application/json"
                ],
                "produces": [
                    "application/json"
                ],
                "tags": [
                    "Nav"
                ],
                "summary": "移动栏目",
                "parameters": [
                    {
                        "description": "Params",
                        "name": "body",
                        "in": "body",
                        "required": true,
                        "schema": {
                            "$ref": "#/definitions/v1.NavMoveReq"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK",
                        "schema": {
                            "$ref": "#/defini
Download .txt
gitextract_zj65fk7g/

├── .gitattributes
├── .github/
│   ├── ISSUE_TEMPLATE/
│   │   ├── 功能建议.md
│   │   └── 故障报告.md
│   ├── PULL_REQUEST_TEMPLATE.md
│   └── workflows/
│       ├── backend.yml
│       ├── backend_check.yml
│       └── web.yml
├── .gitignore
├── .gitmodules
├── CODE_OF_CONDUCT.md
├── CONTRIBUTING.md
├── LICENSE
├── PROJECT_STRUCTURE.md
├── README.md
├── SECURITY.md
├── backend/
│   ├── .dockerignore
│   ├── .golangci.toml
│   ├── Dockerfile.api
│   ├── Dockerfile.api.pro
│   ├── Dockerfile.consumer
│   ├── Dockerfile.consumer.pro
│   ├── Makefile
│   ├── api/
│   │   ├── auth/
│   │   │   └── v1/
│   │   │       └── auth.go
│   │   ├── conversation/
│   │   │   └── v1/
│   │   │       └── conversation.go
│   │   ├── crawler/
│   │   │   └── v1/
│   │   │       ├── confluence.go
│   │   │       ├── crawler.go
│   │   │       ├── epub.go
│   │   │       ├── feishu.go
│   │   │       ├── mindoc.go
│   │   │       ├── notion.go
│   │   │       ├── siyuan.go
│   │   │       ├── wikijs.go
│   │   │       └── yuque.go
│   │   ├── kb/
│   │   │   └── v1/
│   │   │       └── kb.go
│   │   ├── nav/
│   │   │   └── v1/
│   │   │       └── nav.go
│   │   ├── node/
│   │   │   └── v1/
│   │   │       └── node.go
│   │   ├── openapi/
│   │   │   └── v1/
│   │   │       └── openapi.go
│   │   ├── share/
│   │   │   └── v1/
│   │   │       ├── auth.go
│   │   │       ├── common.go
│   │   │       ├── nav.go
│   │   │       ├── node.go
│   │   │       └── wechat.go
│   │   ├── stat/
│   │   │   └── v1/
│   │   │       └── stat.go
│   │   └── user/
│   │       └── v1/
│   │           └── user.go
│   ├── apm/
│   │   ├── provider.go
│   │   └── trace.go
│   ├── cSpell.json
│   ├── cmd/
│   │   ├── api/
│   │   │   ├── main.go
│   │   │   ├── wire.go
│   │   │   └── wire_gen.go
│   │   ├── consumer/
│   │   │   ├── main.go
│   │   │   ├── wire.go
│   │   │   └── wire_gen.go
│   │   └── migrate/
│   │       ├── main.go
│   │       ├── wire.go
│   │       └── wire_gen.go
│   ├── config/
│   │   ├── config.go
│   │   └── provider.go
│   ├── consts/
│   │   ├── admin.go
│   │   ├── app.go
│   │   ├── auth.go
│   │   ├── captcha.go
│   │   ├── consts.go
│   │   ├── contribute.go
│   │   ├── crawler.go
│   │   ├── license.go
│   │   ├── model.go
│   │   ├── node.go
│   │   ├── parse.go
│   │   └── system_setting.go
│   ├── docs/
│   │   ├── docs.go
│   │   ├── swagger.json
│   │   └── swagger.yaml
│   ├── domain/
│   │   ├── api_token.go
│   │   ├── app.go
│   │   ├── auth.go
│   │   ├── chat.go
│   │   ├── comment.go
│   │   ├── contribute.go
│   │   ├── conversation.go
│   │   ├── creation.go
│   │   ├── epub.go
│   │   ├── errors.go
│   │   ├── file.go
│   │   ├── icon.go
│   │   ├── ip.go
│   │   ├── json.go
│   │   ├── knowledge_base.go
│   │   ├── license.go
│   │   ├── llm.go
│   │   ├── model.go
│   │   ├── mq.go
│   │   ├── nav.go
│   │   ├── node.go
│   │   ├── notion.go
│   │   ├── openai.go
│   │   ├── openai_test.go
│   │   ├── pager.go
│   │   ├── prompt.go
│   │   ├── response.go
│   │   ├── setting.go
│   │   ├── siyuan.go
│   │   ├── sse_event.go
│   │   ├── stat.go
│   │   ├── system_setting.go
│   │   ├── user.go
│   │   ├── userfeedback.go
│   │   └── wechat.go
│   ├── go.mod
│   ├── go.sum
│   ├── handler/
│   │   ├── base.go
│   │   ├── mq/
│   │   │   ├── cron.go
│   │   │   ├── provider.go
│   │   │   ├── rag.go
│   │   │   └── rag_doc_update.go
│   │   ├── share/
│   │   │   ├── app.go
│   │   │   ├── auth.go
│   │   │   ├── captcha.go
│   │   │   ├── chat.go
│   │   │   ├── comment.go
│   │   │   ├── common.go
│   │   │   ├── coversation.go
│   │   │   ├── nav.go
│   │   │   ├── node.go
│   │   │   ├── openapi.go
│   │   │   ├── provider.go
│   │   │   ├── sitemap.go
│   │   │   ├── stat.go
│   │   │   └── wechat.go
│   │   └── v1/
│   │       ├── app.go
│   │       ├── auth.go
│   │       ├── comment.go
│   │       ├── conversation.go
│   │       ├── crawler.go
│   │       ├── creation.go
│   │       ├── file.go
│   │       ├── kb_user.go
│   │       ├── knowledge_base.go
│   │       ├── model.go
│   │       ├── nav.go
│   │       ├── node.go
│   │       ├── provider.go
│   │       ├── stat.go
│   │       └── user.go
│   ├── log/
│   │   ├── log.go
│   │   └── provider.go
│   ├── middleware/
│   │   ├── api_token.go
│   │   ├── auth.go
│   │   ├── jwt.go
│   │   ├── provider.go
│   │   ├── readonly.go
│   │   ├── session.go
│   │   └── share_auth.go
│   ├── migration/
│   │   ├── fns/
│   │   │   ├── 0001_migrate_node_version.go
│   │   │   ├── 0002_create_bot_auth.go
│   │   │   ├── 0003_fix_group_ids.go
│   │   │   ├── 0004_update_node_status_unreleased.go
│   │   │   ├── 0005_create_first_nav_tabs.go
│   │   │   └── provider.go
│   │   ├── func.go
│   │   ├── manager.go
│   │   └── provider.go
│   ├── mq/
│   │   ├── mq.go
│   │   ├── nats/
│   │   │   ├── consumer.go
│   │   │   ├── message.go
│   │   │   └── producer.go
│   │   └── types/
│   │       └── message.go
│   ├── pkg/
│   │   ├── anydoc/
│   │   │   ├── anydoc.go
│   │   │   ├── confluence.go
│   │   │   ├── dingtalk.go
│   │   │   ├── epub.go
│   │   │   ├── feishu.go
│   │   │   ├── mindoc.go
│   │   │   ├── notion.go
│   │   │   ├── req.go
│   │   │   ├── res.go
│   │   │   ├── rss.go
│   │   │   ├── sitemap.go
│   │   │   ├── siyuan.go
│   │   │   ├── wikijs.go
│   │   │   └── yuque.go
│   │   ├── bot/
│   │   │   ├── common.go
│   │   │   ├── dingtalk/
│   │   │   │   └── stream.go
│   │   │   ├── discord/
│   │   │   │   ├── discord_test.go
│   │   │   │   └── stream.go
│   │   │   ├── feishu/
│   │   │   │   └── stream.go
│   │   │   ├── lark/
│   │   │   │   └── client.go
│   │   │   ├── utils/
│   │   │   │   └── utils.go
│   │   │   ├── wechat/
│   │   │   │   ├── domain.go
│   │   │   │   └── wechat.go
│   │   │   ├── wechat_official_account/
│   │   │   │   └── official_account.go
│   │   │   ├── wechat_service/
│   │   │   │   ├── domain.go
│   │   │   │   ├── tools.go
│   │   │   │   └── wechat.go
│   │   │   └── wecom/
│   │   │       ├── ai_bot.go
│   │   │       └── crypt.go
│   │   ├── captcha/
│   │   │   └── captcha.go
│   │   ├── cas/
│   │   │   └── cas.go
│   │   ├── dingtalk/
│   │   │   └── dingtalk.go
│   │   ├── feishu/
│   │   │   └── feishu.go
│   │   ├── ldap/
│   │   │   └── ldap.go
│   │   ├── oauth/
│   │   │   ├── github.go
│   │   │   └── oauth.go
│   │   ├── ratelimit/
│   │   │   └── rate_limiter.go
│   │   └── wecom/
│   │       └── wecom.go
│   ├── pro_imports.go
│   ├── project-words.txt
│   ├── repo/
│   │   ├── cache/
│   │   │   ├── geo.go
│   │   │   ├── kb.go
│   │   │   └── provider.go
│   │   ├── ipdb/
│   │   │   ├── ip_addr.go
│   │   │   └── provider.go
│   │   ├── mq/
│   │   │   ├── provider.go
│   │   │   └── rag.go
│   │   └── pg/
│   │       ├── ap_token.go
│   │       ├── app.go
│   │       ├── auth.go
│   │       ├── block_word.go
│   │       ├── comment.go
│   │       ├── conversation.go
│   │       ├── knowledge_base.go
│   │       ├── mcp.go
│   │       ├── model.go
│   │       ├── nav.go
│   │       ├── node.go
│   │       ├── node_group.go
│   │       ├── node_stats.go
│   │       ├── prompt.go
│   │       ├── provider.go
│   │       ├── stat.go
│   │       ├── stat_hour.go
│   │       ├── system_setting.go
│   │       ├── user.go
│   │       ├── user_access.go
│   │       └── wechat.go
│   ├── server/
│   │   └── http/
│   │       ├── http.go
│   │       └── provider.go
│   ├── setup/
│   │   └── cert.go
│   ├── store/
│   │   ├── cache/
│   │   │   ├── provider.go
│   │   │   └── redis.go
│   │   ├── ipdb/
│   │   │   ├── ip2region.xdb
│   │   │   └── ipdb.go
│   │   ├── pg/
│   │   │   ├── migration/
│   │   │   │   ├── 000001_init.down.sql
│   │   │   │   ├── 000001_init.up.sql
│   │   │   │   ├── 000002_add_type_for_model.down.sql
│   │   │   │   ├── 000002_add_type_for_model.up.sql
│   │   │   │   ├── 000003_update_rerank_type.down.sql
│   │   │   │   ├── 000003_update_rerank_type.up.sql
│   │   │   │   ├── 000004_kb_dataset_id.down.sql
│   │   │   │   ├── 000004_kb_dataset_id.up.sql
│   │   │   │   ├── 000005_app_kb_id_type_uniq.down.sql
│   │   │   │   ├── 000005_app_kb_id_type_uniq.up.sql
│   │   │   │   ├── 000006_node_version.down.sql
│   │   │   │   ├── 000006_node_version.up.sql
│   │   │   │   ├── 000007_node_release_updated_at.down.sql
│   │   │   │   ├── 000007_node_release_updated_at.up.sql
│   │   │   │   ├── 000008_add_conversation_info.down.sql
│   │   │   │   ├── 000008_add_conversation_info.up.sql
│   │   │   │   ├── 000009_create_stat_pages.down.sql
│   │   │   │   ├── 000009_create_stat_pages.up.sql
│   │   │   │   ├── 000010_add_conversation_message_feedback.down.sql
│   │   │   │   ├── 000010_add_conversation_message_feedback.up.sql
│   │   │   │   ├── 000011_create_user_comment.down.sql
│   │   │   │   ├── 000011_create_user_comment.up.sql
│   │   │   │   ├── 000012_add_conversation_message_kb_id_parent_id.down.sql
│   │   │   │   ├── 000012_add_conversation_message_kb_id_parent_id.up.sql
│   │   │   │   ├── 000013_create_license.down.sql
│   │   │   │   ├── 000013_create_license.up.sql
│   │   │   │   ├── 000014_add_user_comment_status.down.sql
│   │   │   │   ├── 000014_add_user_comment_status.up.sql
│   │   │   │   ├── 000015_create_auth.down.sql
│   │   │   │   ├── 000015_create_auth.up.sql
│   │   │   │   ├── 000016_create_document_feedback.down.sql
│   │   │   │   ├── 000016_create_document_feedback.up.sql
│   │   │   │   ├── 000017_update_comversation_message_feedback.down.sql
│   │   │   │   ├── 000017_updtate_conversation_message_feedback.up.sql
│   │   │   │   ├── 000018_create_settings.down.sql
│   │   │   │   ├── 000018_create_settings.up.sql
│   │   │   │   ├── 000019_alter_stat_pages_type.down.sql
│   │   │   │   ├── 000019_alter_stat_pages_type.up.sql
│   │   │   │   ├── 000020_add_user_role_and_kb_users.down.sql
│   │   │   │   ├── 000020_add_user_role_and_kb_users.up.sql
│   │   │   │   ├── 000021_create_auth_groups.down.sql
│   │   │   │   ├── 000021_create_auth_groups.up.sql
│   │   │   │   ├── 000022_alter_model.down.sql
│   │   │   │   ├── 000022_alter_model.up.sql
│   │   │   │   ├── 000023_create_stat_page_hours.down.sql
│   │   │   │   ├── 000023_create_stat_page_hours.up.sql
│   │   │   │   ├── 000024_add_parent_id_to_auth_groups.down.sql
│   │   │   │   ├── 000024_add_parent_id_to_auth_groups.up.sql
│   │   │   │   ├── 000025_create_api_tokens_table.down.sql
│   │   │   │   ├── 000025_create_api_tokens_table.up.sql
│   │   │   │   ├── 000026_add_sync.down.sql
│   │   │   │   ├── 000026_add_sync.up.sql
│   │   │   │   ├── 000027_create_contributes_table.down.sql
│   │   │   │   ├── 000027_create_contributes_table.up.sql
│   │   │   │   ├── 000028_add_contributes_ip.down.sql
│   │   │   │   ├── 000028_add_contributes_ip.up.sql
│   │   │   │   ├── 000029_add_comment_pic_urls.down.sql
│   │   │   │   ├── 000029_add_comment_pic_urls.up.sql
│   │   │   │   ├── 000030_add_node_status_msg.down.sql
│   │   │   │   ├── 000030_add_node_status_msg.up.sql
│   │   │   │   ├── 000031_add_node_release_user_id.down.sql
│   │   │   │   ├── 000031_add_node_release_user_id.up.sql
│   │   │   │   ├── 000032_create_system_settings.down.sql
│   │   │   │   ├── 000032_create_system_settings.up.sql
│   │   │   │   ├── 000033_create_mcp_calls.down.sql
│   │   │   │   ├── 000033_create_mcp_calls.up.sql
│   │   │   │   ├── 000034_create_node_stats.down.sql
│   │   │   │   ├── 000034_create_node_stats.up.sql
│   │   │   │   ├── 000035_add_conversation_image_paths.down.sql
│   │   │   │   ├── 000035_add_conversation_image_paths.up.sql
│   │   │   │   ├── 000036_add_kb_release_publisher_id.down.sql
│   │   │   │   ├── 000036_add_kb_release_publisher_id.up.sql
│   │   │   │   ├── 000037_create_nav_tabs.down.sql
│   │   │   │   ├── 000037_create_nav_tabs.up.sql
│   │   │   │   ├── 000038_create_node_release_backups.down.sql
│   │   │   │   └── 000038_create_node_release_backups.up.sql
│   │   │   ├── pg.go
│   │   │   └── provider.go
│   │   ├── rag/
│   │   │   ├── ct.go
│   │   │   ├── html2md.go
│   │   │   └── rag.go
│   │   └── s3/
│   │       ├── minio.go
│   │       └── provider.go
│   ├── telemetry/
│   │   ├── aes.go
│   │   ├── client.go
│   │   ├── provider.go
│   │   └── version.go
│   ├── usecase/
│   │   ├── app.go
│   │   ├── auth.go
│   │   ├── auth_github.go
│   │   ├── chat.go
│   │   ├── comment.go
│   │   ├── conversation.go
│   │   ├── crawler.go
│   │   ├── creation.go
│   │   ├── dingtalk_bot.go
│   │   ├── file.go
│   │   ├── knowledge_base.go
│   │   ├── llm.go
│   │   ├── model.go
│   │   ├── nav.go
│   │   ├── node.go
│   │   ├── provider.go
│   │   ├── sitemap.go
│   │   ├── stat.go
│   │   ├── user.go
│   │   ├── wechat_app.go
│   │   ├── wechat_official_account.go
│   │   ├── wechat_service.go
│   │   └── wecom.go
│   └── utils/
│       ├── DFA.go
│       ├── epub.go
│       ├── feed.go
│       ├── file.go
│       ├── ip_addr.go
│       ├── processor.go
│       ├── time.go
│       └── utils.go
├── sdk/
│   └── rag/
│       ├── chunk.go
│       ├── client.go
│       ├── dataset.go
│       ├── document.go
│       ├── go.mod
│       ├── model_config.go
│       ├── models.go
│       └── retrieval.go
└── web/
    ├── .gitignore
    ├── .husky/
    │   └── pre-commit
    ├── .prettierignore
    ├── admin/
    │   ├── .dockerignore
    │   ├── .gitignore
    │   ├── .prettierignore
    │   ├── Dockerfile
    │   ├── Makefile
    │   ├── README.md
    │   ├── api-templates/
    │   │   ├── api.ejs
    │   │   ├── http-client.ejs
    │   │   └── procedure-call.ejs
    │   ├── eslint.config.js
    │   ├── index.html
    │   ├── nginx.conf
    │   ├── package.json
    │   ├── prettier.config.js
    │   ├── public/
    │   │   ├── echarts/
    │   │   │   └── china.js
    │   │   ├── geo/
    │   │   │   ├── geo.js
    │   │   │   └── world.json
    │   │   ├── panda-wiki.css
    │   │   ├── panda-wiki.js
    │   │   └── world.json
    │   ├── scripts/
    │   │   └── generate-routes.js
    │   ├── server.conf
    │   ├── src/
    │   │   ├── App.tsx
    │   │   ├── api/
    │   │   │   ├── index.tsx
    │   │   │   ├── request.ts
    │   │   │   └── type.ts
    │   │   ├── assets/
    │   │   │   ├── emoji-data/
    │   │   │   │   └── zh.json
    │   │   │   ├── fonts/
    │   │   │   │   ├── font.css
    │   │   │   │   ├── gilroy-bold.otf
    │   │   │   │   ├── gilroy-medium.otf
    │   │   │   │   └── gilroy-regular.otf
    │   │   │   ├── json/
    │   │   │   │   ├── coin.json
    │   │   │   │   ├── error.json
    │   │   │   │   ├── help-center.json
    │   │   │   │   ├── takeoff.json
    │   │   │   │   └── upgrade.json
    │   │   │   └── styles/
    │   │   │       ├── index.css
    │   │   │       └── markdown.css
    │   │   ├── components/
    │   │   │   ├── Avatar/
    │   │   │   │   └── index.tsx
    │   │   │   ├── BarTrend/
    │   │   │   │   └── index.tsx
    │   │   │   ├── Card/
    │   │   │   │   └── index.tsx
    │   │   │   ├── Cascader/
    │   │   │   │   └── index.tsx
    │   │   │   ├── CreateWikiModal/
    │   │   │   │   ├── index.tsx
    │   │   │   │   └── steps/
    │   │   │   │       ├── Step1Model.tsx
    │   │   │   │       ├── Step2Config.tsx
    │   │   │   │       ├── Step3Import.tsx
    │   │   │   │       ├── Step4Publish.tsx
    │   │   │   │       ├── Step5Test.tsx
    │   │   │   │       ├── Step6Decorate.tsx
    │   │   │   │       ├── Step7Complete.tsx
    │   │   │   │       ├── index.ts
    │   │   │   │       └── initData.ts
    │   │   │   ├── CustomImage/
    │   │   │   │   └── index.tsx
    │   │   │   ├── CustomModal/
    │   │   │   │   ├── components/
    │   │   │   │   │   ├── ShowContent.tsx
    │   │   │   │   │   ├── basicComponents/
    │   │   │   │   │   │   ├── DragBrand/
    │   │   │   │   │   │   │   ├── Item.tsx
    │   │   │   │   │   │   │   ├── SortableItem.tsx
    │   │   │   │   │   │   │   └── index.tsx
    │   │   │   │   │   │   ├── DragBtn/
    │   │   │   │   │   │   │   ├── Item.tsx
    │   │   │   │   │   │   │   ├── SortableItem.tsx
    │   │   │   │   │   │   │   └── index.tsx
    │   │   │   │   │   │   ├── DragSocialInfo/
    │   │   │   │   │   │   │   ├── Item.tsx
    │   │   │   │   │   │   │   ├── SortableItem.tsx
    │   │   │   │   │   │   │   └── index.tsx
    │   │   │   │   │   │   └── Switch.tsx
    │   │   │   │   │   ├── components/
    │   │   │   │   │   │   ├── ColorPickerField.tsx
    │   │   │   │   │   │   ├── ComponentBar.tsx
    │   │   │   │   │   │   ├── DragList.tsx
    │   │   │   │   │   │   ├── SortableItem.tsx
    │   │   │   │   │   │   ├── StyledCommon.tsx
    │   │   │   │   │   │   └── index.ts
    │   │   │   │   │   └── config/
    │   │   │   │   │       ├── BannerConfig/
    │   │   │   │   │       │   ├── HotSearchItem.tsx
    │   │   │   │   │       │   ├── Item.tsx
    │   │   │   │   │       │   └── index.tsx
    │   │   │   │   │       ├── BasicDocConfig/
    │   │   │   │   │       │   ├── Item.tsx
    │   │   │   │   │       │   └── index.tsx
    │   │   │   │   │       ├── BlockGridConfig/
    │   │   │   │   │       │   ├── Item.tsx
    │   │   │   │   │       │   └── index.tsx
    │   │   │   │   │       ├── CarouselConfig/
    │   │   │   │   │       │   ├── Item.tsx
    │   │   │   │   │       │   └── index.tsx
    │   │   │   │   │       ├── CaseConfig/
    │   │   │   │   │       │   ├── Item.tsx
    │   │   │   │   │       │   └── index.tsx
    │   │   │   │   │       ├── CommentConfig/
    │   │   │   │   │       │   ├── Item.tsx
    │   │   │   │   │       │   └── index.tsx
    │   │   │   │   │       ├── ConfigBar.tsx
    │   │   │   │   │       ├── DirDocConfig/
    │   │   │   │   │       │   ├── Item.tsx
    │   │   │   │   │       │   └── index.tsx
    │   │   │   │   │       ├── FaqConfig/
    │   │   │   │   │       │   ├── Item.tsx
    │   │   │   │   │       │   └── index.tsx
    │   │   │   │   │       ├── FeatureConfig/
    │   │   │   │   │       │   ├── Item.tsx
    │   │   │   │   │       │   └── index.tsx
    │   │   │   │   │       ├── FooterConfig.tsx
    │   │   │   │   │       ├── HeaderConfig.tsx
    │   │   │   │   │       ├── ImgTextConfig/
    │   │   │   │   │       │   └── index.tsx
    │   │   │   │   │       ├── MetricsConfig/
    │   │   │   │   │       │   ├── Item.tsx
    │   │   │   │   │       │   └── index.tsx
    │   │   │   │   │       ├── QuestionConfig/
    │   │   │   │   │       │   ├── Item.tsx
    │   │   │   │   │       │   └── index.tsx
    │   │   │   │   │       ├── SimpleDocConfig/
    │   │   │   │   │       │   ├── Item.tsx
    │   │   │   │   │       │   └── index.tsx
    │   │   │   │   │       ├── TextConfig/
    │   │   │   │   │       │   └── index.tsx
    │   │   │   │   │       └── type.ts
    │   │   │   │   ├── constants.tsx
    │   │   │   │   ├── index.tsx
    │   │   │   │   └── utils.ts
    │   │   │   ├── Drag/
    │   │   │   │   ├── DragRecommend/
    │   │   │   │   │   ├── Item.tsx
    │   │   │   │   │   ├── SortableItem.tsx
    │   │   │   │   │   └── index.tsx
    │   │   │   │   └── DragTree/
    │   │   │   │       ├── TreeItem.tsx
    │   │   │   │       ├── TreeMenu.tsx
    │   │   │   │       └── index.tsx
    │   │   │   ├── Emoji/
    │   │   │   │   └── index.tsx
    │   │   │   ├── EmptyState/
    │   │   │   │   └── index.tsx
    │   │   │   ├── Form/
    │   │   │   │   └── index.tsx
    │   │   │   ├── FreeSoloAutocomplete/
    │   │   │   │   └── index.tsx
    │   │   │   ├── Header/
    │   │   │   │   ├── Bread.tsx
    │   │   │   │   └── index.tsx
    │   │   │   ├── KB/
    │   │   │   │   ├── KBCreate.tsx
    │   │   │   │   ├── KBDelete.tsx
    │   │   │   │   ├── KBModify.tsx
    │   │   │   │   └── KBSelect.tsx
    │   │   │   ├── Loading/
    │   │   │   │   └── index.tsx
    │   │   │   ├── LottieIcon/
    │   │   │   │   └── index.tsx
    │   │   │   ├── MapChart/
    │   │   │   │   └── index.tsx
    │   │   │   ├── MarkDown/
    │   │   │   │   └── index.tsx
    │   │   │   ├── PieTrend/
    │   │   │   │   └── index.tsx
    │   │   │   ├── ShowText/
    │   │   │   │   └── index.tsx
    │   │   │   ├── Sidebar/
    │   │   │   │   ├── AuthTypeModal.tsx
    │   │   │   │   ├── Version.tsx
    │   │   │   │   └── index.tsx
    │   │   │   ├── Switch/
    │   │   │   │   └── index.tsx
    │   │   │   ├── System/
    │   │   │   │   ├── component/
    │   │   │   │   │   ├── AutoModelConfig.tsx
    │   │   │   │   │   ├── Member.tsx
    │   │   │   │   │   ├── MemberAdd.tsx
    │   │   │   │   │   ├── MemberDelete.tsx
    │   │   │   │   │   ├── MemberUpdate.tsx
    │   │   │   │   │   └── ModelConfig.tsx
    │   │   │   │   └── index.tsx
    │   │   │   ├── TreeDragSortable/
    │   │   │   │   ├── SortableTree.tsx
    │   │   │   │   ├── SortableTreeItem.tsx
    │   │   │   │   ├── SortingStrategy.ts
    │   │   │   │   ├── TreeItemWrapper.tsx
    │   │   │   │   ├── index.css
    │   │   │   │   ├── index.tsx
    │   │   │   │   ├── types.ts
    │   │   │   │   └── utilities.ts
    │   │   │   ├── UploadFile/
    │   │   │   │   ├── Drag.tsx
    │   │   │   │   ├── FileText.tsx
    │   │   │   │   └── index.tsx
    │   │   │   └── VersionMask/
    │   │   │       └── index.tsx
    │   │   ├── constant/
    │   │   │   ├── area.ts
    │   │   │   ├── enums.tsx
    │   │   │   ├── rag.ts
    │   │   │   ├── styles.ts
    │   │   │   └── version.ts
    │   │   ├── hooks/
    │   │   │   ├── index.tsx
    │   │   │   ├── useBindCaptcha.ts
    │   │   │   ├── useCommitPendingInput.tsx
    │   │   │   ├── useDebounceAppPreviewData.tsx
    │   │   │   ├── useURLSearchParams.tsx
    │   │   │   └── useVersionFeature.ts
    │   │   ├── layouts/
    │   │   │   └── index.tsx
    │   │   ├── main.tsx
    │   │   ├── pages/
    │   │   │   ├── 401/
    │   │   │   │   └── index.tsx
    │   │   │   ├── contribution/
    │   │   │   │   ├── ContributePreviewModal.tsx
    │   │   │   │   ├── DocModal.tsx
    │   │   │   │   ├── MarkdownPreviewModal.tsx
    │   │   │   │   └── index.tsx
    │   │   │   ├── conversation/
    │   │   │   │   ├── Detail.tsx
    │   │   │   │   ├── Search.tsx
    │   │   │   │   └── index.tsx
    │   │   │   ├── document/
    │   │   │   │   ├── component/
    │   │   │   │   │   ├── AddDocBtn.tsx
    │   │   │   │   │   ├── AddDocByType/
    │   │   │   │   │   │   ├── FileParse/
    │   │   │   │   │   │   │   └── index.tsx
    │   │   │   │   │   │   ├── FormSubmit/
    │   │   │   │   │   │   │   ├── FormInput.tsx
    │   │   │   │   │   │   │   └── index.tsx
    │   │   │   │   │   │   ├── ListRender/
    │   │   │   │   │   │   │   ├── Action.tsx
    │   │   │   │   │   │   │   ├── Item.tsx
    │   │   │   │   │   │   │   └── index.tsx
    │   │   │   │   │   │   ├── components/
    │   │   │   │   │   │   │   ├── StatusBackground.tsx
    │   │   │   │   │   │   │   └── StatusBadge.tsx
    │   │   │   │   │   │   ├── constants.ts
    │   │   │   │   │   │   ├── hooks/
    │   │   │   │   │   │   │   └── useGlobalQueue.ts
    │   │   │   │   │   │   ├── index.tsx
    │   │   │   │   │   │   └── util.ts
    │   │   │   │   │   ├── DocAddByCustomText.tsx
    │   │   │   │   │   ├── DocDelete.tsx
    │   │   │   │   │   ├── DocPropertiesModal.tsx
    │   │   │   │   │   ├── DocStatus.tsx
    │   │   │   │   │   ├── DocSummary.tsx
    │   │   │   │   │   ├── EditorCollaboration.tsx
    │   │   │   │   │   ├── MoveDocs.tsx
    │   │   │   │   │   ├── RagErrorReStart.tsx
    │   │   │   │   │   ├── Summary.tsx
    │   │   │   │   │   └── VersionRollback.tsx
    │   │   │   │   ├── editor/
    │   │   │   │   │   ├── Catalog/
    │   │   │   │   │   │   ├── KBSwitch.tsx
    │   │   │   │   │   │   └── index.tsx
    │   │   │   │   │   ├── edit/
    │   │   │   │   │   │   ├── AIGenerate.tsx
    │   │   │   │   │   │   ├── FullTextEditor.tsx
    │   │   │   │   │   │   ├── Header.tsx
    │   │   │   │   │   │   ├── Loading.tsx
    │   │   │   │   │   │   ├── Summary.tsx
    │   │   │   │   │   │   ├── Toc.tsx
    │   │   │   │   │   │   ├── Toolbar.tsx
    │   │   │   │   │   │   ├── Wrap.tsx
    │   │   │   │   │   │   └── index.tsx
    │   │   │   │   │   ├── history/
    │   │   │   │   │   │   └── index.tsx
    │   │   │   │   │   ├── index.tsx
    │   │   │   │   │   └── space/
    │   │   │   │   │       └── index.tsx
    │   │   │   │   └── layout/
    │   │   │   │       ├── DocPageHeader/
    │   │   │   │       │   ├── DocSearch.tsx
    │   │   │   │       │   └── index.tsx
    │   │   │   │       ├── DocPageList/
    │   │   │   │       │   ├── DocListModals.tsx
    │   │   │   │       │   ├── DocPageListContainer.tsx
    │   │   │   │       │   ├── DocPageListContent.tsx
    │   │   │   │       │   ├── index.tsx
    │   │   │   │       │   ├── types.ts
    │   │   │   │       │   ├── useDocTreeMenu.tsx
    │   │   │   │       │   └── utils.ts
    │   │   │   │       ├── DocPageNavs/
    │   │   │   │       │   ├── NavEditModal.tsx
    │   │   │   │       │   └── index.tsx
    │   │   │   │       └── index.tsx
    │   │   │   ├── feedback/
    │   │   │   │   ├── Comments.tsx
    │   │   │   │   ├── Detail.tsx
    │   │   │   │   ├── Evaluate.tsx
    │   │   │   │   └── index.tsx
    │   │   │   ├── login/
    │   │   │   │   └── index.tsx
    │   │   │   ├── release/
    │   │   │   │   ├── components/
    │   │   │   │   │   ├── VersionDelete.tsx
    │   │   │   │   │   ├── VersionPublish.tsx
    │   │   │   │   │   └── VersionReset.tsx
    │   │   │   │   └── index.tsx
    │   │   │   ├── setting/
    │   │   │   │   ├── component/
    │   │   │   │   │   ├── AddRecommendContent.tsx
    │   │   │   │   │   ├── AddRole.tsx
    │   │   │   │   │   ├── CardAI.tsx
    │   │   │   │   │   ├── CardAuth.tsx
    │   │   │   │   │   ├── CardBasicInfo.tsx
    │   │   │   │   │   ├── CardCatalog.tsx
    │   │   │   │   │   ├── CardCustom.tsx
    │   │   │   │   │   ├── CardFeedback.tsx
    │   │   │   │   │   ├── CardKB.tsx
    │   │   │   │   │   ├── CardListen.tsx
    │   │   │   │   │   ├── CardMCP.tsx
    │   │   │   │   │   ├── CardProxy.tsx
    │   │   │   │   │   ├── CardQaCopyright.tsx
    │   │   │   │   │   ├── CardRobot/
    │   │   │   │   │   │   └── WebComponent/
    │   │   │   │   │   │       ├── RecommendDocDragList.tsx
    │   │   │   │   │   │       └── index.tsx
    │   │   │   │   │   ├── CardRobot.tsx
    │   │   │   │   │   ├── CardRobotApi.tsx
    │   │   │   │   │   ├── CardRobotDing.tsx
    │   │   │   │   │   ├── CardRobotDiscord.tsx
    │   │   │   │   │   ├── CardRobotFeishu.tsx
    │   │   │   │   │   ├── CardRobotLark.tsx
    │   │   │   │   │   ├── CardRobotWechatOfficeAccount.tsx
    │   │   │   │   │   ├── CardRobotWecom.tsx
    │   │   │   │   │   ├── CardRobotWecomAIBot.tsx
    │   │   │   │   │   ├── CardRobotWecomService.tsx
    │   │   │   │   │   ├── CardSecurity.tsx
    │   │   │   │   │   ├── CardStyle.tsx
    │   │   │   │   │   ├── CardWeb.tsx
    │   │   │   │   │   ├── CardWebCustomCode.tsx
    │   │   │   │   │   ├── CardWebSEO.tsx
    │   │   │   │   │   ├── CardWebStats.tsx
    │   │   │   │   │   ├── Common.tsx
    │   │   │   │   │   ├── ConfigKB.tsx
    │   │   │   │   │   ├── UserGroup/
    │   │   │   │   │   │   ├── GroupTree.tsx
    │   │   │   │   │   │   └── index.tsx
    │   │   │   │   │   └── UserGroupModal.tsx
    │   │   │   │   └── index.tsx
    │   │   │   └── stat/
    │   │   │       ├── Statistic/
    │   │   │       │   ├── AreaMap.tsx
    │   │   │       │   ├── ClientStat.tsx
    │   │   │       │   ├── HostReferer.tsx
    │   │   │       │   ├── HotDocs.tsx
    │   │   │       │   ├── QAReferer.tsx
    │   │   │       │   ├── RTVisitor.tsx
    │   │   │       │   ├── TypeCount.tsx
    │   │   │       │   └── index.tsx
    │   │   │       └── index.tsx
    │   │   ├── request/
    │   │   │   ├── App.ts
    │   │   │   ├── Auth.ts
    │   │   │   ├── Comment.ts
    │   │   │   ├── Conversation.ts
    │   │   │   ├── Crawler.ts
    │   │   │   ├── Creation.ts
    │   │   │   ├── File.ts
    │   │   │   ├── KnowledgeBase.ts
    │   │   │   ├── Message.ts
    │   │   │   ├── Model.ts
    │   │   │   ├── Nav.ts
    │   │   │   ├── Node.ts
    │   │   │   ├── NodePermission.ts
    │   │   │   ├── Stat.ts
    │   │   │   ├── User.ts
    │   │   │   ├── httpClient.ts
    │   │   │   ├── index.ts
    │   │   │   ├── pro/
    │   │   │   │   ├── ApiToken.ts
    │   │   │   │   ├── Auth.ts
    │   │   │   │   ├── AuthGroup.ts
    │   │   │   │   ├── AuthOrg.ts
    │   │   │   │   ├── Block.ts
    │   │   │   │   ├── Comment.ts
    │   │   │   │   ├── Contribute.ts
    │   │   │   │   ├── DocumentFeedback.ts
    │   │   │   │   ├── License.ts
    │   │   │   │   ├── Node.ts
    │   │   │   │   ├── Prompt.ts
    │   │   │   │   ├── ShareAuth.ts
    │   │   │   │   ├── ShareContribute.ts
    │   │   │   │   ├── ShareFile.ts
    │   │   │   │   ├── ShareOpenapi.ts
    │   │   │   │   ├── httpClient.ts
    │   │   │   │   ├── index.ts
    │   │   │   │   └── types.ts
    │   │   │   └── types.ts
    │   │   ├── router.tsx
    │   │   ├── services/
    │   │   │   └── modelService.ts
    │   │   ├── store/
    │   │   │   ├── index.ts
    │   │   │   └── slices/
    │   │   │       ├── breadcrumb.ts
    │   │   │       └── config.ts
    │   │   ├── themes/
    │   │   │   ├── dark.ts
    │   │   │   ├── index.ts
    │   │   │   └── light.ts
    │   │   ├── utils/
    │   │   │   ├── drag.ts
    │   │   │   ├── fetch.ts
    │   │   │   ├── getBasePath.ts
    │   │   │   ├── getBasename.ts
    │   │   │   ├── index.ts
    │   │   │   ├── loadScript.ts
    │   │   │   ├── render.ts
    │   │   │   └── tree.ts
    │   │   └── vite-env.d.ts
    │   ├── ssl/
    │   │   ├── panda-wiki.crt
    │   │   └── panda-wiki.key
    │   ├── swagger.api.config.ts
    │   ├── tsconfig.app.json
    │   ├── tsconfig.json
    │   ├── tsconfig.node.json
    │   └── vite.config.ts
    ├── app/
    │   ├── .gitignore
    │   ├── .prettierignore
    │   ├── Dockerfile
    │   ├── Makefile
    │   ├── README.md
    │   ├── api-templates/
    │   │   ├── api.ejs
    │   │   ├── http-client.ejs
    │   │   └── procedure-call.ejs
    │   ├── eslint.config.mjs
    │   ├── new-types.d.ts
    │   ├── next.config.ts
    │   ├── package.json
    │   ├── prettier.config.js
    │   ├── public/
    │   │   ├── cap@0.0.6/
    │   │   │   └── cap_wasm_bg.wasm
    │   │   ├── widget-bot.css
    │   │   └── widget-bot.js
    │   ├── sentry.edge.config.ts
    │   ├── sentry.server.config.ts
    │   ├── src/
    │   │   ├── app/
    │   │   │   ├── (pages)/
    │   │   │   │   ├── (doc)/
    │   │   │   │   │   ├── editor/
    │   │   │   │   │   │   └── [[...id]]/
    │   │   │   │   │   │       └── page.tsx
    │   │   │   │   │   ├── home/
    │   │   │   │   │   │   └── page.tsx
    │   │   │   │   │   ├── layout.tsx
    │   │   │   │   │   ├── node/
    │   │   │   │   │   │   ├── NodeClientLayout.tsx
    │   │   │   │   │   │   ├── [id]/
    │   │   │   │   │   │   │   └── page.tsx
    │   │   │   │   │   │   ├── error.tsx
    │   │   │   │   │   │   ├── layout.tsx
    │   │   │   │   │   │   └── page.tsx
    │   │   │   │   │   └── welcome/
    │   │   │   │   │       └── page.tsx
    │   │   │   │   ├── auth/
    │   │   │   │   │   └── login/
    │   │   │   │   │       └── page.tsx
    │   │   │   │   ├── layout.tsx
    │   │   │   │   └── not-found.tsx
    │   │   │   ├── error.tsx
    │   │   │   ├── feedback/
    │   │   │   │   ├── layout.tsx
    │   │   │   │   └── page.tsx
    │   │   │   ├── global-error.tsx
    │   │   │   ├── globals.css
    │   │   │   ├── h5-chat/
    │   │   │   │   └── page.tsx
    │   │   │   ├── layout.tsx
    │   │   │   ├── markdown.css
    │   │   │   ├── not-found.tsx
    │   │   │   └── widget/
    │   │   │       ├── layout.tsx
    │   │   │       └── page.tsx
    │   │   ├── assets/
    │   │   │   ├── fonts/
    │   │   │   │   ├── gilroy-bold-700.otf
    │   │   │   │   ├── gilroy-light-300.otf
    │   │   │   │   ├── gilroy-medium-500.otf
    │   │   │   │   └── gilroy-regular-400.otf
    │   │   │   └── type/
    │   │   │       └── index.ts
    │   │   ├── components/
    │   │   │   ├── QaModal/
    │   │   │   │   ├── AiQaContent.tsx
    │   │   │   │   ├── SearchDocContent.tsx
    │   │   │   │   ├── StyledComponents.tsx
    │   │   │   │   ├── constants.ts
    │   │   │   │   ├── index.tsx
    │   │   │   │   ├── types.ts
    │   │   │   │   └── utils.ts
    │   │   │   ├── commentInput/
    │   │   │   │   └── index.tsx
    │   │   │   ├── docFab/
    │   │   │   │   └── index.tsx
    │   │   │   ├── docSkeleton/
    │   │   │   │   └── index.tsx
    │   │   │   ├── emoji/
    │   │   │   │   ├── emoji-data/
    │   │   │   │   │   └── zh.json
    │   │   │   │   └── index.tsx
    │   │   │   ├── emptyDocPlaceholder/
    │   │   │   │   └── index.tsx
    │   │   │   ├── error/
    │   │   │   │   └── index.tsx
    │   │   │   ├── feedback/
    │   │   │   │   └── index.tsx
    │   │   │   ├── footer/
    │   │   │   │   ├── Overlay.tsx
    │   │   │   │   └── index.tsx
    │   │   │   ├── header/
    │   │   │   │   ├── index.tsx
    │   │   │   │   └── themeSwitch.tsx
    │   │   │   ├── icons/
    │   │   │   │   └── index.tsx
    │   │   │   ├── markdown/
    │   │   │   │   ├── index.tsx
    │   │   │   │   └── mermaid.tsx
    │   │   │   ├── markdown2/
    │   │   │   │   ├── imageRenderer.tsx
    │   │   │   │   ├── incrementalRenderer.tsx
    │   │   │   │   ├── index.tsx
    │   │   │   │   ├── mermaidRenderer.tsx
    │   │   │   │   └── thinkingRenderer.tsx
    │   │   │   ├── menuSelect/
    │   │   │   │   └── index.tsx
    │   │   │   ├── scrollToTopFab/
    │   │   │   │   └── index.tsx
    │   │   │   └── watermark/
    │   │   │       ├── WaterMarkProvider.tsx
    │   │   │       └── index.tsx
    │   │   ├── constant/
    │   │   │   └── index.ts
    │   │   ├── hooks/
    │   │   │   ├── index.ts
    │   │   │   ├── useBasePath.ts
    │   │   │   ├── useCopy.tsx
    │   │   │   ├── useScroll.ts
    │   │   │   ├── useSmartScroll.ts
    │   │   │   └── useSyncNavByDocId.ts
    │   │   ├── instrumentation-client.ts
    │   │   ├── instrumentation.ts
    │   │   ├── provider/
    │   │   │   ├── index.tsx
    │   │   │   └── themeStore.tsx
    │   │   ├── proxy.ts
    │   │   ├── request/
    │   │   │   ├── ShareApp.ts
    │   │   │   ├── ShareAuth.ts
    │   │   │   ├── ShareCaptcha.ts
    │   │   │   ├── ShareChat.ts
    │   │   │   ├── ShareChatSearch.ts
    │   │   │   ├── ShareComment.ts
    │   │   │   ├── ShareConversation.ts
    │   │   │   ├── ShareFile.ts
    │   │   │   ├── ShareNav.ts
    │   │   │   ├── ShareNode.ts
    │   │   │   ├── ShareOpenapi.ts
    │   │   │   ├── ShareStat.ts
    │   │   │   ├── Wechat.ts
    │   │   │   ├── Widget.ts
    │   │   │   ├── httpClient.ts
    │   │   │   ├── index.ts
    │   │   │   ├── pro/
    │   │   │   │   ├── ApiToken.ts
    │   │   │   │   ├── Auth.ts
    │   │   │   │   ├── AuthGroup.ts
    │   │   │   │   ├── AuthOrg.ts
    │   │   │   │   ├── Block.ts
    │   │   │   │   ├── Comment.ts
    │   │   │   │   ├── Contribute.ts
    │   │   │   │   ├── DocumentFeedback.ts
    │   │   │   │   ├── License.ts
    │   │   │   │   ├── Node.ts
    │   │   │   │   ├── Prompt.ts
    │   │   │   │   ├── ShareAuth.ts
    │   │   │   │   ├── ShareContribute.ts
    │   │   │   │   ├── ShareFile.ts
    │   │   │   │   ├── ShareOpenapi.ts
    │   │   │   │   ├── httpClient.ts
    │   │   │   │   ├── index.ts
    │   │   │   │   ├── otherCustomer.ts
    │   │   │   │   └── types.ts
    │   │   │   └── types.ts
    │   │   ├── theme.ts
    │   │   ├── utils/
    │   │   │   ├── cookie.ts
    │   │   │   ├── fetch.ts
    │   │   │   ├── getBasePath.ts
    │   │   │   ├── getDocContentSx.ts
    │   │   │   ├── getImagePath.ts
    │   │   │   ├── getServerHeader.ts
    │   │   │   ├── index.ts
    │   │   │   └── tree.ts
    │   │   └── views/
    │   │       ├── auth/
    │   │       │   └── login.tsx
    │   │       ├── chat/
    │   │       │   ├── ChatLoading.tsx
    │   │       │   └── constant.ts
    │   │       ├── editor/
    │   │       │   ├── edit/
    │   │       │   │   ├── AIGenerate.tsx
    │   │       │   │   ├── ConfirmModal.tsx
    │   │       │   │   ├── Header.tsx
    │   │       │   │   ├── Loading.tsx
    │   │       │   │   ├── Summary.tsx
    │   │       │   │   ├── Toc.tsx
    │   │       │   │   ├── Toolbar.tsx
    │   │       │   │   ├── Wrap.tsx
    │   │       │   │   ├── constant.ts
    │   │       │   │   └── index.tsx
    │   │       │   └── index.tsx
    │   │       ├── feedback/
    │   │       │   └── index.tsx
    │   │       ├── h5Chat/
    │   │       │   └── index.tsx
    │   │       ├── home/
    │   │       │   └── index.tsx
    │   │       ├── node/
    │   │       │   ├── Catalog.tsx
    │   │       │   ├── CatalogFolder.tsx
    │   │       │   ├── CatalogH5.tsx
    │   │       │   ├── DocAnchor.tsx
    │   │       │   ├── DocContent.tsx
    │   │       │   ├── NavBar.tsx
    │   │       │   ├── NoPermission.tsx
    │   │       │   ├── components/
    │   │       │   │   ├── AdjacentDocNav.tsx
    │   │       │   │   ├── CommentSection.tsx
    │   │       │   │   └── DocMetaInfo.tsx
    │   │       │   ├── folderList.tsx
    │   │       │   └── index.tsx
    │   │       └── widget/
    │   │           ├── AiQaContent.tsx
    │   │           ├── SearchDocContent.tsx
    │   │           ├── StyledComponents.tsx
    │   │           ├── constants.ts
    │   │           ├── index.tsx
    │   │           ├── types.ts
    │   │           └── utils.ts
    │   ├── swagger.api.config.ts
    │   └── tsconfig.json
    ├── package.json
    ├── packages/
    │   ├── icons/
    │   │   ├── package.json
    │   │   ├── scripts/
    │   │   │   └── generate.ts
    │   │   ├── src/
    │   │   │   ├── Icon123.tsx
    │   │   │   ├── IconA302ai.tsx
    │   │   │   ├── IconAAIshezhi.tsx
    │   │   │   ├── IconACaidan.tsx
    │   │   │   ├── IconAChilunshezhisheding.tsx
    │   │   │   ├── IconADiancaiWeixuanzhong2.tsx
    │   │   │   ├── IconADiscordjiqiren.tsx
    │   │   │   ├── IconAIcon_huaban1fuben22.tsx
    │   │   │   ├── IconAKuaizhao2.tsx
    │   │   │   ├── IconALianjie5.tsx
    │   │   │   ├── IconAShijian2.tsx
    │   │   │   ├── IconAWebyingyong.tsx
    │   │   │   ├── IconAWenhao8.tsx
    │   │   │   ├── IconAZiyuan2.tsx
    │   │   │   ├── IconAdd.tsx
    │   │   │   ├── IconAihubmix.tsx
    │   │   │   ├── IconAiyingyong1.tsx
    │   │   │   ├── IconAlayanew.tsx
    │   │   │   ├── IconAliyunbailian.tsx
    │   │   │   ├── IconAnthropic.tsx
    │   │   │   ├── IconAwsBedrock.tsx
    │   │   │   ├── IconAzure.tsx
    │   │   │   ├── IconBaichuan.tsx
    │   │   │   ├── IconBaiduyun.tsx
    │   │   │   ├── IconBaizhiyunlogo.tsx
    │   │   │   ├── IconBanben.tsx
    │   │   │   ├── IconBanben1.tsx
    │   │   │   ├── IconBangzhuwendang1.tsx
    │   │   │   ├── IconBaocun.tsx
    │   │   │   ├── IconBiaoge1.tsx
    │   │   │   ├── IconBukejian.tsx
    │   │   │   ├── IconBurncloud.tsx
    │   │   │   ├── IconBytedance.tsx
    │   │   │   ├── IconC183jianjumidu.tsx
    │   │   │   ├── IconCaiMoren.tsx
    │   │   │   ├── IconCaiXuanzhong.tsx
    │   │   │   ├── IconCephalon.tsx
    │   │   │   ├── IconChahao.tsx
    │   │   │   ├── IconChahao1.tsx
    │   │   │   ├── IconChakan.tsx
    │   │   │   ├── IconChangjianwenti.tsx
    │   │   │   ├── IconChatgpt.tsx
    │   │   │   ├── IconChilun.tsx
    │   │   │   ├── IconChuangjian.tsx
    │   │   │   ├── IconCohere.tsx
    │   │   │   ├── IconCorrection.tsx
    │   │   │   ├── IconDJzhinengzhaiyao.tsx
    │   │   │   ├── IconDMXAPI.tsx
    │   │   │   ├── IconDandulogo.tsx
    │   │   │   ├── IconDanliao.tsx
    │   │   │   ├── IconDanliao1.tsx
    │   │   │   ├── IconDanwenzi.tsx
    │   │   │   ├── IconDaochu.tsx
    │   │   │   ├── IconDashScope.tsx
    │   │   │   ├── IconDeepseek.tsx
    │   │   │   ├── IconDengchu.tsx
    │   │   │   ├── IconDiancaiWeixuanzhong.tsx
    │   │   │   ├── IconDianhua.tsx
    │   │   │   ├── IconDianhua1.tsx
    │   │   │   ├── IconDianzanMoren.tsx
    │   │   │   ├── IconDianzanWeixuanzhong.tsx
    │   │   │   ├── IconDianzanXuanzhong.tsx
    │   │   │   ├── IconDianzanXuanzhong1.tsx
    │   │   │   ├── IconDingdingdingd.tsx
    │   │   │   ├── IconDingdingjiqiren.tsx
    │   │   │   ├── IconDingzi.tsx
    │   │   │   ├── IconDitu_diqiu.tsx
    │   │   │   ├── IconDoubao.tsx
    │   │   │   ├── IconDouyin.tsx
    │   │   │   ├── IconDouyin3.tsx
    │   │   │   ├── IconDrag.tsx
    │   │   │   ├── IconDuihao.tsx
    │   │   │   ├── IconDuihao1.tsx
    │   │   │   ├── IconDuihualishi1.tsx
    │   │   │   ├── IconExcel1.tsx
    │   │   │   ├── IconFabu.tsx
    │   │   │   ├── IconFankui.tsx
    │   │   │   ├── IconFankuiwenti.tsx
    │   │   │   ├── IconFasong.tsx
    │   │   │   ├── IconFeishu.tsx
    │   │   │   ├── IconFeishujiqiren.tsx
    │   │   │   ├── IconFenxi.tsx
    │   │   │   ├── IconFenxiang.tsx
    │   │   │   ├── IconFireworks.tsx
    │   │   │   ├── IconFuzhi.tsx
    │   │   │   ├── IconFuzhi1.tsx
    │   │   │   ├── IconGemini.tsx
    │   │   │   ├── IconGeminiAi.tsx
    │   │   │   ├── IconGengduo.tsx
    │   │   │   ├── IconGengxinshijian.tsx
    │   │   │   ├── IconGitHub1.tsx
    │   │   │   ├── IconGitee_ai.tsx
    │   │   │   ├── IconGithub.tsx
    │   │   │   ├── IconGongjuTool.tsx
    │   │   │   ├── IconGongxian.tsx
    │   │   │   ├── IconGpustack.tsx
    │   │   │   ├── IconGraphRag.tsx
    │   │   │   ├── IconGrok.tsx
    │   │   │   ├── IconGroup.tsx
    │   │   │   ├── IconGuajian.tsx
    │   │   │   ├── IconHuanyuan.tsx
    │   │   │   ├── IconHuoshanyinqing.tsx
    │   │   │   ├── IconHyperbolic.tsx
    │   │   │   ├── IconIPdizhijiancha.tsx
    │   │   │   ├── IconIcon_tool_close.tsx
    │   │   │   ├── IconImageError.tsx
    │   │   │   ├── IconInfini.tsx
    │   │   │   ├── IconJiage.tsx
    │   │   │   ├── IconJiahao.tsx
    │   │   │   ├── IconJiajianzujianjiahao.tsx
    │   │   │   ├── IconJianyiwendang.tsx
    │   │   │   ├── IconJichuwendang.tsx
    │   │   │   ├── IconJina.tsx
    │   │   │   ├── IconJinggao.tsx
    │   │   │   ├── IconJinsousuo.tsx
    │   │   │   ├── IconJiugongge.tsx
    │   │   │   ├── IconJushou.tsx
    │   │   │   ├── IconKefu.tsx
    │   │   │   ├── IconKehuanli.tsx
    │   │   │   ├── IconKehupingjia.tsx
    │   │   │   ├── IconKejian.tsx
    │   │   │   ├── IconKim.tsx
    │   │   │   ├── IconKoulingrenzheng.tsx
    │   │   │   ├── IconLDAP.tsx
    │   │   │   ├── IconLanyun.tsx
    │   │   │   ├── IconLepton.tsx
    │   │   │   ├── IconLianjiezu.tsx
    │   │   │   ├── IconLianjiezu1.tsx
    │   │   │   ├── IconLingyiwanwu.tsx
    │   │   │   ├── IconLmstudio.tsx
    │   │   │   ├── IconLogoGroq.tsx
    │   │   │   ├── IconLunbotu.tsx
    │   │   │   ├── IconMianbaoxie.tsx
    │   │   │   ├── IconMima.tsx
    │   │   │   ├── IconMingliangmoshi.tsx
    │   │   │   ├── IconMiniMax.tsx
    │   │   │   ├── IconMistral.tsx
    │   │   │   ├── IconMixedbread.tsx
    │   │   │   ├── IconModaGPT.tsx
    │   │   │   ├── IconMoxing.tsx
    │   │   │   ├── IconMulu.tsx
    │   │   │   ├── IconMulushouqi.tsx
    │   │   │   ├── IconMuluwendang.tsx
    │   │   │   ├── IconMuluzhankai.tsx
    │   │   │   ├── IconNeirongdagang.tsx
    │   │   │   ├── IconNeirongguanli.tsx
    │   │   │   ├── IconNeteaseYoudao.tsx
    │   │   │   ├── IconNewapi.tsx
    │   │   │   ├── IconNomic_logo.tsx
    │   │   │   ├── IconO3.tsx
    │   │   │   ├── IconOcoolai.tsx
    │   │   │   ├── IconOllama.tsx
    │   │   │   ├── IconOpenrouter.tsx
    │   │   │   ├── IconPCduan.tsx
    │   │   │   ├── IconPDF.tsx
    │   │   │   ├── IconPageview1.tsx
    │   │   │   ├── IconPaperFull.tsx
    │   │   │   ├── IconPaperPlaneFill.tsx
    │   │   │   ├── IconPeizhi.tsx
    │   │   │   ├── IconPerplexity.tsx
    │   │   │   ├── IconPlainText1.tsx
    │   │   │   ├── IconPpio.tsx
    │   │   │   ├── IconQQ.tsx
    │   │   │   ├── IconQQ1.tsx
    │   │   │   ├── IconQiehuan.tsx
    │   │   │   ├── IconQiniuyun.tsx
    │   │   │   ├── IconQiyeweixinjiqiren.tsx
    │   │   │   ├── IconQiyeweixinkefu.tsx
    │   │   │   ├── IconQiyewx.tsx
    │   │   │   ├── IconQunliao.tsx
    │   │   │   ├── IconQunliao1.tsx
    │   │   │   ├── IconQuseqi.tsx
    │   │   │   ├── IconSetFull.tsx
    │   │   │   ├── IconShanchu.tsx
    │   │   │   ├── IconShanchu1.tsx
    │   │   │   ├── IconShanchu2.tsx
    │   │   │   ├── IconShangchuan.tsx
    │   │   │   ├── IconShangjiantou.tsx
    │   │   │   ├── IconShengji.tsx
    │   │   │   ├── IconShensemoshi.tsx
    │   │   │   ├── IconShoujihao.tsx
    │   │   │   ├── IconShuaxin.tsx
    │   │   │   ├── IconShuzikapian.tsx
    │   │   │   ├── IconSousuo.tsx
    │   │   │   ├── IconStep.tsx
    │   │   │   ├── IconTengxunhunyuan.tsx
    │   │   │   ├── IconTengxunyun.tsx
    │   │   │   ├── IconTexing.tsx
    │   │   │   ├── IconTextColor.tsx
    │   │   │   ├── IconTianjia.tsx
    │   │   │   ├── IconTianjiachengyuan.tsx
    │   │   │   ├── IconTianjiawendang.tsx
    │   │   │   ├── IconTianyiyun.tsx
    │   │   │   ├── IconTingzhi.tsx
    │   │   │   ├── IconTips.tsx
    │   │   │   ├── IconTokenflux.tsx
    │   │   │   ├── IconTokenguanli.tsx
    │   │   │   ├── IconTongjifenxi1.tsx
    │   │   │   ├── IconTuozhuai.tsx
    │   │   │   ├── IconTupian.tsx
    │   │   │   ├── IconTushu.tsx
    │   │   │   ├── IconUI_icon_wangfanjiantou.tsx
    │   │   │   ├── IconUnknow1.tsx
    │   │   │   ├── IconWangyeguajian.tsx
    │   │   │   ├── IconWebPage1.tsx
    │   │   │   ├── IconWeibo.tsx
    │   │   │   ├── IconWeibo1.tsx
    │   │   │   ├── IconWeixingongzhonghao.tsx
    │   │   │   ├── IconWeixingongzhonghaoDaiyanse.tsx
    │   │   │   ├── IconWendajiqiren.tsx
    │   │   │   ├── IconWenhao.tsx
    │   │   │   ├── IconWenjian.tsx
    │   │   │   ├── IconWenjianjia.tsx
    │   │   │   ├── IconWenjianjiaKai.tsx
    │   │   │   ├── IconWenzi.tsx
    │   │   │   ├── IconWenzishuliang.tsx
    │   │   │   ├── IconWord.tsx
    │   │   │   ├── IconXiajiantou.tsx
    │   │   │   ├── IconXiala.tsx
    │   │   │   ├── IconXiala1.tsx
    │   │   │   ├── IconXialaCopy.tsx
    │   │   │   ├── IconXiaohongshu.tsx
    │   │   │   ├── IconXiaohongshuHui.tsx
    │   │   │   ├── IconXinduihua.tsx
    │   │   │   ├── IconXinference.tsx
    │   │   │   ├── IconXingxing.tsx
    │   │   │   ├── IconYanzhengma.tsx
    │   │   │   ├── IconYidongduan.tsx
    │   │   │   ├── IconYingweida.tsx
    │   │   │   ├── IconYonghuwenjianjia.tsx
    │   │   │   ├── IconYoutuzuozi.tsx
    │   │   │   ├── IconYouxiang.tsx
    │   │   │   ├── IconYouxiang1.tsx
    │   │   │   ├── IconYulan.tsx
    │   │   │   ├── IconYunhang.tsx
    │   │   │   ├── IconYunhang1.tsx
    │   │   │   ├── IconYunpan.tsx
    │   │   │   ├── IconZaixianzixun.tsx
    │   │   │   ├── IconZhanghao.tsx
    │   │   │   ├── IconZhiding.tsx
    │   │   │   ├── IconZhinengwenda.tsx
    │   │   │   ├── IconZhipuAI.tsx
    │   │   │   ├── IconZhipuqingyan.tsx
    │   │   │   ├── IconZhishikulogo.tsx
    │   │   │   ├── IconZiti.tsx
    │   │   │   ├── IconZujian.tsx
    │   │   │   ├── IconZuotuyouzi.tsx
    │   │   │   ├── IconZuzhi.tsx
    │   │   │   └── index.tsx
    │   │   └── tsconfig.json
    │   ├── themes/
    │   │   ├── package.json
    │   │   ├── src/
    │   │   │   ├── black.ts
    │   │   │   ├── blue.ts
    │   │   │   ├── constants.ts
    │   │   │   ├── dark.ts
    │   │   │   ├── darkDeepForest.ts
    │   │   │   ├── darkGold.ts
    │   │   │   ├── deepTeal.ts
    │   │   │   ├── electricBlue.ts
    │   │   │   ├── green.ts
    │   │   │   ├── index.ts
    │   │   │   ├── light.ts
    │   │   │   ├── orange.ts
    │   │   │   ├── purple.ts
    │   │   │   └── red.ts
    │   │   ├── theme.d.ts
    │   │   └── tsconfig.json
    │   └── ui/
    │       ├── env.d.ts
    │       ├── package.json
    │       ├── src/
    │       │   ├── banner/
    │       │   │   └── index.tsx
    │       │   ├── basicDoc/
    │       │   │   └── index.tsx
    │       │   ├── blockGrid/
    │       │   │   └── index.tsx
    │       │   ├── carousel/
    │       │   │   ├── index.css
    │       │   │   └── index.tsx
    │       │   ├── case/
    │       │   │   └── index.tsx
    │       │   ├── comment/
    │       │   │   └── index.tsx
    │       │   ├── component/
    │       │   │   └── styledCommon/
    │       │   │       └── index.tsx
    │       │   ├── constants/
    │       │   │   └── index.ts
    │       │   ├── dirDoc/
    │       │   │   └── index.tsx
    │       │   ├── faq/
    │       │   │   └── index.tsx
    │       │   ├── feature/
    │       │   │   └── index.tsx
    │       │   ├── footer/
    │       │   │   ├── Overlay.tsx
    │       │   │   └── index.tsx
    │       │   ├── header/
    │       │   │   ├── NavBtns.tsx
    │       │   │   └── index.tsx
    │       │   ├── hooks/
    │       │   │   └── useGsapAnimation.tsx
    │       │   ├── imgText/
    │       │   │   └── index.tsx
    │       │   ├── index.tsx
    │       │   ├── metrics/
    │       │   │   └── index.tsx
    │       │   ├── question/
    │       │   │   └── index.tsx
    │       │   ├── simpleDoc/
    │       │   │   └── index.tsx
    │       │   ├── text/
    │       │   │   └── index.tsx
    │       │   ├── utils.ts
    │       │   ├── welcomeFooter/
    │       │   │   ├── Overlay.tsx
    │       │   │   └── index.tsx
    │       │   └── welcomeHeader/
    │       │       ├── NavBtns.tsx
    │       │       └── index.tsx
    │       └── tsconfig.json
    ├── pnpm-workspace.yaml
    ├── prettier.config.js
    └── tsconfig.base.json
Download .txt
Showing preview only (308K chars total). Download the full file or copy to clipboard to get everything.
SYMBOL INDEX (3392 symbols across 534 files)

FILE: backend/api/auth/v1/auth.go
  type AuthGetReq (line 9) | type AuthGetReq struct
  type AuthGetResp (line 14) | type AuthGetResp struct
  type AuthItem (line 22) | type AuthItem struct
  type AuthSetReq (line 32) | type AuthSetReq struct
  type AuthSetResp (line 40) | type AuthSetResp struct
  type AuthDeleteReq (line 42) | type AuthDeleteReq struct
  type AuthDeleteResp (line 47) | type AuthDeleteResp struct

FILE: backend/api/conversation/v1/conversation.go
  type GetConversationDetailReq (line 3) | type GetConversationDetailReq struct
  type GetConversationDetailResp (line 8) | type GetConversationDetailResp struct
  type GetMessageDetailReq (line 11) | type GetMessageDetailReq struct
  type GetMessageDetailResp (line 16) | type GetMessageDetailResp struct

FILE: backend/api/crawler/v1/confluence.go
  type ConfluenceParseReq (line 3) | type ConfluenceParseReq struct
  type ConfluenceParseItem (line 7) | type ConfluenceParseItem struct
  type ConfluenceParseResp (line 13) | type ConfluenceParseResp struct
  type ConfluenceScrapeReq (line 18) | type ConfluenceScrapeReq struct
  type ConfluenceScrapeResp (line 24) | type ConfluenceScrapeResp struct

FILE: backend/api/crawler/v1/crawler.go
  type CrawlerParseReq (line 8) | type CrawlerParseReq struct
  type CrawlerParseResp (line 17) | type CrawlerParseResp struct
  type CrawlerExportReq (line 22) | type CrawlerExportReq struct
  type CrawlerExportResp (line 30) | type CrawlerExportResp struct
  type CrawlerResultReq (line 34) | type CrawlerResultReq struct
  type CrawlerResultResp (line 38) | type CrawlerResultResp struct
  type CrawlerResultsReq (line 43) | type CrawlerResultsReq struct
  type CrawlerResultsResp (line 47) | type CrawlerResultsResp struct
  type CrawlerResultItem (line 51) | type CrawlerResultItem struct

FILE: backend/api/crawler/v1/epub.go
  type EpubParseReq (line 3) | type EpubParseReq struct
  type EpubParseResp (line 9) | type EpubParseResp struct

FILE: backend/api/crawler/v1/feishu.go
  type FeishuSpaceListReq (line 3) | type FeishuSpaceListReq struct
  type FeishuSpaceListResp (line 8) | type FeishuSpaceListResp struct
  type FeishuSearchWikiReq (line 13) | type FeishuSearchWikiReq struct
  type FeishuSearchWikiResp (line 20) | type FeishuSearchWikiResp struct
  type FeishuListCloudDocReq (line 28) | type FeishuListCloudDocReq struct
  type FeishuListCloudDocResp (line 34) | type FeishuListCloudDocResp struct
  type FeishuGetDocReq (line 42) | type FeishuGetDocReq struct
  type FeishuGetDocResp (line 50) | type FeishuGetDocResp struct

FILE: backend/api/crawler/v1/mindoc.go
  type MindocParseReq (line 3) | type MindocParseReq struct
  type MindocParseItem (line 7) | type MindocParseItem struct
  type MindocParseResp (line 13) | type MindocParseResp struct
  type MindocScrapeReq (line 18) | type MindocScrapeReq struct
  type MindocScrapeResp (line 24) | type MindocScrapeResp struct

FILE: backend/api/crawler/v1/notion.go
  type NotionParseReq (line 3) | type NotionParseReq struct
  type NotionParseResp (line 6) | type NotionParseResp struct
  type NotionParseItem (line 11) | type NotionParseItem struct
  type NotionScrapeReq (line 16) | type NotionScrapeReq struct
  type NotionScrapeResp (line 22) | type NotionScrapeResp struct

FILE: backend/api/crawler/v1/siyuan.go
  type SiyuanParseReq (line 3) | type SiyuanParseReq struct
  type SiyuanParseItem (line 7) | type SiyuanParseItem struct
  type SiyuanParseResp (line 13) | type SiyuanParseResp struct
  type SiyuanScrapeReq (line 18) | type SiyuanScrapeReq struct
  type SiyuanScrapeResp (line 24) | type SiyuanScrapeResp struct

FILE: backend/api/crawler/v1/wikijs.go
  type WikijsParseReq (line 3) | type WikijsParseReq struct
  type WikijsParseItem (line 7) | type WikijsParseItem struct
  type WikijsParseResp (line 12) | type WikijsParseResp struct
  type WikijsScrapeReq (line 17) | type WikijsScrapeReq struct
  type WikijsScrapeResp (line 23) | type WikijsScrapeResp struct

FILE: backend/api/crawler/v1/yuque.go
  type YuqueParseReq (line 3) | type YuqueParseReq struct
  type YuqueParseResp (line 9) | type YuqueParseResp struct
  type YuqueParseItem (line 13) | type YuqueParseItem struct

FILE: backend/api/kb/v1/kb.go
  type KBUserListReq (line 7) | type KBUserListReq struct
  type KBUserListItemResp (line 11) | type KBUserListItemResp struct
  type KBUserInviteReq (line 18) | type KBUserInviteReq struct
  type KBUserInviteResp (line 24) | type KBUserInviteResp struct
  type KBUserUpdateReq (line 27) | type KBUserUpdateReq struct
  type KBUserUpdateResp (line 33) | type KBUserUpdateResp struct
  type KBUserDeleteReq (line 36) | type KBUserDeleteReq struct
  type KBUserDeleteResp (line 41) | type KBUserDeleteResp struct

FILE: backend/api/nav/v1/nav.go
  type NavListReq (line 5) | type NavListReq struct
  type NavAddReq (line 9) | type NavAddReq struct
  type NavUpdateReq (line 15) | type NavUpdateReq struct
  type NavDeleteReq (line 21) | type NavDeleteReq struct
  type NavMoveReq (line 26) | type NavMoveReq struct
  type NavListResp (line 33) | type NavListResp struct

FILE: backend/api/node/v1/node.go
  type GetNodeDetailReq (line 9) | type GetNodeDetailReq struct
  type NodeDetailResp (line 15) | type NodeDetailResp struct
  type NodePermissionReq (line 37) | type NodePermissionReq struct
  type NodePermissionResp (line 42) | type NodePermissionResp struct
  type NodePermissionEditReq (line 50) | type NodePermissionEditReq struct
  type NodePermissionEditResp (line 59) | type NodePermissionEditResp struct
  type NodeRestudyReq (line 62) | type NodeRestudyReq struct
  type NodeRestudyResp (line 67) | type NodeRestudyResp struct
  type NodeStatsReq (line 70) | type NodeStatsReq struct
  type NodeStatsResp (line 74) | type NodeStatsResp struct
  type NodeMoveNavReq (line 80) | type NodeMoveNavReq struct
  type NodeListGroupNavReq (line 86) | type NodeListGroupNavReq struct
  type NodeListGroupNavResp (line 92) | type NodeListGroupNavResp struct

FILE: backend/api/openapi/v1/openapi.go
  type GitHubCallbackReq (line 3) | type GitHubCallbackReq struct
  type GitHubCallbackResp (line 8) | type GitHubCallbackResp struct

FILE: backend/api/share/v1/auth.go
  type AuthLoginSimpleReq (line 5) | type AuthLoginSimpleReq struct
  type AuthLoginSimpleResp (line 9) | type AuthLoginSimpleResp struct
  type AuthGetReq (line 12) | type AuthGetReq struct
  type AuthGetResp (line 14) | type AuthGetResp struct
  type AuthGitHubReq (line 20) | type AuthGitHubReq struct
  type AuthGitHubResp (line 25) | type AuthGitHubResp struct
  type GitHubCallbackReq (line 29) | type GitHubCallbackReq struct
  type GitHubCallbackResp (line 34) | type GitHubCallbackResp struct

FILE: backend/api/share/v1/common.go
  type ShareFileUploadReq (line 3) | type ShareFileUploadReq struct
  type FileUploadResp (line 9) | type FileUploadResp struct
  type ShareFileUploadUrlReq (line 13) | type ShareFileUploadUrlReq struct
  type ShareFileUploadUrlResp (line 19) | type ShareFileUploadUrlResp struct

FILE: backend/api/share/v1/nav.go
  type ShareNavListReq (line 3) | type ShareNavListReq struct

FILE: backend/api/share/v1/node.go
  type ShareNodeDetailResp (line 9) | type ShareNodeDetailResp struct
  type NodeListGroupNavResp (line 31) | type NodeListGroupNavResp struct

FILE: backend/api/share/v1/wechat.go
  type WechatAppInfoResp (line 3) | type WechatAppInfoResp struct

FILE: backend/api/stat/v1/stat.go
  type StatInstantCountReq (line 8) | type StatInstantCountReq struct
  type StatInstantPagesReq (line 12) | type StatInstantPagesReq struct
  type StatHotPagesReq (line 16) | type StatHotPagesReq struct
  type StatCountReq (line 21) | type StatCountReq struct
  type StatCountResp (line 26) | type StatCountResp struct
  type StatRefererHostsReq (line 33) | type StatRefererHostsReq struct
  type StatBrowsersReq (line 38) | type StatBrowsersReq struct
  type StatGeoCountReq (line 43) | type StatGeoCountReq struct
  type StatConversationDistributionReq (line 48) | type StatConversationDistributionReq struct
  type StatConversationDistributionResp (line 53) | type StatConversationDistributionResp struct

FILE: backend/api/user/v1/user.go
  type CreateUserReq (line 9) | type CreateUserReq struct
  type CreateUserResp (line 15) | type CreateUserResp struct
  type UserInfoResp (line 19) | type UserInfoResp struct
  type UserListReq (line 28) | type UserListReq struct
  type UserListItemResp (line 31) | type UserListItemResp struct
  type LoginReq (line 39) | type LoginReq struct
  type LoginResp (line 44) | type LoginResp struct
  type UserListResp (line 48) | type UserListResp struct
  type ResetPasswordReq (line 52) | type ResetPasswordReq struct
  type DeleteUserReq (line 57) | type DeleteUserReq struct

FILE: backend/apm/trace.go
  type Tracer (line 19) | type Tracer struct
  function NewTracer (line 23) | func NewTracer(config *config.Config) (*Tracer, error) {

FILE: backend/cmd/api/main.go
  function main (line 17) | func main() {

FILE: backend/cmd/api/wire.go
  function createApp (line 16) | func createApp() (*App, error) {
  type App (line 32) | type App struct

FILE: backend/cmd/api/wire_gen.go
  function createApp (line 34) | func createApp() (*App, error) {
  type App (line 212) | type App struct

FILE: backend/cmd/consumer/main.go
  function main (line 7) | func main() {

FILE: backend/cmd/consumer/wire.go
  function createApp (line 14) | func createApp() (*App, error) {
  type App (line 26) | type App struct

FILE: backend/cmd/consumer/wire_gen.go
  function createApp (line 28) | func createApp() (*App, error) {
  type App (line 108) | type App struct

FILE: backend/cmd/migrate/main.go
  function main (line 3) | func main() {

FILE: backend/cmd/migrate/wire.go
  function createApp (line 13) | func createApp() (*App, error) {
  type App (line 25) | type App struct

FILE: backend/cmd/migrate/wire_gen.go
  function createApp (line 27) | func createApp() (*App, error) {
  type App (line 97) | type App struct

FILE: backend/config/config.go
  type Config (line 11) | type Config struct
    method GetString (line 229) | func (*Config) GetString(key string) string {
    method GetInt (line 233) | func (*Config) GetInt(key string) int {
    method GetUint64 (line 237) | func (*Config) GetUint64(key string) uint64 {
    method GetBool (line 241) | func (*Config) GetBool(key string) bool {
    method GetStringSlice (line 245) | func (*Config) GetStringSlice(key string) []string {
    method GetFloat64 (line 249) | func (*Config) GetFloat64(key string) float64 {
  type LogConfig (line 26) | type LogConfig struct
  type HTTPConfig (line 30) | type HTTPConfig struct
  type PGConfig (line 34) | type PGConfig struct
  type MQConfig (line 38) | type MQConfig struct
  type NATSConfig (line 43) | type NATSConfig struct
  type RAGConfig (line 49) | type RAGConfig struct
  type CTRAGConfig (line 54) | type CTRAGConfig struct
  type RedisConfig (line 59) | type RedisConfig struct
  type AuthConfig (line 64) | type AuthConfig struct
  type JWTConfig (line 69) | type JWTConfig struct
  type S3Config (line 73) | type S3Config struct
  type SentryConfig (line 79) | type SentryConfig struct
  function NewConfig (line 84) | func NewConfig() (*Config, error) {
  function overrideWithEnv (line 162) | func overrideWithEnv(c *Config) {

FILE: backend/consts/admin.go
  type UserKBPermission (line 3) | type UserKBPermission
  constant UserKBPermissionNull (line 6) | UserKBPermissionNull        UserKBPermission = ""
  constant UserKBPermissionNotNull (line 7) | UserKBPermissionNotNull     UserKBPermission = "not null"
  constant UserKBPermissionFullControl (line 8) | UserKBPermissionFullControl UserKBPermission = "full_control"
  constant UserKBPermissionDocManage (line 9) | UserKBPermissionDocManage   UserKBPermission = "doc_manage"
  constant UserKBPermissionDataOperate (line 10) | UserKBPermissionDataOperate UserKBPermission = "data_operate"
  type UserRole (line 13) | type UserRole
  constant UserRoleAdmin (line 16) | UserRoleAdmin UserRole = "admin"
  constant UserRoleUser (line 17) | UserRoleUser  UserRole = "user"

FILE: backend/consts/app.go
  type CopySetting (line 3) | type CopySetting
  constant CopySettingNone (line 6) | CopySettingNone     CopySetting = ""
  constant CopySettingAppend (line 7) | CopySettingAppend   CopySetting = "append"
  constant CopySettingDisabled (line 8) | CopySettingDisabled CopySetting = "disabled"
  type WatermarkSetting (line 11) | type WatermarkSetting
  constant WatermarkDisabled (line 14) | WatermarkDisabled WatermarkSetting = ""
  constant WatermarkHidden (line 15) | WatermarkHidden   WatermarkSetting = "hidden"
  constant WatermarkVisible (line 16) | WatermarkVisible  WatermarkSetting = "visible"
  type HomePageSetting (line 19) | type HomePageSetting
  constant HomePageSettingDoc (line 22) | HomePageSettingDoc    HomePageSetting = "doc"
  constant HomePageSettingCustom (line 23) | HomePageSettingCustom HomePageSetting = "custom"

FILE: backend/consts/auth.go
  type SourceType (line 3) | type SourceType
    method Name (line 30) | func (s SourceType) Name() string {
  constant SourceTypeDingTalk (line 10) | SourceTypeDingTalk              SourceType = "dingtalk"
  constant SourceTypeFeishu (line 11) | SourceTypeFeishu                SourceType = "feishu"
  constant SourceTypeWeCom (line 12) | SourceTypeWeCom                 SourceType = "wecom"
  constant SourceTypeOAuth (line 13) | SourceTypeOAuth                 SourceType = "oauth"
  constant SourceTypeGitHub (line 14) | SourceTypeGitHub                SourceType = "github"
  constant SourceTypeCAS (line 15) | SourceTypeCAS                   SourceType = "cas"
  constant SourceTypeLDAP (line 16) | SourceTypeLDAP                  SourceType = "ldap"
  constant SourceTypeWidget (line 17) | SourceTypeWidget                SourceType = "widget"
  constant SourceTypeDingtalkBot (line 18) | SourceTypeDingtalkBot           SourceType = "dingtalk_bot"
  constant SourceTypeFeishuBot (line 19) | SourceTypeFeishuBot             SourceType = "feishu_bot"
  constant SourceTypeLarkBot (line 20) | SourceTypeLarkBot               SourceType = "lark_bot"
  constant SourceTypeWechatBot (line 21) | SourceTypeWechatBot             SourceType = "wechat_bot"
  constant SourceTypeWecomAIBot (line 22) | SourceTypeWecomAIBot            SourceType = "wecom_ai_bot"
  constant SourceTypeWechatServiceBot (line 23) | SourceTypeWechatServiceBot      SourceType = "wechat_service_bot"
  constant SourceTypeDiscordBot (line 24) | SourceTypeDiscordBot            SourceType = "discord_bot"
  constant SourceTypeWechatOfficialAccount (line 25) | SourceTypeWechatOfficialAccount SourceType = "wechat_official_account"
  constant SourceTypeOpenAIAPI (line 26) | SourceTypeOpenAIAPI             SourceType = "openai_api"
  constant SourceTypeMcpServer (line 27) | SourceTypeMcpServer             SourceType = "mcp_server"
  type AuthType (line 57) | type AuthType
  constant AuthTypeNull (line 60) | AuthTypeNull       AuthType = ""
  constant AuthTypeSimple (line 61) | AuthTypeSimple     AuthType = "simple"
  constant AuthTypeEnterprise (line 62) | AuthTypeEnterprise AuthType = "enterprise"

FILE: backend/consts/captcha.go
  type RedeemCaptchaReq (line 3) | type RedeemCaptchaReq struct

FILE: backend/consts/consts.go
  type StatDay (line 3) | type StatDay
  constant StatDay1 (line 6) | StatDay1  StatDay = 1
  constant StatDay7 (line 7) | StatDay7  StatDay = 7
  constant StatDay30 (line 8) | StatDay30 StatDay = 30
  constant StatDay90 (line 9) | StatDay90 StatDay = 90

FILE: backend/consts/contribute.go
  type ContributeStatus (line 3) | type ContributeStatus
  constant ContributeStatusPending (line 6) | ContributeStatusPending  ContributeStatus = "pending"
  constant ContributeStatusApproved (line 7) | ContributeStatusApproved ContributeStatus = "approved"
  constant ContributeStatusRejected (line 8) | ContributeStatusRejected ContributeStatus = "rejected"
  type ContributeType (line 11) | type ContributeType
  constant ContributeTypeAdd (line 14) | ContributeTypeAdd  ContributeType = "add"
  constant ContributeTypeEdit (line 15) | ContributeTypeEdit ContributeType = "edit"

FILE: backend/consts/crawler.go
  type CrawlerStatus (line 3) | type CrawlerStatus
  constant CrawlerStatusPending (line 6) | CrawlerStatusPending   CrawlerStatus = "pending"
  constant CrawlerStatusInProcess (line 7) | CrawlerStatusInProcess CrawlerStatus = "in_process"
  constant CrawlerStatusCompleted (line 8) | CrawlerStatusCompleted CrawlerStatus = "completed"
  constant CrawlerStatusFailed (line 9) | CrawlerStatusFailed    CrawlerStatus = "failed"

FILE: backend/consts/license.go
  type contextKey (line 7) | type contextKey
  constant ContextKeyEdition (line 9) | ContextKeyEdition contextKey = "edition"
  type LicenseEdition (line 11) | type LicenseEdition
  constant LicenseEditionFree (line 14) | LicenseEditionFree       LicenseEdition = 0
  constant LicenseEditionProfession (line 15) | LicenseEditionProfession LicenseEdition = 1
  constant LicenseEditionEnterprise (line 16) | LicenseEditionEnterprise LicenseEdition = 2
  constant LicenseEditionBusiness (line 17) | LicenseEditionBusiness   LicenseEdition = 3
  function GetLicenseEdition (line 20) | func GetLicenseEdition(c echo.Context) LicenseEdition {

FILE: backend/consts/model.go
  type AutoModeDefaultModel (line 3) | type AutoModeDefaultModel
  constant AutoModeDefaultChatModel (line 6) | AutoModeDefaultChatModel       AutoModeDefaultModel = "deepseek-chat"
  constant AutoModeDefaultEmbeddingModel (line 7) | AutoModeDefaultEmbeddingModel  AutoModeDefaultModel = "bge-m3"
  constant AutoModeDefaultRerankModel (line 8) | AutoModeDefaultRerankModel     AutoModeDefaultModel = "bge-reranker-v2-m3"
  constant AutoModeDefaultAnalysisModel (line 9) | AutoModeDefaultAnalysisModel   AutoModeDefaultModel = "qwen2.5-3b-instruct"
  constant AutoModeDefaultAnalysisVLModel (line 10) | AutoModeDefaultAnalysisVLModel AutoModeDefaultModel = "qwen-vl-max-latest"
  function GetAutoModeDefaultModel (line 13) | func GetAutoModeDefaultModel(modelType string) string {
  type ModelSettingMode (line 30) | type ModelSettingMode
  constant ModelSettingModeManual (line 33) | ModelSettingModeManual ModelSettingMode = "manual"
  constant ModelSettingModeAuto (line 34) | ModelSettingModeAuto   ModelSettingMode = "auto"
  constant AutoModeBaseURL (line 38) | AutoModeBaseURL = "https://model-square.app.baizhi.cloud/v1"

FILE: backend/consts/node.go
  type NodeAccessPerm (line 3) | type NodeAccessPerm
  constant NodeAccessPermOpen (line 6) | NodeAccessPermOpen    NodeAccessPerm = "open"
  constant NodeAccessPermPartial (line 7) | NodeAccessPermPartial NodeAccessPerm = "partial"
  constant NodeAccessPermClosed (line 8) | NodeAccessPermClosed  NodeAccessPerm = "closed"
  type NodePermName (line 11) | type NodePermName
  constant NodePermNameVisible (line 14) | NodePermNameVisible    NodePermName = "visible"
  constant NodePermNameVisitable (line 15) | NodePermNameVisitable  NodePermName = "visitable"
  constant NodePermNameAnswerable (line 16) | NodePermNameAnswerable NodePermName = "answerable"
  type NodeRagInfoStatus (line 19) | type NodeRagInfoStatus
  constant NodeRagStatusPending (line 22) | NodeRagStatusPending    NodeRagInfoStatus = "PENDING"
  constant NodeRagStatusRunning (line 23) | NodeRagStatusRunning    NodeRagInfoStatus = "RUNNING"
  constant NodeRagStatusFailed (line 24) | NodeRagStatusFailed     NodeRagInfoStatus = "FAILED"
  constant NodeRagStatusSucceeded (line 25) | NodeRagStatusSucceeded  NodeRagInfoStatus = "SUCCEEDED"
  constant NodeRagStatusReindexing (line 26) | NodeRagStatusReindexing NodeRagInfoStatus = "REINDEX"

FILE: backend/consts/parse.go
  type CrawlerSource (line 3) | type CrawlerSource
    method Type (line 32) | func (c CrawlerSource) Type() CrawlerSourceType {
  constant CrawlerSourceUrl (line 7) | CrawlerSourceUrl      CrawlerSource = "url"
  constant CrawlerSourceRSS (line 8) | CrawlerSourceRSS      CrawlerSource = "rss"
  constant CrawlerSourceSitemap (line 9) | CrawlerSourceSitemap  CrawlerSource = "sitemap"
  constant CrawlerSourceNotion (line 10) | CrawlerSourceNotion   CrawlerSource = "notion"
  constant CrawlerSourceFeishu (line 11) | CrawlerSourceFeishu   CrawlerSource = "feishu"
  constant CrawlerSourceDingtalk (line 12) | CrawlerSourceDingtalk CrawlerSource = "dingtalk"
  constant CrawlerSourceFile (line 15) | CrawlerSourceFile       CrawlerSource = "file"
  constant CrawlerSourceEpub (line 16) | CrawlerSourceEpub       CrawlerSource = "epub"
  constant CrawlerSourceYuque (line 17) | CrawlerSourceYuque      CrawlerSource = "yuque"
  constant CrawlerSourceSiyuan (line 18) | CrawlerSourceSiyuan     CrawlerSource = "siyuan"
  constant CrawlerSourceMindoc (line 19) | CrawlerSourceMindoc     CrawlerSource = "mindoc"
  constant CrawlerSourceWikijs (line 20) | CrawlerSourceWikijs     CrawlerSource = "wikijs"
  constant CrawlerSourceConfluence (line 21) | CrawlerSourceConfluence CrawlerSource = "confluence"
  type CrawlerSourceType (line 24) | type CrawlerSourceType
  constant CrawlerSourceTypeFile (line 27) | CrawlerSourceTypeFile CrawlerSourceType = "file"
  constant CrawlerSourceTypeUrl (line 28) | CrawlerSourceTypeUrl  CrawlerSourceType = "url"
  constant CrawlerSourceTypeKey (line 29) | CrawlerSourceTypeKey  CrawlerSourceType = "key"

FILE: backend/consts/system_setting.go
  type SystemSettingKey (line 3) | type SystemSettingKey
  constant SystemSettingModelMode (line 6) | SystemSettingModelMode SystemSettingKey = "model_setting_mode"
  constant SystemSettingUpload (line 7) | SystemSettingUpload    SystemSettingKey = "upload"

FILE: backend/docs/docs.go
  constant docTemplate (line 6) | docTemplate = `{
  function init (line 9717) | func init() {

FILE: backend/domain/api_token.go
  type APIToken (line 10) | type APIToken struct
    method TableName (line 21) | func (APIToken) TableName() string {
  type CtxAuthInfo (line 25) | type CtxAuthInfo struct
  type contextKey (line 32) | type contextKey
  constant CtxAuthInfoKey (line 35) | CtxAuthInfoKey contextKey = "ctx_auth_info"
  function GetAuthInfoFromCtx (line 38) | func GetAuthInfoFromCtx(c context.Context) *CtxAuthInfo {

FILE: backend/domain/app.go
  type AppType (line 13) | type AppType
    method ToSourceType (line 45) | func (t AppType) ToSourceType() consts.SourceType {
  constant AppTypeWeb (line 16) | AppTypeWeb AppType = iota + 1
  constant AppTypeWidget (line 17) | AppTypeWidget
  constant AppTypeDingTalkBot (line 18) | AppTypeDingTalkBot
  constant AppTypeFeishuBot (line 19) | AppTypeFeishuBot
  constant AppTypeWechatBot (line 20) | AppTypeWechatBot
  constant AppTypeWechatServiceBot (line 21) | AppTypeWechatServiceBot
  constant AppTypeDisCordBot (line 22) | AppTypeDisCordBot
  constant AppTypeWechatOfficialAccount (line 23) | AppTypeWechatOfficialAccount
  constant AppTypeOpenAIAPI (line 24) | AppTypeOpenAIAPI
  constant AppTypeWecomAIBot (line 25) | AppTypeWecomAIBot
  constant AppTypeLarkBot (line 26) | AppTypeLarkBot
  constant AppTypeMcpServer (line 27) | AppTypeMcpServer
  type App (line 74) | type App struct
  type AppSettings (line 86) | type AppSettings struct
    method Scan (line 464) | func (s *AppSettings) Scan(value any) error {
    method Value (line 472) | func (s AppSettings) Value() (driver.Value, error) {
  type WeChatAppAdvancedSetting (line 178) | type WeChatAppAdvancedSetting struct
  type StatsSetting (line 186) | type StatsSetting struct
  type ConversationSetting (line 190) | type ConversationSetting struct
  type WebAppLandingTheme (line 195) | type WebAppLandingTheme struct
  type MCPServerSettings (line 199) | type MCPServerSettings struct
  type MCPToolSettings (line 205) | type MCPToolSettings struct
  type LarkBotSettings (line 210) | type LarkBotSettings struct
  type BannerConfig (line 218) | type BannerConfig struct
  type BasicDocConfig (line 235) | type BasicDocConfig struct
  type DirDocConfig (line 240) | type DirDocConfig struct
  type SimpleDocConfig (line 246) | type SimpleDocConfig struct
  type CarouselConfig (line 251) | type CarouselConfig struct
  type FaqConfig (line 261) | type FaqConfig struct
  type TextConfig (line 271) | type TextConfig struct
  type MetricsConfig (line 275) | type MetricsConfig struct
  type CaseConfig (line 284) | type CaseConfig struct
  type CommentConfig (line 293) | type CommentConfig struct
  type FeatureConfig (line 304) | type FeatureConfig struct
  type ImgTextConfig (line 313) | type ImgTextConfig struct
  type TextImgConfig (line 322) | type TextImgConfig struct
  type QuestionConfig (line 331) | type QuestionConfig struct
  type BlockGridConfig (line 339) | type BlockGridConfig struct
  type WebAppLandingConfig (line 349) | type WebAppLandingConfig struct
  type WecomAIBotSettings (line 370) | type WecomAIBotSettings struct
  type DisclaimerSettings (line 376) | type DisclaimerSettings struct
  type ContributeSettings (line 380) | type ContributeSettings struct
  type OpenAIAPIBotSettings (line 384) | type OpenAIAPIBotSettings struct
  type WebAppCustomSettings (line 389) | type WebAppCustomSettings struct
  type SocialMediaAccount (line 397) | type SocialMediaAccount struct
  type WebAppCommentSettings (line 405) | type WebAppCommentSettings struct
  type AIFeedbackSettings (line 410) | type AIFeedbackSettings struct
  type ThemeAndStyle (line 415) | type ThemeAndStyle struct
  type CatalogSettings (line 420) | type CatalogSettings struct
  type FooterSettings (line 426) | type FooterSettings struct
  type WidgetBotSettings (line 436) | type WidgetBotSettings struct
  type BrandGroup (line 454) | type BrandGroup struct
  type Link (line 459) | type Link struct
  type AppDetailResp (line 476) | type AppDetailResp struct
  type AppSettingsResp (line 488) | type AppSettingsResp struct
    method Scan (line 604) | func (s *AppSettingsResp) Scan(value any) error {
    method Value (line 612) | func (s AppSettingsResp) Value() (driver.Value, error) {
  type WebAppLandingConfigResp (line 582) | type WebAppLandingConfigResp struct
  type UpdateAppReq (line 616) | type UpdateAppReq struct
  type CreateAppReq (line 622) | type CreateAppReq struct
  type AppInfoResp (line 629) | type AppInfoResp struct

FILE: backend/domain/auth.go
  constant SessionCacheKey (line 17) | SessionCacheKey = "_session_store"
  constant SessionName (line 18) | SessionName     = "_pw_auth_session"
  type Auth (line 21) | type Auth struct
    method TableName (line 33) | func (Auth) TableName() string {
  type AuthGroup (line 37) | type AuthGroup struct
    method TableName (line 55) | func (AuthGroup) TableName() string {
  type AuthConfig (line 59) | type AuthConfig struct
    method TableName (line 80) | func (AuthConfig) TableName() string {
  type AuthSetting (line 84) | type AuthSetting struct
    method Scan (line 68) | func (s *AuthSetting) Scan(value any) error {
    method Value (line 76) | func (s AuthSetting) Value() (driver.Value, error) {
  type AuthInfo (line 90) | type AuthInfo struct
  type AuthUserInfo (line 95) | type AuthUserInfo struct
    method Scan (line 101) | func (s *AuthUserInfo) Scan(value any) error {
    method Value (line 109) | func (s *AuthUserInfo) Value() (driver.Value, error) {
  function GetAuthID (line 113) | func GetAuthID(c echo.Context) uint {

FILE: backend/domain/chat.go
  type ChatRequest (line 10) | type ChatRequest struct
  type ChatRagOnlyRequest (line 28) | type ChatRagOnlyRequest struct
  type ConversationInfo (line 37) | type ConversationInfo struct
    method Scan (line 51) | func (s *ConversationInfo) Scan(value any) error {
    method Value (line 59) | func (s ConversationInfo) Value() (driver.Value, error) {
  type UserInfo (line 41) | type UserInfo struct
  type MessageFrom (line 63) | type MessageFrom
    method String (line 70) | func (m MessageFrom) String() string {
  constant MessageFromGroup (line 66) | MessageFromGroup MessageFrom = iota + 1
  constant MessageFromPrivate (line 67) | MessageFromPrivate
  type ChatSearchReq (line 81) | type ChatSearchReq struct
  type ChatSearchResp (line 91) | type ChatSearchResp struct

FILE: backend/domain/comment.go
  type Comment (line 13) | type Comment struct
    method TableName (line 27) | func (Comment) TableName() string {
  type CommentInfo (line 31) | type CommentInfo struct
    method Value (line 47) | func (d *CommentInfo) Value() (driver.Value, error) {
    method Scan (line 51) | func (d *CommentInfo) Scan(value any) error {
  type CommentStatus (line 39) | type CommentStatus
  constant CommentStatusReject (line 42) | CommentStatusReject   CommentStatus = -1
  constant CommentStatusPending (line 43) | CommentStatusPending  CommentStatus = 0
  constant CommentStatusAccepted (line 44) | CommentStatusAccepted CommentStatus = 1
  type CommentReq (line 59) | type CommentReq struct
  type CommentListReq (line 69) | type CommentListReq struct
  type CommentListItem (line 75) | type CommentListItem struct
  type DeleteCommentListReq (line 88) | type DeleteCommentListReq struct
  type ShareCommentListItem (line 92) | type ShareCommentListItem struct

FILE: backend/domain/contribute.go
  type Contribute (line 9) | type Contribute struct
    method TableName (line 27) | func (Contribute) TableName() string {

FILE: backend/domain/conversation.go
  type Conversation (line 13) | type Conversation struct
  type ConversationMessage (line 27) | type ConversationMessage struct
  type FeedBackInfo (line 55) | type FeedBackInfo struct
    method Value (line 61) | func (f *FeedBackInfo) Value() (driver.Value, error) {
    method Scan (line 65) | func (f *FeedBackInfo) Scan(value any) error {
  type ConversationReference (line 73) | type ConversationReference struct
  type ConversationListReq (line 82) | type ConversationListReq struct
  type ConversationListItem (line 93) | type ConversationListItem struct
  type ConversationDetailResp (line 109) | type ConversationDetailResp struct
  type MessageListReq (line 123) | type MessageListReq struct
  type ConversationMessageListItem (line 128) | type ConversationMessageListItem struct
  type ShareConversationDetailResp (line 148) | type ShareConversationDetailResp struct
  type ShareConversationMessage (line 155) | type ShareConversationMessage struct

FILE: backend/domain/creation.go
  type TextReq (line 3) | type TextReq struct
  constant FIMPrefix (line 10) | FIMPrefix = "<fim_prefix>"
  constant FIMSuffix (line 11) | FIMSuffix = "<fim_suffix>"
  constant FIMMiddle (line 12) | FIMMiddle = "<fim_middle>"
  type CompleteReq (line 15) | type CompleteReq struct

FILE: backend/domain/epub.go
  type EpubReq (line 3) | type EpubReq struct
  type EpubResp (line 7) | type EpubResp struct

FILE: backend/domain/file.go
  constant Bucket (line 4) | Bucket = "static-file"
  type ObjectUploadResp (line 7) | type ObjectUploadResp struct
  type UploadByUrlReq (line 12) | type UploadByUrlReq struct
  type AnydocUploadResp (line 17) | type AnydocUploadResp struct

FILE: backend/domain/icon.go
  constant DefaultGitHubIconB64 (line 4) | DefaultGitHubIconB64    = `data:image/png;base64,iVBORw0KGgoAAAANSUhEUgA...
  constant DefaultPandaWikiIconB64 (line 5) | DefaultPandaWikiIconB64 = `data:image/png;base64,iVBORw0KGgoAAAANSUhEUgA...

FILE: backend/domain/ip.go
  type IPAddress (line 3) | type IPAddress struct

FILE: backend/domain/json.go
  type MapStrInt64 (line 9) | type MapStrInt64
    method Value (line 11) | func (m *MapStrInt64) Value() (driver.Value, error) {
    method Scan (line 18) | func (m *MapStrInt64) Scan(value interface{}) error {

FILE: backend/domain/knowledge_base.go
  type KnowledgeBase (line 15) | type KnowledgeBase struct
  type AccessSettings (line 28) | type AccessSettings struct
    method GetAuthType (line 51) | func (s *AccessSettings) GetAuthType() consts.AuthType {
    method Scan (line 61) | func (s *AccessSettings) Scan(value any) error {
    method Value (line 69) | func (s *AccessSettings) Value() (driver.Value, error) {
    method GetBaseUrl (line 73) | func (s *AccessSettings) GetBaseUrl() string {
  type SimpleAuth (line 42) | type SimpleAuth struct
  type EnterpriseAuth (line 47) | type EnterpriseAuth struct
  type CreateKnowledgeBaseReq (line 96) | type CreateKnowledgeBaseReq struct
  type UpdateKnowledgeBaseReq (line 107) | type UpdateKnowledgeBaseReq struct
  type KnowledgeBaseListItem (line 113) | type KnowledgeBaseListItem struct
  type KnowledgeBaseDetail (line 125) | type KnowledgeBaseDetail struct
  type KBRelease (line 138) | type KBRelease struct
  type KBReleaseNodeRelease (line 148) | type KBReleaseNodeRelease struct
    method TableName (line 158) | func (KBReleaseNodeRelease) TableName() string {
  type CreateKBReleaseReq (line 162) | type CreateKBReleaseReq struct
  type KBReleaseListItemResp (line 169) | type KBReleaseListItemResp struct
  type GetKBReleaseListReq (line 178) | type GetKBReleaseListReq struct

FILE: backend/domain/license.go
  constant ContextKeyEditionLimitation (line 8) | ContextKeyEditionLimitation contextKey = "edition_limitation"
  type BaseEditionLimitation (line 10) | type BaseEditionLimitation struct
  function GetBaseEditionLimitation (line 32) | func GetBaseEditionLimitation(c context.Context) BaseEditionLimitation {

FILE: backend/domain/llm.go
  constant PromptHeader (line 9) | PromptHeader = `你是一个专业的AI知识库问答助手,要按照以下步骤回答用户问题。
  function processContentWithBaseURL (line 86) | func processContentWithBaseURL(content, baseURL string) string {
  function FormatNodeChunks (line 131) | func FormatNodeChunks(nodeChunks []*RankedNodeChunks, baseURL string) st...

FILE: backend/domain/model.go
  type ModelProvider (line 13) | type ModelProvider
  constant ModelProviderBrandBaiZhiCloud (line 16) | ModelProviderBrandBaiZhiCloud ModelProvider = "BaiZhiCloud"
  type ModelType (line 19) | type ModelType
  constant ModelTypeChat (line 22) | ModelTypeChat       ModelType = "chat"
  constant ModelTypeEmbedding (line 23) | ModelTypeEmbedding  ModelType = "embedding"
  constant ModelTypeRerank (line 24) | ModelTypeRerank     ModelType = "rerank"
  constant ModelTypeAnalysis (line 25) | ModelTypeAnalysis   ModelType = "analysis"
  constant ModelTypeAnalysisVL (line 26) | ModelTypeAnalysisVL ModelType = "analysis-vl"
  type Model (line 29) | type Model struct
    method ToModelkitModel (line 52) | func (m *Model) ToModelkitModel() (*modelkitDomain.ModelMetadata, erro...
  type ModelListItem (line 68) | type ModelListItem struct
  type CreateModelReq (line 86) | type CreateModelReq struct
  type UpdateModelReq (line 91) | type UpdateModelReq struct
  type CheckModelReq (line 98) | type CheckModelReq struct
  type ModelParam (line 103) | type ModelParam struct
    method Map (line 113) | func (p ModelParam) Map() map[string]any {
    method Value (line 126) | func (p ModelParam) Value() (driver.Value, error) {
    method Scan (line 131) | func (p *ModelParam) Scan(value interface{}) error {
  type BaseModelInfo (line 146) | type BaseModelInfo struct
  type CheckModelResp (line 156) | type CheckModelResp struct
  type GetProviderModelListReq (line 161) | type GetProviderModelListReq struct
  type GetProviderModelListResp (line 169) | type GetProviderModelListResp struct
  type ProviderModelListItem (line 173) | type ProviderModelListItem struct
  type ActivateModelReq (line 177) | type ActivateModelReq struct
  type SwitchModeReq (line 181) | type SwitchModeReq struct
  type SwitchModeResp (line 187) | type SwitchModeResp struct

FILE: backend/domain/mq.go
  constant VectorTaskTopic (line 4) | VectorTaskTopic       = "apps.panda-wiki.vector.task"
  constant AnydocTaskExportTopic (line 5) | AnydocTaskExportTopic = "anydoc.persistence.doc.task.export"
  constant RagDocUpdateTopic (line 6) | RagDocUpdateTopic     = "raglite.events.doc.update"
  type NodeReleaseVectorRequest (line 15) | type NodeReleaseVectorRequest struct
  type AnydocTaskExportEvent (line 25) | type AnydocTaskExportEvent struct
  type RagDocInfoUpdateEvent (line 35) | type RagDocInfoUpdateEvent struct

FILE: backend/domain/nav.go
  type Nav (line 5) | type Nav struct
    method TableName (line 14) | func (Nav) TableName() string {
  type NavRelease (line 19) | type NavRelease struct
    method TableName (line 29) | func (NavRelease) TableName() string {

FILE: backend/domain/node.go
  constant MaxPosition (line 16) | MaxPosition    float64 = 1e38
  constant MinPositionGap (line 17) | MinPositionGap float64 = 1e-5
  type NodeType (line 20) | type NodeType
  constant NodeTypeFolder (line 23) | NodeTypeFolder   NodeType = 1
  constant NodeTypeDocument (line 24) | NodeTypeDocument NodeType = 2
  type NodeStatus (line 27) | type NodeStatus
  constant NodeStatusUnreleased (line 30) | NodeStatusUnreleased NodeStatus = 0
  constant NodeStatusDraft (line 31) | NodeStatusDraft      NodeStatus = 1
  constant NodeStatusReleased (line 32) | NodeStatusReleased   NodeStatus = 2
  constant ContentTypeMD (line 36) | ContentTypeMD   string = "md"
  constant ContentTypeHTML (line 37) | ContentTypeHTML string = "html"
  type Node (line 41) | type Node struct
    method TableName (line 62) | func (Node) TableName() string {
  type RagInfo (line 66) | type RagInfo struct
    method Value (line 72) | func (d *RagInfo) Value() (driver.Value, error) {
    method Scan (line 76) | func (d *RagInfo) Scan(value any) error {
  type NodePermissions (line 84) | type NodePermissions struct
    method Scan (line 90) | func (s *NodePermissions) Scan(value any) error {
    method Value (line 98) | func (s *NodePermissions) Value() (driver.Value, error) {
  type NodeAuthGroup (line 102) | type NodeAuthGroup struct
    method TableName (line 110) | func (NodeAuthGroup) TableName() string {
  type NodeGroupDetail (line 114) | type NodeGroupDetail struct
  type NodeMeta (line 123) | type NodeMeta struct
    method Value (line 129) | func (d *NodeMeta) Value() (driver.Value, error) {
    method Scan (line 133) | func (d *NodeMeta) Scan(value any) error {
  type CreateNodeReq (line 141) | type CreateNodeReq struct
  type GetNodeListReq (line 155) | type GetNodeListReq struct
  type NodeListItemResp (line 161) | type NodeListItemResp struct
  type NodeContentChunk (line 183) | type NodeContentChunk struct
  type RankedNodeChunks (line 193) | type RankedNodeChunks struct
    method GetURL (line 202) | func (n *RankedNodeChunks) GetURL(baseURL string) string {
  type ChunkListItemResp (line 206) | type ChunkListItemResp struct
  type NodeContentChunkSSE (line 213) | type NodeContentChunkSSE struct
  type RecommendNodeListResp (line 221) | type RecommendNodeListResp struct
  type NodeActionReq (line 233) | type NodeActionReq struct
  type UpdateNodeReq (line 239) | type UpdateNodeReq struct
  type ShareNodeListItemResp (line 251) | type ShareNodeListItemResp struct
    method GetURL (line 277) | func (n *ShareNodeListItemResp) GetURL(baseURL string) string {
  type ShareNodeDetailItem (line 264) | type ShareNodeDetailItem struct
  type MoveNodeReq (line 281) | type MoveNodeReq struct
  type NodeSummaryReq (line 289) | type NodeSummaryReq struct
  type GetRecommendNodeListReq (line 294) | type GetRecommendNodeListReq struct
  type NodeRelease (line 300) | type NodeRelease struct
    method TableName (line 321) | func (NodeRelease) TableName() string {
  type NodeReleaseBackup (line 326) | type NodeReleaseBackup struct
    method TableName (line 344) | func (NodeReleaseBackup) TableName() string {
  type NodeReleaseWithDirPath (line 349) | type NodeReleaseWithDirPath struct
  type BatchMoveReq (line 354) | type BatchMoveReq struct
  type NodeCreateInfo (line 360) | type NodeCreateInfo struct
  type NodeReleaseWithPublisher (line 366) | type NodeReleaseWithPublisher struct

FILE: backend/domain/notion.go
  type Page (line 3) | type Page struct
  type PageInfo (line 9) | type PageInfo struct

FILE: backend/domain/openai.go
  type OpenAICompletionsRequest (line 10) | type OpenAICompletionsRequest struct
  type OpenAIStreamOptions (line 27) | type OpenAIStreamOptions struct
  type MessageContent (line 32) | type MessageContent struct
    method UnmarshalJSON (line 51) | func (mc *MessageContent) UnmarshalJSON(data []byte) error {
    method MarshalJSON (line 72) | func (mc *MessageContent) MarshalJSON() ([]byte, error) {
    method String (line 96) | func (mc *MessageContent) String() string {
  type OpenAIContentPart (line 39) | type OpenAIContentPart struct
  type OpenAIContentPartURL (line 46) | type OpenAIContentPartURL struct
  function NewStringContent (line 80) | func NewStringContent(s string) *MessageContent {
  function NewArrayContent (line 88) | func NewArrayContent(parts []OpenAIContentPart) *MessageContent {
  type OpenAIMessage (line 113) | type OpenAIMessage struct
  type OpenAITool (line 121) | type OpenAITool struct
  type OpenAIFunction (line 126) | type OpenAIFunction struct
  type OpenAIToolCall (line 132) | type OpenAIToolCall struct
  type OpenAIFunctionCall (line 138) | type OpenAIFunctionCall struct
  type OpenAIToolChoice (line 143) | type OpenAIToolChoice struct
  type OpenAIFunctionChoice (line 148) | type OpenAIFunctionChoice struct
  type OpenAIResponseFormat (line 152) | type OpenAIResponseFormat struct
  type OpenAICompletionsResponse (line 157) | type OpenAICompletionsResponse struct
  type OpenAIChoice (line 166) | type OpenAIChoice struct
  type OpenAIUsage (line 173) | type OpenAIUsage struct
  type OpenAIStreamResponse (line 180) | type OpenAIStreamResponse struct
  type OpenAIStreamChoice (line 189) | type OpenAIStreamChoice struct
  type OpenAIErrorResponse (line 196) | type OpenAIErrorResponse struct
  type OpenAIError (line 200) | type OpenAIError struct

FILE: backend/domain/openai_test.go
  function TestMessageContent_UnmarshalJSON_String (line 11) | func TestMessageContent_UnmarshalJSON_String(t *testing.T) {
  function TestMessageContent_UnmarshalJSON_Array (line 36) | func TestMessageContent_UnmarshalJSON_Array(t *testing.T) {
  function TestMessageContent_UnmarshalJSON_Invalid (line 75) | func TestMessageContent_UnmarshalJSON_Invalid(t *testing.T) {
  function TestMessageContent_UnmarshalJSON_Null (line 95) | func TestMessageContent_UnmarshalJSON_Null(t *testing.T) {
  function TestMessageContent_MarshalJSON_String (line 102) | func TestMessageContent_MarshalJSON_String(t *testing.T) {
  function TestMessageContent_MarshalJSON_Array (line 109) | func TestMessageContent_MarshalJSON_Array(t *testing.T) {
  function TestMessageContent_Roundtrip_String (line 119) | func TestMessageContent_Roundtrip_String(t *testing.T) {
  function TestMessageContent_Roundtrip_Array (line 136) | func TestMessageContent_Roundtrip_Array(t *testing.T) {
  function TestNewStringContent (line 157) | func TestNewStringContent(t *testing.T) {
  function TestNewArrayContent (line 165) | func TestNewArrayContent(t *testing.T) {
  function TestMessageContent_String_EmptyArray (line 176) | func TestMessageContent_String_EmptyArray(t *testing.T) {
  function TestMessageContent_String_NoTextParts (line 181) | func TestMessageContent_String_NoTextParts(t *testing.T) {

FILE: backend/domain/pager.go
  type Pager (line 3) | type Pager struct
    method Offset (line 12) | func (p *Pager) Offset() int {
    method Limit (line 20) | func (p *Pager) Limit() int {
  type PagerInfo (line 8) | type PagerInfo struct
  type PaginatedResult (line 31) | type PaginatedResult struct
  function NewPaginatedResult (line 36) | func NewPaginatedResult[T any](data T, total uint64) *PaginatedResult[T] {

FILE: backend/domain/prompt.go
  type Prompt (line 3) | type Prompt struct

FILE: backend/domain/response.go
  type PWResponse (line 3) | type PWResponse struct
  type PWResponseErrCode (line 10) | type PWResponseErrCode

FILE: backend/domain/setting.go
  constant SettingKeySystemPrompt (line 9) | SettingKeySystemPrompt = "system_prompt"
  constant SettingBlockWords (line 10) | SettingBlockWords      = "block_words"
  constant SettingCopyrightInfo (line 11) | SettingCopyrightInfo   = "本网站由 PandaWiki 提供技术支持"
  type Setting (line 15) | type Setting struct
  type SettingRepo (line 25) | type SettingRepo interface

FILE: backend/domain/siyuan.go
  type SiYuanReq (line 3) | type SiYuanReq struct
  type SiYuanResp (line 6) | type SiYuanResp struct

FILE: backend/domain/sse_event.go
  type SSEEvent (line 3) | type SSEEvent struct

FILE: backend/domain/stat.go
  type StatPageScene (line 7) | type StatPageScene
  constant StatPageSceneWelcome (line 10) | StatPageSceneWelcome StatPageScene = iota + 1
  constant StatPageSceneNodeDetail (line 11) | StatPageSceneNodeDetail
  constant StatPageSceneChat (line 12) | StatPageSceneChat
  constant StatPageSceneLogin (line 13) | StatPageSceneLogin
  type StatPage (line 20) | type StatPage struct
  type StatPageReq (line 36) | type StatPageReq struct
  type HotPage (line 41) | type HotPage struct
  type HotRefererHost (line 48) | type HotRefererHost struct
  type HotBrowser (line 53) | type HotBrowser struct
  type BrowserCount (line 58) | type BrowserCount struct
  type InstantCountResp (line 63) | type InstantCountResp struct
  type InstantPageResp (line 68) | type InstantPageResp struct
  type ConversationDistribution (line 80) | type ConversationDistribution struct
  type StatPageHour (line 87) | type StatPageHour struct
    method TableName (line 105) | func (StatPageHour) TableName() string {
  type NodeStats (line 110) | type NodeStats struct
    method TableName (line 116) | func (NodeStats) TableName() string {

FILE: backend/domain/system_setting.go
  type SystemSetting (line 10) | type SystemSetting struct
    method TableName (line 19) | func (SystemSetting) TableName() string {
  type ModelModeSetting (line 24) | type ModelModeSetting struct
  type UploadDeniedExtensionsSetting (line 33) | type UploadDeniedExtensionsSetting struct

FILE: backend/domain/user.go
  type User (line 9) | type User struct
  type KBUsers (line 19) | type KBUsers struct
    method TableName (line 27) | func (KBUsers) TableName() string {
  type UserAccessTime (line 31) | type UserAccessTime struct

FILE: backend/domain/userfeedback.go
  type FeedbackRequest (line 4) | type FeedbackRequest struct
  type FeedbackType (line 12) | type FeedbackType
  type ScoreType (line 14) | type ScoreType
  constant Like (line 18) | Like    ScoreType = 1
  constant DisLike (line 19) | DisLike ScoreType = -1

FILE: backend/domain/wechat.go
  type ConversationState (line 9) | type ConversationState struct
  type WechatStatic (line 21) | type WechatStatic struct

FILE: backend/handler/base.go
  type BaseHandler (line 20) | type BaseHandler struct
    method NewResponseWithData (line 40) | func (h *BaseHandler) NewResponseWithData(c echo.Context, data any) er...
    method NewResponseWithErrCode (line 47) | func (h *BaseHandler) NewResponseWithErrCode(c echo.Context, resp doma...
    method NewResponseWithError (line 51) | func (h *BaseHandler) NewResponseWithError(c echo.Context, msg string,...
  function NewBaseHandler (line 29) | func NewBaseHandler(echo *echo.Echo, logger *log.Logger, config *config....

FILE: backend/handler/mq/cron.go
  type CronHandler (line 14) | type CronHandler struct
    method RemoveOldStatData (line 77) | func (h *CronHandler) RemoveOldStatData() {
    method AggregateHourlyStats (line 96) | func (h *CronHandler) AggregateHourlyStats() {
    method CleanupOldHourlyStats (line 106) | func (h *CronHandler) CleanupOldHourlyStats() {
    method SyncRagNodeStatus (line 116) | func (h *CronHandler) SyncRagNodeStatus() {
    method CleanupOldNodeReleaseBackups (line 126) | func (h *CronHandler) CleanupOldNodeReleaseBackups() {
  function NewCronHandler (line 22) | func NewCronHandler(logger *log.Logger, statRepo *pg.StatRepository, nod...

FILE: backend/handler/mq/provider.go
  type MQHandlers (line 14) | type MQHandlers struct

FILE: backend/handler/mq/rag.go
  type RAGMQHandler (line 17) | type RAGMQHandler struct
    method HandleNodeContentVectorRequest (line 43) | func (h *RAGMQHandler) HandleNodeContentVectorRequest(ctx context.Cont...
  function NewRAGMQHandler (line 27) | func NewRAGMQHandler(consumer mq.MQConsumer, logger *log.Logger, rag rag...

FILE: backend/handler/mq/rag_doc_update.go
  type RagDocUpdateHandler (line 16) | type RagDocUpdateHandler struct
    method HandleRagDocUpdate (line 34) | func (h *RagDocUpdateHandler) HandleRagDocUpdate(ctx context.Context, ...
  function NewRagDocUpdateHandler (line 22) | func NewRagDocUpdateHandler(consumer mq.MQConsumer, logger *log.Logger, ...

FILE: backend/handler/share/app.go
  type ShareAppHandler (line 20) | type ShareAppHandler struct
    method GetWebAppInfo (line 70) | func (h *ShareAppHandler) GetWebAppInfo(c echo.Context) error {
    method GetWidgetAppInfo (line 93) | func (h *ShareAppHandler) GetWidgetAppInfo(c echo.Context) error {
    method WechatAppInfo (line 115) | func (h *ShareAppHandler) WechatAppInfo(c echo.Context) error {
    method VerifyUrlWechatOfficialAccount (line 127) | func (h *ShareAppHandler) VerifyUrlWechatOfficialAccount(c echo.Contex...
    method WechatHandlerOfficialAccount (line 165) | func (h *ShareAppHandler) WechatHandlerOfficialAccount(c echo.Context)...
  function NewShareAppHandler (line 26) | func NewShareAppHandler(

FILE: backend/handler/share/auth.go
  type ShareAuthHandler (line 18) | type ShareAuthHandler struct
    method AuthGet (line 60) | func (h *ShareAuthHandler) AuthGet(c echo.Context) error {
    method AuthLoginSimple (line 93) | func (h *ShareAuthHandler) AuthLoginSimple(c echo.Context) error {
    method AuthGitHub (line 156) | func (h *ShareAuthHandler) AuthGitHub(c echo.Context) error {
  function NewShareAuthHandler (line 25) | func NewShareAuthHandler(

FILE: backend/handler/share/captcha.go
  type ShareCaptchaHandler (line 15) | type ShareCaptchaHandler struct
    method CreateCaptcha (line 47) | func (h *ShareCaptchaHandler) CreateCaptcha(c echo.Context) error {
    method RedeemCaptcha (line 70) | func (h *ShareCaptchaHandler) RedeemCaptcha(c echo.Context) error {
  function NewShareCaptchaHandler (line 20) | func NewShareCaptchaHandler(

FILE: backend/handler/share/chat.go
  type ShareChatHandler (line 18) | type ShareChatHandler struct
    method ChatMessage (line 80) | func (h *ShareChatHandler) ChatMessage(c echo.Context) error {
    method ChatWidget (line 153) | func (h *ShareChatHandler) ChatWidget(c echo.Context) error {
    method sendErrMsg (line 209) | func (h *ShareChatHandler) sendErrMsg(c echo.Context, errMsg string) e...
    method writeSSEEvent (line 213) | func (h *ShareChatHandler) writeSSEEvent(c echo.Context, data any) err...
    method FeedBack (line 237) | func (h *ShareChatHandler) FeedBack(c echo.Context) error {
    method ChatCompletions (line 265) | func (h *ShareChatHandler) ChatCompletions(c echo.Context) error {
    method handleOpenAIStreamResponse (line 351) | func (h *ShareChatHandler) handleOpenAIStreamResponse(c echo.Context, ...
    method handleOpenAINonStreamResponse (line 401) | func (h *ShareChatHandler) handleOpenAINonStreamResponse(c echo.Contex...
    method sendOpenAIError (line 436) | func (h *ShareChatHandler) sendOpenAIError(c echo.Context, message, er...
    method writeOpenAIStreamEvent (line 446) | func (h *ShareChatHandler) writeOpenAIStreamEvent(c echo.Context, data...
    method ChatSearch (line 478) | func (h *ShareChatHandler) ChatSearch(c echo.Context) error {
    method WidgetSearch (line 522) | func (h *ShareChatHandler) WidgetSearch(c echo.Context) error {
  function NewShareChatHandler (line 28) | func NewShareChatHandler(
  function generateID (line 460) | func generateID() string {
  function stringPtr (line 464) | func stringPtr(s string) *string {

FILE: backend/handler/share/comment.go
  type ShareCommentHandler (line 15) | type ShareCommentHandler struct
    method CreateComment (line 64) | func (h *ShareCommentHandler) CreateComment(c echo.Context) error {
    method GetCommentList (line 135) | func (h *ShareCommentHandler) GetCommentList(c echo.Context) error {
  function NewShareCommentHandler (line 22) | func NewShareCommentHandler(

FILE: backend/handler/share/common.go
  type ShareCommonHandler (line 17) | type ShareCommonHandler struct
    method FileUpload (line 65) | func (h *ShareCommonHandler) FileUpload(c echo.Context) error {
    method FileUploadByUrl (line 118) | func (h *ShareCommonHandler) FileUploadByUrl(c echo.Context) error {
  function NewShareCommonHandler (line 23) | func NewShareCommonHandler(

FILE: backend/handler/share/coversation.go
  type ShareConversationHandler (line 11) | type ShareConversationHandler struct
    method GetConversationDetail (line 48) | func (h *ShareConversationHandler) GetConversationDetail(c echo.Contex...
  function NewShareConversationHandler (line 17) | func NewShareConversationHandler(

FILE: backend/handler/share/nav.go
  type ShareNavHandler (line 12) | type ShareNavHandler struct
    method ShareNavList (line 48) | func (h *ShareNavHandler) ShareNavList(c echo.Context) error {
  function NewShareNavHandler (line 18) | func NewShareNavHandler(

FILE: backend/handler/share/node.go
  type ShareNodeHandler (line 12) | type ShareNodeHandler struct
    method ShareNodeList (line 49) | func (h *ShareNodeHandler) ShareNodeList(c echo.Context) error {
    method GetNodeDetail (line 76) | func (h *ShareNodeHandler) GetNodeDetail(c echo.Context) error {
  function NewShareNodeHandler (line 18) | func NewShareNodeHandler(

FILE: backend/handler/share/openapi.go
  type OpenapiV1Handler (line 21) | type OpenapiV1Handler struct
    method GitHubCallback (line 63) | func (h *OpenapiV1Handler) GitHubCallback(c echo.Context) error {
    method LarkBot (line 97) | func (h *OpenapiV1Handler) LarkBot(c echo.Context) error {
  function NewOpenapiV1Handler (line 28) | func NewOpenapiV1Handler(

FILE: backend/handler/share/provider.go
  type ShareHandler (line 9) | type ShareHandler struct

FILE: backend/handler/share/sitemap.go
  type ShareSitemapHandler (line 13) | type ShareSitemapHandler struct
    method GetSitemap (line 34) | func (h *ShareSitemapHandler) GetSitemap(c echo.Context) error {
  function NewShareSitemapHandler (line 20) | func NewShareSitemapHandler(echo *echo.Echo, baseHandler *handler.BaseHa...

FILE: backend/handler/share/stat.go
  type ShareStatHandler (line 16) | type ShareStatHandler struct
    method RecordPage (line 44) | func (h *ShareStatHandler) RecordPage(c echo.Context) error {
  function NewShareStatHandler (line 22) | func NewShareStatHandler(baseHandler *handler.BaseHandler, echo *echo.Ec...

FILE: backend/handler/share/wechat.go
  type ShareWechatHandler (line 23) | type ShareWechatHandler struct
    method GetWechatAnswer (line 92) | func (h *ShareWechatHandler) GetWechatAnswer(c echo.Context) error {
    method sendErrMsg (line 160) | func (h *ShareWechatHandler) sendErrMsg(c echo.Context, errMsg string)...
    method writeSSEEvent (line 164) | func (h *ShareWechatHandler) writeSSEEvent(c echo.Context, data any) e...
    method VerifyUrlWechatService (line 179) | func (h *ShareWechatHandler) VerifyUrlWechatService(c echo.Context) er...
    method WechatHandlerService (line 227) | func (h *ShareWechatHandler) WechatHandlerService(c echo.Context) error {
    method VerifyUrlWechatApp (line 293) | func (h *ShareWechatHandler) VerifyUrlWechatApp(c echo.Context) error {
    method WechatHandlerApp (line 342) | func (h *ShareWechatHandler) WechatHandlerApp(c echo.Context) error {
    method WecomAIBotVerify (line 412) | func (h *ShareWechatHandler) WecomAIBotVerify(c echo.Context) error {
    method WecomAIBotHandle (line 452) | func (h *ShareWechatHandler) WecomAIBotHandle(c echo.Context) error {
  function NewShareWechatHandler (line 33) | func NewShareWechatHandler(

FILE: backend/handler/v1/app.go
  type AppHandler (line 17) | type AppHandler struct
    method GetAppDetail (line 58) | func (h *AppHandler) GetAppDetail(c echo.Context) error {
    method UpdateApp (line 91) | func (h *AppHandler) UpdateApp(c echo.Context) error {
    method DeleteApp (line 126) | func (h *AppHandler) DeleteApp(c echo.Context) error {
  function NewAppHandler (line 27) | func NewAppHandler(e *echo.Echo, baseHandler *handler.BaseHandler, logge...

FILE: backend/handler/v1/auth.go
  type AuthV1Handler (line 13) | type AuthV1Handler struct
    method OpenAuthGet (line 55) | func (h *AuthV1Handler) OpenAuthGet(c echo.Context) error {
    method OpenAuthSet (line 86) | func (h *AuthV1Handler) OpenAuthSet(c echo.Context) error {
    method OpenAuthDelete (line 116) | func (h *AuthV1Handler) OpenAuthDelete(c echo.Context) error {
  function NewAuthV1Handler (line 19) | func NewAuthV1Handler(

FILE: backend/handler/v1/comment.go
  type CommentHandler (line 14) | type CommentHandler struct
    method GetCommentModeratedList (line 49) | func (h *CommentHandler) GetCommentModeratedList(c echo.Context) error {
    method DeleteCommentList (line 77) | func (h *CommentHandler) DeleteCommentList(c echo.Context) error {
  function NewCommentHandler (line 21) | func NewCommentHandler(e *echo.Echo, baseHandler *handler.BaseHandler, l...

FILE: backend/handler/v1/conversation.go
  type ConversationHandler (line 15) | type ConversationHandler struct
    method GetConversationList (line 50) | func (h *ConversationHandler) GetConversationList(c echo.Context) error {
    method GetConversationDetail (line 76) | func (h *ConversationHandler) GetConversationDetail(c echo.Context) er...
    method GetMessageFeedBackList (line 105) | func (h *ConversationHandler) GetMessageFeedBackList(c echo.Context) e...
    method GetMessageDetail (line 129) | func (h *ConversationHandler) GetMessageDetail(c echo.Context) error {
  function NewConversationHandler (line 22) | func NewConversationHandler(echo *echo.Echo, baseHandler *handler.BaseHa...

FILE: backend/handler/v1/crawler.go
  type CrawlerHandler (line 15) | type CrawlerHandler struct
    method CrawlerParse (line 57) | func (h *CrawlerHandler) CrawlerParse(c echo.Context) error {
    method CrawlerExport (line 99) | func (h *CrawlerHandler) CrawlerExport(c echo.Context) error {
    method CrawlerResult (line 124) | func (h *CrawlerHandler) CrawlerResult(c echo.Context) error {
    method CrawlerResults (line 150) | func (h *CrawlerHandler) CrawlerResults(c echo.Context) error {
  function NewCrawlerHandler (line 23) | func NewCrawlerHandler(echo *echo.Echo,

FILE: backend/handler/v1/creation.go
  type CreationHandler (line 14) | type CreationHandler struct
    method Text (line 44) | func (h *CreationHandler) Text(c echo.Context) error {
    method TabComplete (line 83) | func (h *CreationHandler) TabComplete(c echo.Context) error {
  function NewCreationHandler (line 20) | func NewCreationHandler(echo *echo.Echo, baseHandler *handler.BaseHandle...

FILE: backend/handler/v1/file.go
  type FileHandler (line 21) | type FileHandler struct
    method Upload (line 54) | func (h *FileHandler) Upload(c echo.Context) error {
    method UploadByUrl (line 85) | func (h *FileHandler) UploadByUrl(c echo.Context) error {
    method UploadAnydoc (line 122) | func (h *FileHandler) UploadAnydoc(c echo.Context) error {
  function NewFileHandler (line 29) | func NewFileHandler(echo *echo.Echo, baseHandler *handler.BaseHandler, l...

FILE: backend/handler/v1/kb_user.go
  method KBUserList (line 22) | func (h *KnowledgeBaseHandler) KBUserList(c echo.Context) error {
  method KBUserInvite (line 50) | func (h *KnowledgeBaseHandler) KBUserInvite(c echo.Context) error {
  method KBUserUpdate (line 82) | func (h *KnowledgeBaseHandler) KBUserUpdate(c echo.Context) error {
  method KBUserDelete (line 114) | func (h *KnowledgeBaseHandler) KBUserDelete(c echo.Context) error {

FILE: backend/handler/v1/knowledge_base.go
  type KnowledgeBaseHandler (line 17) | type KnowledgeBaseHandler struct
    method CreateKnowledgeBase (line 73) | func (h *KnowledgeBaseHandler) CreateKnowledgeBase(c echo.Context) err...
    method GetKnowledgeBaseList (line 121) | func (h *KnowledgeBaseHandler) GetKnowledgeBaseList(c echo.Context) er...
    method UpdateKnowledgeBase (line 141) | func (h *KnowledgeBaseHandler) UpdateKnowledgeBase(c echo.Context) err...
    method GetKnowledgeBaseDetail (line 176) | func (h *KnowledgeBaseHandler) GetKnowledgeBaseDetail(c echo.Context) ...
    method DeleteKnowledgeBase (line 218) | func (h *KnowledgeBaseHandler) DeleteKnowledgeBase(c echo.Context) err...
    method CreateKBRelease (line 242) | func (h *KnowledgeBaseHandler) CreateKBRelease(c echo.Context) error {
    method GetKBReleaseList (line 277) | func (h *KnowledgeBaseHandler) GetKBReleaseList(c echo.Context) error {
  function NewKnowledgeBaseHandler (line 25) | func NewKnowledgeBaseHandler(

FILE: backend/handler/v1/model.go
  type ModelHandler (line 18) | type ModelHandler struct
    method GetModelList (line 58) | func (h *ModelHandler) GetModelList(c echo.Context) error {
    method CreateModel (line 79) | func (h *ModelHandler) CreateModel(c echo.Context) error {
    method UpdateModel (line 121) | func (h *ModelHandler) UpdateModel(c echo.Context) error {
    method CheckModel (line 152) | func (h *ModelHandler) CheckModel(c echo.Context) error {
    method GetProviderSupportedModelList (line 193) | func (h *ModelHandler) GetProviderSupportedModelList(c echo.Context) e...
    method SwitchMode (line 226) | func (h *ModelHandler) SwitchMode(c echo.Context) error {
    method GetModelModeSetting (line 255) | func (h *ModelHandler) GetModelModeSetting(c echo.Context) error {
  function NewModelHandler (line 27) | func NewModelHandler(echo *echo.Echo, baseHandler *handler.BaseHandler, ...

FILE: backend/handler/v1/nav.go
  type NavHandler (line 14) | type NavHandler struct
    method NavList (line 56) | func (h *NavHandler) NavList(c echo.Context) error {
    method NavAdd (line 84) | func (h *NavHandler) NavAdd(c echo.Context) error {
    method NavDelete (line 113) | func (h *NavHandler) NavDelete(c echo.Context) error {
    method NavMove (line 141) | func (h *NavHandler) NavMove(c echo.Context) error {
    method NavUpdate (line 167) | func (h *NavHandler) NavUpdate(c echo.Context) error {
  function NewNavHandler (line 21) | func NewNavHandler(

FILE: backend/handler/v1/node.go
  type NodeHandler (line 17) | type NodeHandler struct
    method CreateNode (line 74) | func (h *NodeHandler) CreateNode(c echo.Context) error {
    method NodeStats (line 114) | func (h *NodeHandler) NodeStats(c echo.Context) error {
    method GetNodeList (line 143) | func (h *NodeHandler) GetNodeList(c echo.Context) error {
    method NodeListGroupNav (line 170) | func (h *NodeHandler) NodeListGroupNav(c echo.Context) error {
    method GetNodeDetail (line 197) | func (h *NodeHandler) GetNodeDetail(c echo.Context) error {
    method NodeAction (line 226) | func (h *NodeHandler) NodeAction(c echo.Context) error {
    method UpdateNodeDetail (line 252) | func (h *NodeHandler) UpdateNodeDetail(c echo.Context) error {
    method MoveNode (line 284) | func (h *NodeHandler) MoveNode(c echo.Context) error {
    method NodeMoveNav (line 310) | func (h *NodeHandler) NodeMoveNav(c echo.Context) error {
    method SummaryNode (line 336) | func (h *NodeHandler) SummaryNode(c echo.Context) error {
    method RecommendNodes (line 368) | func (h *NodeHandler) RecommendNodes(c echo.Context) error {
    method BatchMoveNode (line 395) | func (h *NodeHandler) BatchMoveNode(c echo.Context) error {
    method NodePermission (line 422) | func (h *NodeHandler) NodePermission(c echo.Context) error {
    method NodePermissionEdit (line 452) | func (h *NodeHandler) NodePermissionEdit(c echo.Context) error {
    method NodeRestudy (line 486) | func (h *NodeHandler) NodeRestudy(c echo.Context) error {
  function NewNodeHandler (line 24) | func NewNodeHandler(

FILE: backend/handler/v1/provider.go
  type APIHandlers (line 11) | type APIHandlers struct

FILE: backend/handler/v1/stat.go
  type StatHandler (line 15) | type StatHandler struct
    method StatCount (line 57) | func (h *StatHandler) StatCount(c echo.Context) error {
    method StatGeoCountReq (line 90) | func (h *StatHandler) StatGeoCountReq(c echo.Context) error {
    method StatConversationDistribution (line 123) | func (h *StatHandler) StatConversationDistribution(c echo.Context) err...
    method StatHotPages (line 156) | func (h *StatHandler) StatHotPages(c echo.Context) error {
    method StatRefererHosts (line 188) | func (h *StatHandler) StatRefererHosts(c echo.Context) error {
    method StatBrowsers (line 220) | func (h *StatHandler) StatBrowsers(c echo.Context) error {
    method GetInstantCount (line 252) | func (h *StatHandler) GetInstantCount(c echo.Context) error {
    method GetInstantPages (line 280) | func (h *StatHandler) GetInstantPages(c echo.Context) error {
  function NewStatHandler (line 22) | func NewStatHandler(baseHandler *handler.BaseHandler, echo *echo.Echo, u...

FILE: backend/handler/v1/user.go
  type UserHandler (line 22) | type UserHandler struct
    method CreateUser (line 63) | func (h *UserHandler) CreateUser(c echo.Context) error {
    method Login (line 97) | func (h *UserHandler) Login(c echo.Context) error {
    method GetUserInfo (line 138) | func (h *UserHandler) GetUserInfo(c echo.Context) error {
    method ListUsers (line 171) | func (h *UserHandler) ListUsers(c echo.Context) error {
    method ResetPassword (line 194) | func (h *UserHandler) ResetPassword(c echo.Context) error {
    method DeleteUser (line 254) | func (h *UserHandler) DeleteUser(c echo.Context) error {
  function NewUserHandler (line 31) | func NewUserHandler(e *echo.Echo, baseHandler *handler.BaseHandler, logg...

FILE: backend/log/log.go
  type Logger (line 10) | type Logger struct
    method WithModule (line 19) | func (l *Logger) WithModule(module string) *Logger {
  function NewLogger (line 14) | func NewLogger(config *config.Config) *Logger {
  function Any (line 23) | func Any(key string, value any) slog.Attr {
  function String (line 27) | func String(key string, value string) slog.Attr {
  function Int (line 31) | func Int(key string, value int) slog.Attr {
  function Int64 (line 35) | func Int64(key string, value int64) slog.Attr {
  function Error (line 39) | func Error(err error) slog.Attr {

FILE: backend/middleware/api_token.go
  type APITokenRepository (line 9) | type APITokenRepository interface

FILE: backend/middleware/auth.go
  type AuthMiddleware (line 14) | type AuthMiddleware interface
  function NewAuthMiddleware (line 22) | func NewAuthMiddleware(config *config.Config, logger *log.Logger, userAc...

FILE: backend/middleware/jwt.go
  type JWTMiddleware (line 23) | type JWTMiddleware struct
    method Authorize (line 51) | func (m *JWTMiddleware) Authorize(next echo.HandlerFunc) echo.HandlerF...
    method validateAPIToken (line 81) | func (m *JWTMiddleware) validateAPIToken(c echo.Context, token string,...
    method ValidateUserRole (line 112) | func (m *JWTMiddleware) ValidateUserRole(role consts.UserRole) echo.Mi...
    method ValidateKBUserPerm (line 148) | func (m *JWTMiddleware) ValidateKBUserPerm(perm consts.UserKBPermissio...
    method ValidateLicenseEdition (line 205) | func (m *JWTMiddleware) ValidateLicenseEdition(needEditions ...consts....
    method MustGetUserID (line 229) | func (m *JWTMiddleware) MustGetUserID(c echo.Context) (string, bool) {
  function NewJWTMiddleware (line 31) | func NewJWTMiddleware(config *config.Config, logger *log.Logger, userAcc...
  function GetKbID (line 242) | func GetKbID(c echo.Context) (string, error) {

FILE: backend/middleware/readonly.go
  type ReadOnlyMiddleware (line 13) | type ReadOnlyMiddleware struct
    method ReadOnly (line 24) | func (readonly *ReadOnlyMiddleware) ReadOnly(next echo.HandlerFunc) ec...
  function NewReadonlyMiddleware (line 17) | func NewReadonlyMiddleware(logger *log.Logger) *ReadOnlyMiddleware {
  function isReadOnlyMethod (line 50) | func isReadOnlyMethod(method string) bool {

FILE: backend/middleware/session.go
  constant SessionKey (line 20) | SessionKey = "SessionKey"
  type SessionMiddleware (line 23) | type SessionMiddleware struct
    method Session (line 63) | func (s *SessionMiddleware) Session() echo.MiddlewareFunc {
  function NewSessionMiddleware (line 28) | func NewSessionMiddleware(logger *log.Logger, config *config.Config, cac...

FILE: backend/middleware/share_auth.go
  type ShareAuthMiddleware (line 15) | type ShareAuthMiddleware struct
    method CheckForbidden (line 27) | func (h *ShareAuthMiddleware) CheckForbidden(next echo.HandlerFunc) ec...
    method Authorize (line 60) | func (h *ShareAuthMiddleware) Authorize(next echo.HandlerFunc) echo.Ha...
  function NewShareAuthMiddleware (line 20) | func NewShareAuthMiddleware(logger *log.Logger, kbUsecase *usecase.Knowl...

FILE: backend/migration/fns/0001_migrate_node_version.go
  type MigrationNodeVersion (line 16) | type MigrationNodeVersion struct
    method Execute (line 34) | func (m *MigrationNodeVersion) Execute(tx *gorm.DB) error {
  function NewMigrationNodeVersion (line 24) | func NewMigrationNodeVersion(logger *log.Logger, nodeUsecase *usecase.No...

FILE: backend/migration/fns/0002_create_bot_auth.go
  type MigrationCreateBotAuth (line 14) | type MigrationCreateBotAuth struct
    method Execute (line 26) | func (m *MigrationCreateBotAuth) Execute(tx *gorm.DB) error {
  function NewMigrationCreateBotAuth (line 19) | func NewMigrationCreateBotAuth(logger *log.Logger) *MigrationCreateBotAu...

FILE: backend/migration/fns/0003_fix_group_ids.go
  type MigrationFixGroupIds (line 14) | type MigrationFixGroupIds struct
    method Execute (line 28) | func (m *MigrationFixGroupIds) Execute(tx *gorm.DB) error {
  function NewMigrationFixGroupIds (line 20) | func NewMigrationFixGroupIds(logger *log.Logger, ragRepo *mq.RAGReposito...

FILE: backend/migration/fns/0004_update_node_status_unreleased.go
  type MigrationUpdateNodeStatusUnreleased (line 10) | type MigrationUpdateNodeStatusUnreleased struct
    method Execute (line 22) | func (m *MigrationUpdateNodeStatusUnreleased) Execute(tx *gorm.DB) err...
  function NewMigrationUpdateNodeStatusUnreleased (line 15) | func NewMigrationUpdateNodeStatusUnreleased(logger *log.Logger) *Migrati...

FILE: backend/migration/fns/0005_create_first_nav_tabs.go
  type MigrationCreateFirstNavs (line 14) | type MigrationCreateFirstNavs struct
    method Execute (line 26) | func (m *MigrationCreateFirstNavs) Execute(tx *gorm.DB) error {
  function NewMigrationCreateFirstNavs (line 19) | func NewMigrationCreateFirstNavs(logger *log.Logger) *MigrationCreateFir...

FILE: backend/migration/func.go
  type MigrationFuncs (line 7) | type MigrationFuncs struct
    method GetMigrationFuncs (line 15) | func (mf *MigrationFuncs) GetMigrationFuncs() []MigrationFunc {

FILE: backend/migration/manager.go
  type GoMigrationFunc (line 13) | type GoMigrationFunc interface
  type MigrationFunc (line 18) | type MigrationFunc struct
  type Migration (line 24) | type Migration struct
  type Manager (line 31) | type Manager struct
    method Execute (line 47) | func (m *Manager) Execute() error {
  function NewManager (line 38) | func NewManager(db *pg.DB, logger *log.Logger, migrationFuncs *Migration...

FILE: backend/mq/mq.go
  type Message (line 16) | type Message interface
  type MQConsumer (line 21) | type MQConsumer interface
  type MQProducer (line 27) | type MQProducer interface
  function NewMQConsumer (line 31) | func NewMQConsumer(config *config.Config, logger *log.Logger) (MQConsume...
  function NewMQProducer (line 38) | func NewMQProducer(config *config.Config, logger *log.Logger) (MQProduce...

FILE: backend/mq/nats/consumer.go
  type MQConsumer (line 15) | type MQConsumer struct
    method RegisterHandler (line 54) | func (c *MQConsumer) RegisterHandler(topic string, handler func(ctx co...
    method registerCoreNATSHandler (line 69) | func (c *MQConsumer) registerCoreNATSHandler(topic string, handler fun...
    method registerJetStreamHandler (line 96) | func (c *MQConsumer) registerJetStreamHandler(topic string, handler fu...
    method StartConsumerHandlers (line 137) | func (c *MQConsumer) StartConsumerHandlers(ctx context.Context) error {
    method Close (line 142) | func (c *MQConsumer) Close() error {
  function NewMQConsumer (line 23) | func NewMQConsumer(logger *log.Logger, config *config.Config) (*MQConsum...

FILE: backend/mq/nats/message.go
  type Message (line 9) | type Message struct
    method GetData (line 13) | func (m *Message) GetData() []byte {
    method GetTopic (line 17) | func (m *Message) GetTopic() string {

FILE: backend/mq/nats/producer.go
  type MQProducer (line 14) | type MQProducer struct
    method EnsureStreams (line 20) | func (p *MQProducer) EnsureStreams() error {
    method Produce (line 106) | func (p *MQProducer) Produce(ctx context.Context, topic string, key st...
    method Close (line 125) | func (p *MQProducer) Close() error {
  function NewMQProducer (line 69) | func NewMQProducer(config *config.Config, logger *log.Logger) (*MQProduc...

FILE: backend/mq/types/message.go
  type Message (line 4) | type Message interface

FILE: backend/pkg/anydoc/anydoc.go
  type Client (line 22) | type Client struct
    method GetUrlList (line 75) | func (c *Client) GetUrlList(ctx context.Context, targetURL, id string)...
    method UrlExport (line 115) | func (c *Client) UrlExport(ctx context.Context, id, docID, kbId string...
    method ensureSubscribed (line 169) | func (c *Client) ensureSubscribed() error {
    method TaskWaitForCompletion (line 192) | func (c *Client) TaskWaitForCompletion(ctx context.Context, taskID str...
    method TaskListPoll (line 227) | func (c *Client) TaskListPoll(ctx context.Context, ids []string) (*Tas...
    method handleTaskExportEvent (line 246) | func (c *Client) handleTaskExportEvent(ctx context.Context, msg types....
    method TaskList (line 272) | func (c *Client) TaskList(ctx context.Context, ids []string) (*TaskRes...
    method DownloadDoc (line 318) | func (c *Client) DownloadDoc(ctx context.Context, filepath string) ([]...
  constant apiUploaderUrl (line 33) | apiUploaderUrl     = "http://panda-wiki-api:8000/api/v1/file/upload/anydoc"
  constant uploaderDir (line 34) | uploaderDir        = "/image"
  constant crawlerServiceHost (line 35) | crawlerServiceHost = "http://panda-wiki-crawler:8080"
  constant SpaceIdCloud (line 36) | SpaceIdCloud       = "cloud_disk"
  constant getUrlPath (line 37) | getUrlPath         = "/api/docs/url/list"
  constant UrlExportPath (line 38) | UrlExportPath      = "/api/docs/url/export"
  constant TaskListPath (line 39) | TaskListPath       = "/api/tasks/list"
  type Status (line 42) | type Status
  constant StatusPending (line 45) | StatusPending    Status = "pending"
  constant StatusInProgress (line 46) | StatusInProgress Status = "in_process"
  constant StatusCompleted (line 47) | StatusCompleted  Status = "completed"
  constant StatusFailed (line 48) | StatusFailed     Status = "failed"
  type UploaderType (line 51) | type UploaderType
  constant uploaderTypeDefault (line 54) | uploaderTypeDefault UploaderType = iota
  constant uploaderTypeHTTP (line 55) | uploaderTypeHTTP
  function NewClient (line 58) | func NewClient(logger *log.Logger, mqConsumer mq.MQConsumer) (*Client, e...

FILE: backend/pkg/anydoc/confluence.go
  constant ConfluenceListPath (line 15) | ConfluenceListPath   = "/api/docs/confluence/list"
  constant ConfluenceExportPath (line 16) | ConfluenceExportPath = "/api/docs/confluence/export"
  type ConfluenceListDocsRequest (line 20) | type ConfluenceListDocsRequest struct
  type ConfluenceExportDocRequest (line 27) | type ConfluenceExportDocRequest struct
  type ConfluenceExportDocResponse (line 33) | type ConfluenceExportDocResponse struct
  type ConfluenceExportDocData (line 40) | type ConfluenceExportDocData struct
  method ConfluenceListDocs (line 47) | func (c *Client) ConfluenceListDocs(ctx context.Context, confluenceURL, ...
  method ConfluenceExportDoc (line 99) | func (c *Client) ConfluenceExportDoc(ctx context.Context, uuid, docID, k...

FILE: backend/pkg/anydoc/dingtalk.go
  constant dingtalkListPath (line 15) | dingtalkListPath   = "/api/docs/dingtalk/list"
  constant dingtalkExportPath (line 16) | dingtalkExportPath = "/api/docs/dingtalk/export"
  method DingtalkListDocs (line 20) | func (c *Client) DingtalkListDocs(ctx context.Context, uuid string, ding...

FILE: backend/pkg/anydoc/epub.go
  constant epubpListPath (line 15) | epubpListPath   = "/api/docs/epubp/list"
  constant epubpExportPath (line 16) | epubpExportPath = "/api/docs/epubp/export"
  type EpubpListDocsRequest (line 20) | type EpubpListDocsRequest struct
  type EpubpListDocsResponse (line 27) | type EpubpListDocsResponse struct
  type EpubpListDocsData (line 34) | type EpubpListDocsData struct
  type EpubpDoc (line 39) | type EpubpDoc struct
  type EpubpExportDocRequest (line 46) | type EpubpExportDocRequest struct
  type EpubpExportDocResponse (line 52) | type EpubpExportDocResponse struct
  type EpubpExportDocData (line 59) | type EpubpExportDocData struct
  method EpubpListDocs (line 66) | func (c *Client) EpubpListDocs(ctx context.Context, epubpURL, filename, ...
  method EpubpExportDoc (line 118) | func (c *Client) EpubpExportDoc(ctx context.Context, uuid, docID, kbId s...

FILE: backend/pkg/anydoc/feishu.go
  constant feishuListPath (line 15) | feishuListPath   = "/api/docs/feishu/list"
  constant feishuExportPath (line 16) | feishuExportPath = "/api/docs/feishu/export"
  type FeishuListDocsRequest (line 20) | type FeishuListDocsRequest struct
  type FeishuListDocsResponse (line 27) | type FeishuListDocsResponse struct
  type FeishuListDocsData (line 34) | type FeishuListDocsData struct
  type FeishuDoc (line 39) | type FeishuDoc struct
  type FeishuExportDocRequest (line 47) | type FeishuExportDocRequest struct
  type FeishuExportDocResponse (line 53) | type FeishuExportDocResponse struct
  type FeishuExportDocData (line 60) | type FeishuExportDocData struct
  method FeishuListDocs (line 67) | func (c *Client) FeishuListDocs(ctx context.Context, uuid, appId, appSec...
  method FeishuExportDoc (line 118) | func (c *Client) FeishuExportDoc(ctx context.Context, uuid, docID, fileT...

FILE: backend/pkg/anydoc/mindoc.go
  constant mindocListPath (line 15) | mindocListPath   = "/api/docs/mindoc/list"
  constant mindocExportPath (line 16) | mindocExportPath = "/api/docs/mindoc/export"
  type MindocListDocsRequest (line 20) | type MindocListDocsRequest struct
  type MindocListDocsResponse (line 27) | type MindocListDocsResponse struct
  type MindocListDocsData (line 34) | type MindocListDocsData struct
  type MindocDoc (line 39) | type MindocDoc struct
  type MindocExportDocRequest (line 46) | type MindocExportDocRequest struct
  type MindocExportDocResponse (line 52) | type MindocExportDocResponse struct
  type MindocExportDocData (line 59) | type MindocExportDocData struct
  method MindocListDocs (line 66) | func (c *Client) MindocListDocs(ctx context.Context, mindocURL, filename...
  method MindocExportDoc (line 118) | func (c *Client) MindocExportDoc(ctx context.Context, uuid, docID, kbId ...

FILE: backend/pkg/anydoc/notion.go
  constant notionListPath (line 15) | notionListPath   = "/api/docs/notion/list"
  constant notionExportPath (line 16) | notionExportPath = "/api/docs/notion/export"
  type NotionListDocsResponse (line 20) | type NotionListDocsResponse struct
  type NotionListDocsData (line 27) | type NotionListDocsData struct
  type NotionDoc (line 32) | type NotionDoc struct
  type NotionExportDocResponse (line 39) | type NotionExportDocResponse struct
  method NotionListDocs (line 46) | func (c *Client) NotionListDocs(ctx context.Context, secret, uuid string...
  method NotionExportDoc (line 93) | func (c *Client) NotionExportDoc(ctx context.Context, uuid, docID, kbId ...

FILE: backend/pkg/anydoc/req.go
  type FeishuSetting (line 3) | type FeishuSetting struct
  type DingtalkSetting (line 10) | type DingtalkSetting struct

FILE: backend/pkg/anydoc/res.go
  type GetUrlListResponse (line 3) | type GetUrlListResponse struct
  type GetUrlListData (line 10) | type GetUrlListData struct
  type UrlExportRes (line 19) | type UrlExportRes struct
  type TaskRes (line 26) | type TaskRes struct
  type ListDocResponse (line 40) | type ListDocResponse struct
  type ListDocsData (line 48) | type ListDocsData struct
  type Value (line 52) | type Value struct
  type Child (line 60) | type Child struct

FILE: backend/pkg/anydoc/rss.go
  constant rssListPath (line 15) | rssListPath   = "/api/docs/rss/list"
  constant rssExportPath (line 16) | rssExportPath = "/api/docs/rss/export"
  type RssListDocsResponse (line 20) | type RssListDocsResponse struct
  type RssListDocsData (line 27) | type RssListDocsData struct
  type RssDoc (line 32) | type RssDoc struct
  type RssExportDocRequest (line 40) | type RssExportDocRequest struct
  type RssExportDocResponse (line 46) | type RssExportDocResponse struct
  type RssExportDocData (line 53) | type RssExportDocData struct
  method RssListDocs (line 60) | func (c *Client) RssListDocs(ctx context.Context, xmlUrl, uuid string) (...
  method RssExportDoc (line 106) | func (c *Client) RssExportDoc(ctx context.Context, uuid, docID, kbId str...

FILE: backend/pkg/anydoc/sitemap.go
  constant sitemapListPath (line 15) | sitemapListPath   = "/api/docs/sitemap/list"
  constant sitemapExportPath (line 16) | sitemapExportPath = "/api/docs/sitemap/export"
  type SitemapListDocsResponse (line 20) | type SitemapListDocsResponse struct
  type SitemapListDocsData (line 27) | type SitemapListDocsData struct
  type SitemapDoc (line 32) | type SitemapDoc struct
  type SitemapExportDocRequest (line 40) | type SitemapExportDocRequest struct
  type SitemapExportDocResponse (line 46) | type SitemapExportDocResponse struct
  type SitemapExportDocData (line 53) | type SitemapExportDocData struct
  method SitemapListDocs (line 60) | func (c *Client) SitemapListDocs(ctx context.Context, xmlUrl, uuid strin...
  method SitemapExportDoc (line 106) | func (c *Client) SitemapExportDoc(ctx context.Context, uuid, docID, kbId...

FILE: backend/pkg/anydoc/siyuan.go
  constant siyuanListPath (line 15) | siyuanListPath   = "/api/docs/siyuan/list"
  constant siyuanExportPath (line 16) | siyuanExportPath = "/api/docs/siyuan/export"
  type SiyuanListDocsRequest (line 20) | type SiyuanListDocsRequest struct
  type SiyuanListDocsResponse (line 27) | type SiyuanListDocsResponse struct
  type SiyuanListDocsData (line 34) | type SiyuanListDocsData struct
  type SiyuanDoc (line 39) | type SiyuanDoc struct
  type SiyuanExportDocRequest (line 46) | type SiyuanExportDocRequest struct
  type SiyuanExportDocResponse (line 52) | type SiyuanExportDocResponse struct
  type SiyuanExportDocData (line 59) | type SiyuanExportDocData struct
  method SiyuanListDocs (line 66) | func (c *Client) SiyuanListDocs(ctx context.Context, siyuanURL, filename...
  method SiyuanExportDoc (line 118) | func (c *Client) SiyuanExportDoc(ctx context.Context, uuid, docID, kbId ...

FILE: backend/pkg/anydoc/wikijs.go
  constant wikijsListPath (line 15) | wikijsListPath   = "/api/docs/wikijs/list"
  constant wikijsExportPath (line 16) | wikijsExportPath = "/api/docs/wikijs/export"
  type WikijsListDocsRequest (line 20) | type WikijsListDocsRequest struct
  type WikijsExportDocRequest (line 27) | type WikijsExportDocRequest struct
  type WikijsExportDocResponse (line 33) | type WikijsExportDocResponse struct
  type WikijsExportDocData (line 40) | type WikijsExportDocData struct
  method WikijsListDocs (line 47) | func (c *Client) WikijsListDocs(ctx context.Context, wikijsURL, filename...
  method WikijsExportDoc (line 99) | func (c *Client) WikijsExportDoc(ctx context.Context, uuid, docID, kbId ...

FILE: backend/pkg/anydoc/yuque.go
  constant yuqueListPath (line 14) | yuqueListPath   = "/api/docs/yuque/list"
  constant yuqueExportPath (line 15) | yuqueExportPath = "/api/docs/yuque/export"
  type YuqueListDocsRequest (line 19) | type YuqueListDocsRequest struct
  type YuqueListDocsResponse (line 26) | type YuqueListDocsResponse struct
  type YuqueListDocsData (line 33) | type YuqueListDocsData struct
  type YuqueDoc (line 38) | type YuqueDoc struct
  type YuqueExportDocRequest (line 45) | type YuqueExportDocRequest struct
  type YuqueExportDocResponse (line 51) | type YuqueExportDocResponse struct
  method YuqueListDocs (line 58) | func (c *Client) YuqueListDocs(ctx context.Context, yuqueURL, filename, ...
  method YuqueExportDoc (line 110) | func (c *Client) YuqueExportDoc(ctx context.Context, uuid, docID, kbId s...

FILE: backend/pkg/bot/common.go
  type GetQAFun (line 9) | type GetQAFun

FILE: backend/pkg/bot/dingtalk/stream.go
  type DingTalkClient (line 28) | type DingTalkClient struct
    method GetAccessToken (line 70) | func (c *DingTalkClient) GetAccessToken() (string, error) {
    method UpdateAIStreamCard (line 115) | func (c *DingTalkClient) UpdateAIStreamCard(trackID, content string, i...
    method CreateAndDeliverCard (line 140) | func (c *DingTalkClient) CreateAndDeliverCard(ctx context.Context, tra...
    method OnChatBotMessageReceived (line 194) | func (c *DingTalkClient) OnChatBotMessageReceived(ctx context.Context,...
    method Start (line 284) | func (c *DingTalkClient) Start() error {
    method Stop (line 299) | func (c *DingTalkClient) Stop() {
    method GetUserInfo (line 328) | func (c *DingTalkClient) GetUserInfo(userID string) (*UserDetailRespon...
  function NewDingTalkClient (line 45) | func NewDingTalkClient(ctx context.Context, cancel context.CancelFunc, c...
  type UserDetailResponse (line 304) | type UserDetailResponse struct
  type UserDetails (line 310) | type UserDetails struct

FILE: backend/pkg/bot/discord/discord_test.go
  function TestDiscord (line 12) | func TestDiscord(t *testing.T) {

FILE: backend/pkg/bot/discord/stream.go
  type DiscordClient (line 15) | type DiscordClient struct
    method Start (line 35) | func (d *DiscordClient) Start() error {
    method Stop (line 44) | func (d *DiscordClient) Stop() error {
    method handleMessage (line 48) | func (d *DiscordClient) handleMessage(s *discordgo.Session, m *discord...
  function NewDiscordClient (line 22) | func NewDiscordClient(logger *log.Logger, BotToken string, getQA bot.Get...

FILE: backend/pkg/bot/feishu/stream.go
  type FeishuBotLogger (line 24) | type FeishuBotLogger struct
    method Info (line 28) | func (l *FeishuBotLogger) Info(ctx context.Context, args ...interface{...
    method Error (line 32) | func (l *FeishuBotLogger) Error(ctx context.Context, args ...interface...
    method Debug (line 36) | func (l *FeishuBotLogger) Debug(ctx context.Context, args ...interface...
    method Warn (line 40) | func (l *FeishuBotLogger) Warn(ctx context.Context, args ...interface{...
  type FeishuClient (line 44) | type FeishuClient struct
    method sendQACard (line 90) | func (c *FeishuClient) sendQACard(ctx context.Context, receiveIdType s...
    method Start (line 224) | func (c *FeishuClient) Start() error {
    method GetUserInfo (line 277) | func (c *FeishuClient) GetUserInfo(UserOpenId string) (*larkcontact.Us...
    method Stop (line 297) | func (c *FeishuClient) Stop() {
  function NewFeishuClient (line 55) | func NewFeishuClient(ctx context.Context, cancel context.CancelFunc, cli...
  type Message (line 220) | type Message struct

FILE: backend/pkg/bot/lark/client.go
  type LarkBotLogger (line 25) | type LarkBotLogger struct
    method Info (line 29) | func (l *LarkBotLogger) Info(ctx context.Context, args ...interface{}) {
    method Error (line 33) | func (l *LarkBotLogger) Error(ctx context.Context, args ...interface{}) {
    method Debug (line 37) | func (l *LarkBotLogger) Debug(ctx context.Context, args ...interface{}) {
    method Warn (line 41) | func (l *LarkBotLogger) Warn(ctx context.Context, args ...interface{}) {
  type LarkClient (line 47) | type LarkClient struct
    method setupEventHandler (line 108) | func (c *LarkClient) setupEventHandler() {
    method GetEventHandler (line 149) | func (c *LarkClient) GetEventHandler() *dispatcher.EventDispatcher {
    method sendQACard (line 155) | func (c *LarkClient) sendQACard(ctx context.Context, receiveIdType str...
    method replaceMentions (line 296) | func (c *LarkClient) replaceMentions(text string, mentions []*larkim.M...
    method Start (line 314) | func (c *LarkClient) Start() error {
    method GetUserInfo (line 327) | func (c *LarkClient) GetUserInfo(UserOpenId string) (*larkcontact.User...
    method Stop (line 344) | func (c *LarkClient) Stop() {
  function NewLarkClient (line 64) | func NewLarkClient(ctx context.Context, cancel context.CancelFunc, clien...
  type Message (line 291) | type Message struct

FILE: backend/pkg/bot/utils/utils.go
  function Markdown2HTML (line 7) | func Markdown2HTML(md string) string {

FILE: backend/pkg/bot/wechat/domain.go
  type WechatConfig (line 13) | type WechatConfig struct
  type ReceivedMessage (line 28) | type ReceivedMessage struct
  type ResponseMessage (line 37) | type ResponseMessage struct
  type CDATA (line 46) | type CDATA struct
  type BackendRequest (line 50) | type BackendRequest struct
  type BackendResponse (line 55) | type BackendResponse struct
  type UserInfo (line 64) | type UserInfo struct
  type AccessToken (line 76) | type AccessToken struct
  type TokenCache (line 83) | type TokenCache struct
  function getTokenCacheKey (line 94) | func getTokenCacheKey(kbID, agentID string) string {
  type MediaUploadResponse (line 100) | type MediaUploadResponse struct

FILE: backend/pkg/bot/wechat/wechat.go
  constant wechatMessageMaxBytes (line 23) | wechatMessageMaxBytes = 2000
  function NewWechatAppConfig (line 25) | func NewWechatAppConfig(ctx context.Context, logger *log.Logger, kbId, C...
  method VerifyUrlWechatAPP (line 38) | func (cfg *WechatConfig) VerifyUrlWechatAPP(signature, timestamp, nonce,...
  method Wechat (line 55) | func (cfg *WechatConfig) Wechat(msg ReceivedMessage, getQA bot.GetQAFun,...
  method ProcessUrlMessage (line 78) | func (cfg *WechatConfig) ProcessUrlMessage(msg ReceivedMessage, GetQA bo...
  method ProcessTextMessage (line 126) | func (cfg *WechatConfig) ProcessTextMessage(msg ReceivedMessage, GetQA b...
  method SendURLToUser (line 175) | func (cfg *WechatConfig) SendURLToUser(touser, question, token, conversa...
  method SendResponseToUser (line 212) | func (cfg *WechatConfig) SendResponseToUser(response string, touser stri...
  method SendResponse (line 252) | func (cfg *WechatConfig) SendResponse(msg ReceivedMessage, content strin...
  method GetAccessToken (line 281) | func (cfg *WechatConfig) GetAccessToken() (string, error) {
  method GetUserInfo (line 335) | func (cfg *WechatConfig) GetUserInfo(username string) (*UserInfo, error) {
  method UnmarshalMsg (line 369) | func (cfg *WechatConfig) UnmarshalMsg(decryptMsg []byte) (*ReceivedMessa...
  method SendQuestionToAI (line 376) | func (cfg *WechatConfig) SendQuestionToAI(conversationID string, wcconte...

FILE: backend/pkg/bot/wechat_official_account/official_account.go
  function Wechat (line 14) | func Wechat(ctx context.Context, GetQA bot.GetQAFun, userinfo *user.Info...

FILE: backend/pkg/bot/wechat_service/domain.go
  type WechatServiceConfig (line 12) | type WechatServiceConfig struct
  type WeixinUserAskMsg (line 31) | type WeixinUserAskMsg struct
  type AccessToken (line 40) | type AccessToken struct
  type MsgRequest (line 47) | type MsgRequest struct
  type MsgRet (line 55) | type MsgRet struct
  type Msg (line 63) | type Msg struct
  type ReplyMsg (line 83) | type ReplyMsg struct
  type ReplyMsgUrl (line 94) | type ReplyMsgUrl struct
  type Link (line 102) | type Link struct
  type MediaUploadResponse (line 110) | type MediaUploadResponse struct
  type WechatCustomerResponse (line 119) | type WechatCustomerResponse struct
  type Customer (line 126) | type Customer struct
  type UerInfoRequest (line 134) | type UerInfoRequest struct
  type Status (line 140) | type Status struct
  type HumanList (line 147) | type HumanList struct
  type ServicerList (line 153) | type ServicerList struct
  type TokenCache (line 158) | type TokenCache struct
  function getTokenCacheKey (line 169) | func getTokenCacheKey(kbID, secret string) string {
  type UserImageCache (line 173) | type UserImageCache struct
  type DefaultImageCache (line 182) | type DefaultImageCache struct

FILE: backend/pkg/bot/wechat_service/tools.go
  function getCursor (line 19) | func getCursor(openKfId string) string {
  function setCursor (line 26) | func setCursor(openKfId, cursor string) {
  function CheckSessionState (line 30) | func CheckSessionState(token, extrenaluserid, kfId string) (int, error) {
  function ChangeState (line 68) | func ChangeState(token, extrenaluserId, kfId string, state int, serviceI...
  function GetUserInfo (line 113) | func GetUserInfo(userid string, accessToken string) (*Customer, error) {
  function GetUserImageID (line 150) | func GetUserImageID(accessToken, filePath string) (string, error) {
  function GetDefaultImageID (line 172) | func GetDefaultImageID(accessToken, ImageBase64 string) (string, error) {
  function UploadMediaFromURL (line 193) | func UploadMediaFromURL(accessToken, fileURL string) (string, error) {
  function UploadMediaFromBase64 (line 219) | func UploadMediaFromBase64(accessToken, base64Data string) (string, erro...
  function uploadMediaToWechat (line 239) | func uploadMediaToWechat(accessToken string, reader io.Reader, fileName ...
  function getMsgs (line 285) | func getMsgs(accessToken string, msg *WeixinUserAskMsg) (*MsgRet, error) {
  function MarkdowntoText (line 319) | func MarkdowntoText(md string) string {

FILE: backend/pkg/bot/wechat_service/wechat.go
  function NewWechatServiceConfig (line 25) | func NewWechatServiceConfig(ctx context.Context, logger *log.Logger, KbI...
  method VerifyUrlWechatService (line 40) | func (cfg *WechatServiceConfig) VerifyUrlWechatService(signature, timest...
  method Wechat (line 57) | func (cfg *WechatServiceConfig) Wechat(msg *WeixinUserAskMsg, getQA bot....
  method Processmessage (line 81) | func (cfg *WechatServiceConfig) Processmessage(msgRet *MsgRet, Kfmsg *We...
  method getImageID (line 188) | func (cfg *WechatServiceConfig) getImageID(token, image string) (string,...
  method SendResponseToKfUrl (line 218) | func (cfg *WechatServiceConfig) SendResponseToKfUrl(userId, openkfId, co...
  method SendResponseToKfTxt (line 243) | func (cfg *WechatServiceConfig) SendResponseToKfTxt(userId string, openk...
  method SendMessage (line 261) | func (cfg *WechatServiceConfig) SendMessage(jsonData []byte, token strin...
  method GetAccessToken (line 297) | func (cfg *WechatServiceConfig) GetAccessToken() (string, error) {
  method UnmarshalMsg (line 352) | func (cfg *WechatServiceConfig) UnmarshalMsg(decryptMsg []byte) (*Weixin...
  method GetKfHumanList (line 358) | func (cfg *WechatServiceConfig) GetKfHumanList(token string, KfId string...
  method SendQuestionToAI (line 381) | func (cfg *WechatServiceConfig) SendQuestionToAI(conversationID string, ...

FILE: backend/pkg/bot/wecom/ai_bot.go
  type AIBotClient (line 12) | type AIBotClient struct
    method VerifyUrlWecomService (line 66) | func (c *AIBotClient) VerifyUrlWecomService(signature, timestamp, nonc...
    method DecryptUserReq (line 85) | func (c *AIBotClient) DecryptUserReq(signature, timestamp, nonce, msg ...
    method MakeStreamResp (line 111) | func (c *AIBotClient) MakeStreamResp(nonce, id, content string, isFini...
  type UserReq (line 19) | type UserReq struct
  type UserResp (line 34) | type UserResp struct
  type Stream (line 39) | type Stream struct
  function NewAIBotClient (line 52) | func NewAIBotClient(

FILE: backend/pkg/bot/wecom/crypt.go
  constant WXBizMsgCrypt_OK (line 23) | WXBizMsgCrypt_OK                        = 0
  constant WXBizMsgCrypt_ValidateSignature_Error (line 24) | WXBizMsgCrypt_ValidateSignature_Error   = 40001
  constant WXBizMsgCrypt_ParseJson_Error (line 25) | WXBizMsgCrypt_ParseJson_Error           = 40002
  constant WXBizMsgCrypt_ComputeSignature_Error (line 26) | WXBizMsgCrypt_ComputeSignature_Error    = 40003
  constant WXBizMsgCrypt_IllegalAesKey (line 27) | WXBizMsgCrypt_IllegalAesKey             = 40004
  constant WXBizMsgCrypt_EncryptAES_Error (line 28) | WXBizMsgCrypt_EncryptAES_Error          = 40005
  constant WXBizMsgCrypt_DecryptAES_Error (line 29) | WXBizMsgCrypt_DecryptAES_Error          = 40006
  constant WXBizMsgCrypt_IllegalBuffer (line 30) | WXBizMsgCrypt_IllegalBuffer             = 40007
  constant WXBizMsgCrypt_ValidateCorpid_Error (line 31) | WXBizMsgCrypt_ValidateCorpid_Error      = 40008
  constant WXBizMsgCrypt_ValidateCorpid_Receive_Id (line 32) | WXBizMsgCrypt_ValidateCorpid_Receive_Id = 40009
  constant WXBizMsgCrypt_ValidateCorpid_Mismatch (line 33) | WXBizMsgCrypt_ValidateCorpid_Mismatch   = 40010
  method getErrorMessage (line 50) | func (c *AIBotClient) getErrorMessage(code int) error {
  type SHA1 (line 60) | type SHA1 struct
    method GetSHA1 (line 64) | func (s *SHA1) GetSHA1(token, timestamp, nonce string, encrypt interfa...
  type JsonParse (line 91) | type JsonParse struct
    method Extract (line 102) | func (jp *JsonParse) Extract(jsonText string) (int, string) {
    method Generate (line 114) | func (jp *JsonParse) Generate(encrypt, signature, timestamp, nonce str...
  type aesTextResponse (line 93) | type aesTextResponse struct
  type PKCS7Encoder (line 126) | type PKCS7Encoder struct
    method Encode (line 134) | func (p *PKCS7Encoder) Encode(src []byte) []byte {
    method Decode (line 148) | func (p *PKCS7Encoder) Decode(decrypted []byte) ([]byte, error) {
  function NewPKCS7Encoder (line 130) | func NewPKCS7Encoder() *PKCS7Encoder {
  type Prpcrypt (line 161) | type Prpcrypt struct
    method Encrypt (line 171) | func (pc *Prpcrypt) Encrypt(plainText string, receiveID string) (int, ...
    method Decrypt (line 220) | func (pc *Prpcrypt) Decrypt(base64Cipher string, receiveID string) (in...
  function NewPrpcrypt (line 166) | func NewPrpcrypt(key []byte) *Prpcrypt {
  function getRandom16BytesAsDigits (line 270) | func getRandom16BytesAsDigits() ([]byte, error) {
  type WXBizJsonMsgCrypt (line 284) | type WXBizJsonMsgCrypt struct
    method VerifyURL (line 311) | func (w *WXBizJsonMsgCrypt) VerifyURL(sMsgSignature, sTimeStamp, sNonc...
    method EncryptMsg (line 327) | func (w *WXBizJsonMsgCrypt) EncryptMsg(sReplyMsg, sNonce string, times...
    method DecryptMsg (line 358) | func (w *WXBizJsonMsgCrypt) DecryptMsg(sPostData, sMsgSignature, sTime...
  function NewWXBizJsonMsgCrypt (line 292) | func NewWXBizJsonMsgCrypt(sToken, sEncodingAESKey, sReceiveID string) (*...

FILE: backend/pkg/captcha/captcha.go
  type Captcha (line 5) | type Captcha struct
  function NewCaptcha (line 9) | func NewCaptcha() *Captcha {

FILE: backend/pkg/cas/cas.go
  type Client (line 16) | type Client struct
    method GetLoginURL (line 125) | func (c *Client) GetLoginURL(state string) string {
    method ValidateTicket (line 135) | func (c *Client) ValidateTicket(ticket, state string) (*UserInfo, erro...
    method parseCAS2Response (line 173) | func (c *Client) parseCAS2Response(body []byte) (*UserInfo, error) {
    method parseCAS3Response (line 199) | func (c *Client) parseCAS3Response(body []byte) (*UserInfo, error) {
  type Config (line 23) | type Config struct
  type UserInfo (line 32) | type UserInfo struct
  type CAS2ServiceResponse (line 38) | type CAS2ServiceResponse struct
  type CAS2AuthenticationSuccess (line 44) | type CAS2AuthenticationSuccess struct
  type CAS3ServiceResponse (line 49) | type CAS3ServiceResponse struct
  type CAS3AuthenticationSuccess (line 55) | type CAS3AuthenticationSuccess struct
  type AuthenticationFailure (line 60) | type AuthenticationFailure struct
  type CAS3Attributes (line 65) | type CAS3Attributes struct
  constant defaultLoginPath (line 72) | defaultLoginPath        = "/login"
  constant defaultValidatePathCAS2 (line 73) | defaultValidatePathCAS2 = "/serviceValidate"
  constant defaultValidatePathCAS3 (line 74) | defaultValidatePathCAS3 = "/p3/serviceValidate"
  constant callbackPath (line 75) | callbackPath            = "/share/pro/v1/openapi/cas/callback"
  function NewClient (line 79) | func NewClient(ctx context.Context, logger *log.Logger, config Config) (...

FILE: backend/pkg/dingtalk/dingtalk.go
  constant callbackPath (line 23) | callbackPath      = "/share/pro/v1/openapi/dingtalk/callback"
  constant userInfoUrl (line 24) | userInfoUrl       = "https://api.dingtalk.com/v1.0/contact/users/me"
  constant DepartmentListUrl (line 25) | DepartmentListUrl = "https://oapi.dingtalk.com/department/list"
  constant UserListUrl (line 27) | UserListUrl = "https://oapi.dingtalk.com/topapi/v2/user/list"
  type Client (line 30) | type Client struct
    method GenerateAuthURL (line 122) | func (c *Client) GenerateAuthURL(baseUrl string, state string) string {
    method GetAccessTokenByCode (line 140) | func (c *Client) GetAccessTokenByCode(code string) (string, error) {
    method GetAccessToken (line 155) | func (c *Client) GetAccessToken() (string, error) {
    method GetUserInfoByCode (line 193) | func (c *Client) GetUserInfoByCode(code string) (*UserInfo, error) {
    method GetDepartmentList (line 231) | func (c *Client) GetDepartmentList() (*DepartmentListRsp, error) {
    method GetAllUserList (line 276) | func (c *Client) GetAllUserList(deptID int) ([]UserDetail, error) {
    method GetUserList (line 297) | func (c *Client) GetUserList(deptID int) (*GetUserListResp, error) {
  type UserInfo (line 43) | type UserInfo struct
  type DepartmentListRsp (line 52) | type DepartmentListRsp struct
  type GetUserListResp (line 64) | type GetUserListResp struct
  type UserDetail (line 73) | type UserDetail struct
  function NewDingTalkClient (line 96) | func NewDingTalkClient(ctx context.Context, logger *log.Logger, clientId...

FILE: backend/pkg/feishu/feishu.go
  constant AuthURL (line 16) | AuthURL      = "https://accounts.feishu.cn/open-apis/authen/v1/authorize"
  constant TokenURL (line 17) | TokenURL     = "https://open.feishu.cn/open-apis/authen/v2/oauth/token"
  constant UserInfoURL (line 18) | UserInfoURL  = "https://open.feishu.cn/open-apis/authen/v1/user_info"
  constant callbackPath (line 19) | callbackPath = "/share/pro/v1/openapi/feishu/callback"
  type Client (line 28) | type Client struct
    method GenerateAuthURL (line 78) | func (c *Client) GenerateAuthURL(state string, verifier string) string {
    method GetAccessToken (line 83) | func (c *Client) GetAccessToken(ctx context.Context, code string, code...
    method GetUserInfoByCode (line 92) | func (c *Client) GetUserInfoByCode(ctx context.Context, code string, c...
  type Response (line 34) | type Response struct
  type UserInfo (line 39) | type UserInfo struct
  function NewClient (line 56) | func NewClient(ctx context.Context, logger *log.Logger, appID, appSecret...

FILE: backend/pkg/ldap/ldap.go
  type Client (line 13) | type Client struct
    method Authenticate (line 79) | func (c *Client) Authenticate(username, password string) (*UserInfo, e...
    method searchUser (line 119) | func (c *Client) searchUser(conn *ldap.Conn, username string) (*UserIn...
    method getAttributeValue (line 184) | func (c *Client) getAttributeValue(entry *ldap.Entry, attrName string)...
    method TestConnection (line 193) | func (c *Client) TestConnection() error {
  type Config (line 19) | type Config struct
  type UserInfo (line 30) | type UserInfo struct
  constant defaultUserIDAttr (line 38) | defaultUserIDAttr    = "uid"
  constant defaultUserNameAttr (line 39) | defaultUserNameAttr  = "cn"
  constant defaultUserEmailAttr (line 40) | defaultUserEmailAttr = "mail"
  constant defaultUserFilter (line 41) | defaultUserFilter    = "(&(objectClass=person)(uid=%s))"
  function NewClient (line 45) | func NewClient(ctx context.Context, logger *log.Logger, config Config) (...

FILE: backend/pkg/oauth/github.go
  constant githubAuthorizeURL (line 19) | githubAuthorizeURL    = "https://github.com/login/oauth/authorize"
  constant githubTokenURL (line 20) | githubTokenURL        = "https://github.com/login/oauth/access_token"
  constant githubUserInfoURL (line 21) | githubUserInfoURL     = "https://api.github.com/user"
  constant githubUserEmailURL (line 22) | githubUserEmailURL    = "https://api.github.com/user/emails"
  constant githubCallbackPathPro (line 23) | githubCallbackPathPro = "/share/pro/v1/openapi/github/callback"
  constant githubCallbackPath (line 24) | githubCallbackPath    = "/share/v1/openapi/github/callback"
  function NewGithubClient (line 27) | func NewGithubClient(ctx context.Context, logger *log.Logger, clientID, ...
  method GetGithubPrimaryEmail (line 97) | func (c *Client) GetGithubPrimaryEmail(token *oauth2.Token) (string, err...

FILE: backend/pkg/oauth/oauth.go
  type Client (line 15) | type Client struct
    method GetAuthorizeURL (line 71) | func (c *Client) GetAuthorizeURL(state string) string {
    method GetUserInfo (line 75) | func (c *Client) GetUserInfo(code string) (*UserInfo, error) {
  constant callbackPath (line 24) | callbackPath = "/share/pro/v1/openapi/oauth/callback"
  type Config (line 27) | type Config struct
  type UserInfo (line 40) | type UserInfo struct
  function NewClient (line 48) | func NewClient(ctx context.Context, logger *log.Logger, baseUrl string, ...

FILE: backend/pkg/ratelimit/rate_limiter.go
  type RateLimiter (line 15) | type RateLimiter struct
    method CheckIPLocked (line 38) | func (r *RateLimiter) CheckIPLocked(ctx context.Context, ip string) (b...
    method LockAttempt (line 54) | func (r *RateLimiter) LockAttempt(ctx context.Context, ip string) {
    method ResetLoginAttempts (line 90) | func (r *RateLimiter) ResetLoginAttempts(ctx context.Context, ip strin...
  function NewRateLimiter (line 20) | func NewRateLimiter(logger *log.Logger, cache *cache.Cache) *RateLimiter {
  constant LockThreshold1 (line 28) | LockThreshold1    = 5
  constant LockThreshold2 (line 29) | LockThreshold2    = 10
  constant LockThreshold3 (line 30) | LockThreshold3    = 15
  constant AttemptsKeyExpiry (line 31) | AttemptsKeyExpiry = 24 * time.Hour

FILE: backend/pkg/wecom/wecom.go
  constant AuthWebURL (line 21) | AuthWebURL    = "https://login.work.weixin.qq.com/wwlogin/sso/login"
  constant AuthAPPURL (line 22) | AuthAPPURL    = "https://open.weixin.qq.com/connect/oauth2/authorize"
  constant TokenURL (line 23) | TokenURL      = "https://qyapi.weixin.qq.com/cgi-bin/gettoken"
  constant UserInfoURL (line 24) | UserInfoURL   = "https://qyapi.weixin.qq.com/cgi-bin/auth/getuserinfo"
  constant UserDetailURL (line 25) | UserDetailURL = "https://qyapi.weixin.qq.com/cgi-bin/user/get"
  constant DepartmentListURL (line 27) | DepartmentListURL = "https://qyapi.weixin.qq.com/cgi-bin/department/list"
  constant UserListUrl (line 29) | UserListUrl  = "https://qyapi.weixin.qq.com/cgi-bin/user/list"
  constant callbackPath (line 30) | callbackPath = "/share/pro/v1/openapi/wecom/callback"
  type Client (line 34) | type Client struct
    method GenerateAuthURL (line 148) | func (c *Client) GenerateAuthURL(state string) string {
    method GetAccessToken (line 166) | func (c *Client) GetAccessToken(ctx context.Context) (string, error) {
    method GetUserInfoByCode (line 201) | func (c *Client) GetUserInfoByCode(ctx context.Context, code string) (...
    method GetDepartmentList (line 268) | func (c *Client) GetDepartmentList(ctx context.Context) (*DepartmentLi...
    method GetUserList (line 308) | func (c *Client) GetUserList(ctx context.Context, deptID string) (*Use...
  type TokenResponse (line 44) | type TokenResponse struct
  type UserInfoResponse (line 51) | type UserInfoResponse struct
  type UserDetailResponse (line 60) | type UserDetailResponse struct
  type DepartmentListResponse (line 71) | type DepartmentListResponse struct
  type UserListResponse (line 84) | type UserListResponse struct
  function NewClient (line 114) | func NewClient(ctx context.Context, logger *log.Logger, corpID, corpSecr...

FILE: backend/repo/cache/geo.go
  type GeoRepo (line 16) | type GeoRepo struct
    method SetGeo (line 30) | func (r *GeoRepo) SetGeo(ctx context.Context, kbID, field string) error {
    method GetLast24HourGeo (line 48) | func (r *GeoRepo) GetLast24HourGeo(ctx context.Context, kbID string) (...
    method GetGeoByHour (line 73) | func (r *GeoRepo) GetGeoByHour(ctx context.Context, kbID string, start...
  function NewGeoCache (line 22) | func NewGeoCache(cache *cache.Cache, db *pg.DB, logger *log.Logger) *Geo...

FILE: backend/repo/cache/kb.go
  type KBRepo (line 13) | type KBRepo struct
    method GetKB (line 21) | func (r *KBRepo) GetKB(ctx context.Context, kbID string) (*domain.Know...
    method SetKB (line 41) | func (r *KBRepo) SetKB(ctx context.Context, kbID string, kb *domain.Kn...
    method DeleteKB (line 49) | func (r *KBRepo) DeleteKB(ctx context.Context, kbID string) error {
    method ClearSession (line 53) | func (r *KBRepo) ClearSession(ctx context.Context) error {
  function NewKBRepo (line 17) | func NewKBRepo(cache *cache.Cache) *KBRepo {

FILE: backend/repo/ipdb/ip_addr.go
  type IPAddressRepo (line 13) | type IPAddressRepo struct
    method GetIPAddress (line 22) | func (r *IPAddressRepo) GetIPAddress(ctx context.Context, ip string) (...
    method GetIPAddresses (line 52) | func (r *IPAddressRepo) GetIPAddresses(ctx context.Context, ips []stri...
  function NewIPAddressRepo (line 18) | func NewIPAddressRepo(ipdb *ipdb.IPDB, logger *log.Logger) *IPAddressRepo {

FILE: backend/repo/mq/rag.go
  type RAGRepository (line 11) | type RAGRepository struct
    method AsyncUpdateNodeReleaseVector (line 19) | func (r *RAGRepository) AsyncUpdateNodeReleaseVector(ctx context.Conte...
  function NewRAGRepository (line 15) | func NewRAGRepository(producer mq.MQProducer) *RAGRepository {

FILE: backend/repo/pg/ap_token.go
  type APITokenRepo (line 17) | type APITokenRepo struct
    method GetByTokenWithCache (line 31) | func (r *APITokenRepo) GetByTokenWithCache(ctx context.Context, token ...
  function NewAPITokenRepo (line 23) | func NewAPITokenRepo(db *pg.DB, logger *log.Logger, cache *cache.Cache) ...

FILE: backend/repo/pg/app.go
  type AppRepository (line 16) | type AppRepository struct
    method GetAppDetail (line 28) | func (r *AppRepository) GetAppDetail(ctx context.Context, id string) (...
    method UpdateApp (line 39) | func (r *AppRepository) UpdateApp(ctx context.Context, id, kbId string...
    method DeleteApp (line 50) | func (r *AppRepository) DeleteApp(ctx context.Context, id, kbId string...
    method GetOrCreateAppByKBIDAndType (line 54) | func (r *AppRepository) GetOrCreateAppByKBIDAndType(ctx context.Contex...
    method GetAppsByTypes (line 81) | func (r *AppRepository) GetAppsByTypes(ctx context.Context, appTypes [...
    method GetAppList (line 92) | func (r *AppRepository) GetAppList(ctx context.Context, kbID string) (...
  function NewAppRepository (line 21) | func NewAppRepository(db *pg.DB, logger *log.Logger) *AppRepository {

FILE: backend/repo/pg/auth.go
  type AuthRepo (line 19) | type AuthRepo struct
    method GetAuthUserinfoByIDs (line 33) | func (r *AuthRepo) GetAuthUserinfoByIDs(ctx context.Context, authIDs [...
    method GetAuthGroupByAuthId (line 55) | func (r *AuthRepo) GetAuthGroupByAuthId(ctx context.Context, authID ui...
    method getAllAuthGroupsAsMap (line 68) | func (r *AuthRepo) getAllAuthGroupsAsMap(ctx context.Context) (map[uin...
    method getAuthGroupsWithParentsByAuthId (line 83) | func (r *AuthRepo) getAuthGroupsWithParentsByAuthId(ctx context.Contex...
    method GetAuthGroupWithParentsByAuthId (line 136) | func (r *AuthRepo) GetAuthGroupWithParentsByAuthId(ctx context.Context...
    method GetAuthGroupIdsByAuthId (line 150) | func (r *AuthRepo) GetAuthGroupIdsByAuthId(ctx context.Context, authID...
    method GetAuthGroupIdsWithParentsByAuthId (line 163) | func (r *AuthRepo) GetAuthGroupIdsWithParentsByAuthId(ctx context.Cont...
    method GetAuthBySourceType (line 177) | func (r *AuthRepo) GetAuthBySourceType(ctx context.Context, sourceType...
    method GetAuthByKBIDAndSourceType (line 185) | func (r *AuthRepo) GetAuthByKBIDAndSourceType(ctx context.Context, kbI...
    method CreateAuth (line 193) | func (r *AuthRepo) CreateAuth(ctx context.Context, auth *domain.Auth) ...
    method DeleteAuth (line 197) | func (r *AuthRepo) DeleteAuth(ctx context.Context, kbID string, authId...
    method CreateAuthConfig (line 201) | func (r *AuthRepo) CreateAuthConfig(ctx context.Context, authConfig *d...
    method GetAuthById (line 231) | func (r *AuthRepo) GetAuthById(ctx context.Context, kbID string, id ui...
    method GetAuthConfig (line 243) | func (r *AuthRepo) GetAuthConfig(ctx context.Context, kbID string, sou...
    method GetAuths (line 258) | func (r *AuthRepo) GetAuths(ctx context.Context, kbID string, sourceTy...
    method GetOrCreateAuth (line 272) | func (r *AuthRepo) GetOrCreateAuth(ctx context.Context, auth *domain.A...
  function NewAuthRepo (line 25) | func NewAuthRepo(db *pg.DB, logger *log.Logger, cache *cache.Cache) *Aut...

FILE: backend/repo/pg/block_word.go
  type BlockWordRepo (line 14) | type BlockWordRepo struct
    method GetBlockWords (line 30) | func (r *BlockWordRepo) GetBlockWords(ctx context.Context, kbID string...
  type BlockWords (line 19) | type BlockWords struct
  function NewBlockWordRepo (line 23) | func NewBlockWordRepo(db *pg.DB, logger *log.Logger) *BlockWordRepo {

FILE: backend/repo/pg/comment.go
  type CommentRepository (line 12) | type CommentRepository struct
    method CreateComment (line 21) | func (r *CommentRepository) CreateComment(ctx context.Context, comment...
    method GetCommentList (line 29) | func (r *CommentRepository) GetCommentList(ctx context.Context, nodeID...
    method GetCommentListByKbID (line 51) | func (r *CommentRepository) GetCommentListByKbID(ctx context.Context, ...
    method DeleteCommentList (line 85) | func (r *CommentRepository) DeleteCommentList(ctx context.Context, com...
  function NewCommentRepository (line 17) | func NewCommentRepository(db *pg.DB, logger *log.Logger) *CommentReposit...

FILE: backend/repo/pg/conversation.go
  type ConversationRepository (line 16) | type ConversationRepository struct
    method CreateConversationMessage (line 25) | func (r *ConversationRepository) CreateConversationMessage(ctx context...
    method CreateConversation (line 37) | func (r *ConversationRepository) CreateConversation(ctx context.Contex...
    method GetConversationList (line 41) | func (r *ConversationRepository) GetConversationList(ctx context.Conte...
    method GetConversationDetail (line 72) | func (r *ConversationRepository) GetConversationDetail(ctx context.Con...
    method GetConversationReferences (line 87) | func (r *ConversationRepository) GetConversationReferences(ctx context...
    method GetConversationMessagesByID (line 98) | func (r *ConversationRepository) GetConversationMessagesByID(ctx conte...
    method ValidateConversationNonce (line 110) | func (r *ConversationRepository) ValidateConversationNonce(ctx context...
    method GetConversationDistribution (line 122) | func (r *ConversationRepository) GetConversationDistribution(ctx conte...
    method GetConversationCount (line 136) | func (r *ConversationRepository) GetConversationCount(ctx context.Cont...
    method GetConversationMessagesDetailByID (line 148) | func (r *ConversationRepository) GetConversationMessagesDetailByID(ctx...
    method GetConversationMessagesDetailByKbID (line 159) | func (r *ConversationRepository) GetConversationMessagesDetailByKbID(c...
    method UpdateMessageFeedback (line 172) | func (r *ConversationRepository) UpdateMessageFeedback(ctx context.Con...
    method GetConversationFeedBackInfoByIDs (line 189) | func (r *ConversationRepository) GetConversationFeedBackInfoByIDs(ctx ...
    method GetMessageFeedBackList (line 211) | func (r *ConversationRepository) GetMessageFeedBackList(ctx context.Co...
    method GetConversationDistributionByHour (line 248) | func (r *ConversationRepository) GetConversationDistributionByHour(ctx...
    method GetConversationCountByAppType (line 272) | func (r *ConversationRepository) GetConversationCountByAppType(ctx con...
  function NewConversationRepository (line 21) | func NewConversationRepository(db *pg.DB, logger *log.Logger) *Conversat...

FILE: backend/repo/pg/knowledge_base.go
  type KnowledgeBaseRepository (line 29) | type KnowledgeBaseRepository struct
    method SyncKBAccessSettingsToCaddy (line 57) | func (r *KnowledgeBaseRepository) SyncKBAccessSettingsToCaddy(ctx cont...
    method CreateKnowledgeBase (line 342) | func (r *KnowledgeBaseRepository) CreateKnowledgeBase(ctx context.Cont...
    method checkUniquePortHost (line 440) | func (r *KnowledgeBaseRepository) checkUniquePortHost(kbList []*domain...
    method GetKnowledgeBaseList (line 469) | func (r *KnowledgeBaseRepository) GetKnowledgeBaseList(ctx context.Con...
    method GetKnowledgeBaseIds (line 480) | func (r *KnowledgeBaseRepository) GetKnowledgeBaseIds(ctx context.Cont...
    method GetKnowledgeBaseListByUserId (line 490) | func (r *KnowledgeBaseRepository) GetKnowledgeBaseListByUserId(ctx con...
    method UpdateDatasetID (line 544) | func (r *KnowledgeBaseRepository) UpdateDatasetID(ctx context.Context,...
    method UpdateKnowledgeBase (line 551) | func (r *KnowledgeBaseRepository) UpdateKnowledgeBase(ctx context.Cont...
    method GetKnowledgeBaseByID (line 600) | func (r *KnowledgeBaseRepository) GetKnowledgeBaseByID(ctx context.Con...
    method DeleteKnowledgeBase (line 608) | func (r *KnowledgeBaseRepository) DeleteKnowledgeBase(ctx context.Cont...
    method CreateKBRelease (line 633) | func (r *KnowledgeBaseRepository) CreateKBRelease(ctx context.Context,...
    method GetKBReleaseList (line 721) | func (r *KnowledgeBaseRepository) GetKBReleaseList(ctx context.Context...
    method GetLatestRelease (line 742) | func (r *KnowledgeBaseRepository) GetLatestRelease(ctx context.Context...
    method GetKBUserlist (line 753) | func (r *KnowledgeBaseRepository) GetKBUserlist(ctx context.Context, k...
    method CreateKBUser (line 785) | func (r *KnowledgeBaseRepository) CreateKBUser(ctx context.Context, kb...
    method UpdateKBUserPerm (line 790) | func (r *KnowledgeBaseRepository) UpdateKBUserPerm(ctx context.Context...
    method DeleteKBUser (line 797) | func (r *KnowledgeBaseRepository) DeleteKBUser(ctx context.Context, kb...
    method GetKBUser (line 803) | func (r *KnowledgeBaseRepository) GetKBUser(ctx context.Context, kbId,...
    method GetKBPermByUserId (line 814) | func (r *KnowledgeBaseRepository) GetKBPermByUserId(ctx context.Contex...
  function NewKnowledgeBaseRepository (line 36) | func NewKnowledgeBaseRepository(db *pg.DB, config *config.Config, logger...

FILE: backend/repo/pg/mcp.go
  type MCPRepository (line 10) | type MCPRepository struct
    method GetMCPCallCount (line 19) | func (r *MCPRepository) GetMCPCallCount(ctx context.Context) (int64, e...
  function NewMCPRepository (line 15) | func NewMCPRepository(db *pg.DB, logger *log.Logger) *MCPRepository {

FILE: backend/repo/pg/model.go
  type ModelRepository (line 14) | type ModelRepository struct
    method Create (line 23) | func (r *ModelRepository) Create(ctx context.Context, model *domain.Mo...
    method GetList (line 32) | func (r *ModelRepository) GetList(ctx context.Context) ([]*domain.Mode...
    method Update (line 43) | func (r *ModelRepository) Update(ctx context.Context, req *domain.Upda...
    method Updates (line 67) | func (r *ModelRepository) Updates(ctx context.Context, modelId string,...
    method Delete (line 74) | func (r *ModelRepository) Delete(ctx context.Context, id string) error {
    method GetChatModel (line 85) | func (r *ModelRepository) GetChatModel(ctx context.Context) (*domain.M...
    method GetModelByType (line 96) | func (r *ModelRepository) GetModelByType(ctx context.Context, modelTyp...
    method UpdateUsage (line 107) | func (r *ModelRepository) UpdateUsage(ctx context.Context, modelID str...
  function NewModelRepository (line 19) | func NewModelRepository(db *pg.DB, logger *log.Logger) *ModelRepository {

FILE: backend/repo/pg/nav.go
  type NavRepository (line 15) | type NavRepository struct
    method GetById (line 24) | func (r *NavRepository) GetById(ctx context.Context, id string) (*doma...
    method GetList (line 33) | func (r *NavRepository) GetList(ctx context.Context, kbId string) ([]v...
    method getMaxPosByKbId (line 46) | func (r *NavRepository) getMaxPosByKbId(tx *gorm.DB, kbId string) (flo...
    method Create (line 57) | func (r *NavRepository) Create(ctx context.Context, nav *domain.Nav, p...
    method reorderPositionsTx (line 83) | func (r *NavRepository) reorderPositionsTx(tx *gorm.DB, kbId string) e...
    method Move (line 102) | func (r *NavRepository) Move(ctx context.Context, kbId, id, prevID, ne...
    method Delete (line 152) | func (r *NavRepository) Delete(ctx context.Context, kbId, id string) e...
    method Update (line 158) | func (r *NavRepository) Update(ctx context.Context, kbId, id, name str...
    method GetReleaseList (line 165) | func (r *NavRepository) GetReleaseList(ctx context.Context, kbId strin...
  function NewNavRepository (line 20) | func NewNavRepository(db *pg.DB, logger *log.Logger) *NavRepository {

FILE: backend/repo/pg/node.go
  type NodeRepository (line 26) | type NodeRepository struct
    method Create (line 35) | func (r *NodeRepository) Create(ctx context.Context, req *domain.Creat...
    method GetList (line 129) | func (r *NodeRepository) GetList(ctx context.Context, req *domain.GetN...
    method GetLatestNodeReleaseByNodeIDs (line 150) | func (r *NodeRepository) GetLatestNodeReleaseByNodeIDs(ctx context.Con...
    method GetNodeReleasePublisherMap (line 164) | func (r *NodeRepository) GetNodeReleasePublisherMap(ctx context.Contex...
    method UpdateNodeContent (line 190) | func (r *NodeRepository) UpdateNodeContent(ctx context.Context, req *d...
    method GetByID (line 293) | func (r *NodeRepository) GetByID(ctx context.Context, id, kbId string)...
    method Delete (line 308) | func (r *NodeRepository) Delete(ctx context.Context, kbID string, ids ...
    method backupNodeReleasesTx (line 352) | func (r *NodeRepository) backupNodeReleasesTx(tx *gorm.DB, nodeIDs []s...
    method collectAllChildNodeIDs (line 387) | func (r *NodeRepository) collectAllChildNodeIDs(tx *gorm.DB, kbID stri...
    method GetNodeByID (line 413) | func (r *NodeRepository) GetNodeByID(ctx context.Context, id string) (...
    method GetNodesByIDs (line 425) | func (r *NodeRepository) GetNodesByIDs(ctx context.Context, ids []stri...
    method buildNodePath (line 444) | func (r *NodeRepository) buildNodePath(ctx context.Context, kbID strin...
    method GetNodeNameByNodeIDs (line 484) | func (r *NodeRepository) GetNodeNameByNodeIDs(ctx context.Context, ids...
    method GetNodeReleaseByID (line 502) | func (r *NodeRepository) GetNodeReleaseByID(ctx context.Context, id st...
    method GetLatestNodeReleaseByNodeID (line 513) | func (r *NodeRepository) GetLatestNodeReleaseByNodeID(ctx context.Cont...
    method GetLatestNodeReleaseWithPublishAccount (line 525) | func (r *NodeRepository) GetLatestNodeReleaseWithPublishAccount(ctx co...
    method GetNodeReleaseWithDirPathByID (line 540) | func (r *NodeRepository) GetNodeReleaseWithDirPathByID(ctx context.Con...
    method GetNodeReleasesByDocIDs (line 569) | func (r *NodeRepository) GetNodeReleasesByDocIDs(ctx context.Context, ...
    method GetNodeReleasesWithPathsByDocIDs (line 593) | func (r *NodeRepository) GetNodeReleasesWithPathsByDocIDs(ctx context....
    method getNodePathsBatch (line 649) | func (r *NodeRepository) getNodePathsBatch(ctx context.Context, docIDs...
    method GetRecommendNodeListByIDs (line 716) | func (r *NodeRepository) GetRecommendNodeListByIDs(ctx context.Context...
    method GetRecommendNodeListByParentIDs (line 732) | func (r *NodeRepository) GetRecommendNodeListByParentIDs(ctx context.C...
    method GetNodeReleaseListByKBID (line 757) | func (r *NodeRepository) GetNodeReleaseListByKBID(ctx context.Context,...
    method GetNodeReleaseDetailByKBIDAndID (line 787) | func (r *NodeRepository) GetNodeReleaseDetailByKBIDAndID(ctx context.C...
    method MoveNodeBetween (line 813) | func (r *NodeRepository) MoveNodeBetween(ctx context.Context, id, pare...
    method UpdateNodeDocID (line 864) | func (r *NodeRepository) UpdateNodeDocID(ctx context.Context, id, docI...
    method UpdateNodeReleaseDocID (line 875) | func (r *NodeRepository) UpdateNodeReleaseDocID(ctx context.Context, i...
    method UpdateNodeSummary (line 885) | func (r *NodeRepository) UpdateNodeSummary(ctx context.Context, kbID, ...
    method UpdateNodeStatus (line 894) | func (r *NodeRepository) UpdateNodeStatus(ctx context.Context, kbID, n...
    method TraverseNodesByCursor (line 904) | func (r *NodeRepository) TraverseNodesByCursor(ctx context.Context, ca...
    method CreateNodeReleases (line 933) | func (r *NodeRepository) CreateNodeReleases(ctx context.Context, kbID,...
    method GetOldNodeDocIDsByNodeID (line 980) | func (r *NodeRepository) GetOldNodeDocIDsByNodeID(ctx context.Context,...
    method MoveNodeNav (line 1007) | func (r *NodeRepository) MoveNodeNav(ctx context.Context, kbID, navID ...
    method BatchMove (line 1034) | func (r *NodeRepository) BatchMove(ctx context.Context, req *domain.Ba...
    method reorderPositionsByParentID (line 1057) | func (r *NodeRepository) reorderPositionsByParentID(tx *gorm.DB, kbID,...
    method reorderPositions (line 1080) | func (r *NodeRepository) reorderPositions(tx *gorm.DB, nodes []*domain...
    method GetNodeIDsByReleaseID (line 1123) | func (r *NodeRepository) GetNodeIDsByReleaseID(ctx context.Context, re...
    method UpdateNodeByKbID (line 1134) | func (r *NodeRepository) UpdateNodeByKbID(ctx context.Context, id, kbI...
    method UpdateNodesByKbID (line 1142) | func (r *NodeRepository) UpdateNodesByKbID(ctx context.Context, ids []...
    method UpdateNodeGroupByKbIDAndNodeIds (line 1170) | func (r *NodeRepository) UpdateNodeGroupByKbIDAndNodeIds(ctx context.C...
    method GetNodeGroupByNodeId (line 1218) | func (r *NodeRepository) GetNodeGroupByNodeId(ctx context.Context, nod...
    method Update (line 1231) | func (r *NodeRepository) Update(ctx context.Context, id string, m map[...
    method GetNodeIdByDocId (line 1235) | func (r *NodeRepository) GetNodeIdByDocId(ctx context.Context, docId s...
    method GetNodeIdsWithoutStatusByKbId (line 1248) | func (r *NodeRepository) GetNodeIdsWithoutStatusByKbId(ctx context.Con...
    method GetNodeIdsByDocIds (line 1264) | func (r *NodeRepository) GetNodeIdsByDocIds(ctx context.Context, docId...
    method DeleteOldNodeReleaseBackups (line 1292) | func (r *NodeRepository) DeleteOldNodeReleaseBackups(ctx context.Conte...
    method GetNodeCount (line 1298) | func (r *NodeRepository) GetNodeCount(ctx context.Context) (int, error) {
    method CountNodeByNavId (line 1309) | func (r *NodeRepository) CountNodeByNavId(ctx context.Context, kbId, n...
    method GetNodeIDsByNavId (line 1321) | func (r *NodeRepository) GetNodeIDsByNavId(ctx context.Context, kbId, ...
    method GetNodeListByStatus (line 1332) | func (r *NodeRepository) GetNodeListByStatus(ctx context.Context, kbId...
    method GetNodeStats (line 1361) | func (r *NodeRepository) GetNodeStats(ctx context.Context, kbId string...
  function NewNodeRepository (line 31) | func NewNodeRepository(db *pg.DB, logger *log.Logger) *NodeRepository {
  type NodeReleaseWithPath (line 585) | type NodeReleaseWithPath struct
  type NodePathInfo (line 641) | type NodePathInfo struct

FILE: backend/repo/pg/node_group.go
  method GetNodeGroupsByGroupIdsPerm (line 10) | func (r *NodeRepository) GetNodeGroupsByGroupIdsPerm(ctx context.Context...
  method GetNodeAuthGroupIdsByNodeId (line 22) | func (r *NodeRepository) GetNodeAuthGroupIdsByNodeId(ctx context.Context...

FILE: backend/repo/pg/node_stats.go
  method GetNodeStatsByNodeId (line 13) | func (r *NodeRepository) GetNodeStatsByNodeId(ctx context.Context, nodeI...

FILE: backend/repo/pg/prompt.go
  type PromptRepo (line 17) | type PromptRepo struct
    method GetPromptContent (line 29) | func (r *PromptRepo) GetPromptContent(ctx context.Context, kbID string...
    method GetSummaryPrompt (line 53) | func (r *PromptRepo) GetSummaryPrompt(ctx context.Context, kbID string...
    method buildPresetPrompt (line 74) | func (r *PromptRepo) buildPresetPrompt(prompt domain.Prompt) string {
  function NewPromptRepo (line 22) | func NewPromptRepo(db *pg.DB, logger *log.Logger) *PromptRepo {

FILE: backend/repo/pg/stat.go
  type StatRepository (line 16) | type StatRepository struct
    method CreateStatPage (line 28) | func (r *StatRepository) CreateStatPage(ctx context.Context, stat *dom...
    method GetHotPages (line 32) | func (r *StatRepository) GetHotPages(ctx context.Context, kbID string)...
    method GetHotPagesNoLimit (line 48) | func (r *StatRepository) GetHotPagesNoLimit(ctx context.Context, kbID ...
    method GetHotScene (line 62) | func (r *StatRepository) GetHotScene(ctx context.Context, kbID string)...
    method GetHotRefererHosts (line 76) | func (r *StatRepository) GetHotRefererHosts(ctx context.Context, kbID ...
    method GetHotBrowsers (line 90) | func (r *StatRepository) GetHotBrowsers(ctx context.Context, kbID stri...
    method GetStatPageCount (line 121) | func (r *StatRepository) GetStatPageCount(ctx context.Context, kbID st...
    method GetInstantCount (line 132) | func (r *StatRepository) GetInstantCount(ctx context.Context, kbID str...
    method GetInstantPages (line 145) | func (r *StatRepository) GetInstantPages(ctx context.Context, kbID str...
    method RemoveOldData (line 158) | func (r *StatRepository) RemoveOldData(ctx context.Context) error {
    method GetYesterdayPVByNode (line 168) | func (r *StatRepository) GetYesterdayPVByNode(ctx context.Context) (ma...
    method UpsertNodeStats (line 193) | func (r *StatRepository) UpsertNodeStats(ctx context.Context, nodeID s...
  function NewStatRepository (line 21) | func NewStatRepository(db *pg.DB, cahe *cache.Cache) *StatRepository {

FILE: backend/repo/pg/stat_hour.go
  method GetConversationCountOneHour (line 17) | func (r *StatRepository) GetConversationCountOneHour(ctx context.Context...
  method GetStatPageOneHour (line 29) | func (r *StatRepository) GetStatPageOneHour(ctx context.Context, kbID st...
  method GetGeCountOneHour (line 47) | func (r *StatRepository) GetGeCountOneHour(ctx context.Context, kbID str...
  method GetConversationDistributionOneHour (line 66) | func (r *StatRepository) GetConversationDistributionOneHour(ctx context....
  method GetHotRefererHostOneHour (line 90) | func (r *StatRepository) GetHotRefererHostOneHour(ctx context.Context, k...
  method GetHotRefererHostsByHour (line 114) | func (r *StatRepository) GetHotRefererHostsByHour(ctx context.Context, k...
  method CreateStatPageHour (line 162) | func (r *StatRepository) CreateStatPageHour(ctx context.Context, statPag...
  method CheckStatPageHourExists (line 167) | func (r *StatRepository) CheckStatPageHourExists(ctx context.Context, kb...
  method CleanupOldHourlyStats (line 179) | func (r *StatRepository) CleanupOldHourlyStats(ctx context.Context) error {
  method GetHotPagesOneHour (line 185) | func (r *StatRepository) GetHotPagesOneHour(ctx context.Context, kbID st...
  method GetHotPagesByHour (line 210) | func (r *StatRepository) GetHotPagesByHour(ctx context.Context, kbID str...
  method GetHotBrowsersOneHour (line 230) | func (r *StatRepository) GetHotBrowsersOneHour(ctx context.Context, kbID...
  method GetHotOSOneHour (line 253) | func (r *StatRepository) GetHotOSOneHour(ctx context.Context, kbID strin...
  method GetStatPageCountByHour (line 276) | func (r *StatRepository) GetStatPageCountByHour(ctx context.Context, kbI...
  method GetHotBrowsersByHour (line 288) | func (r *StatRepository) GetHotBrowsersByHour(ctx context.Context, kbID ...

FILE: backend/repo/pg/system_setting.go
  type SystemSettingRepo (line 12) | type SystemSettingRepo struct
    method GetSystemSetting (line 24) | func (r *SystemSettingRepo) GetSystemSetting(ctx context.Context, key ...
    method UpdateSystemSetting (line 34) | func (r *SystemSettingRepo) UpdateSystemSetting(ctx context.Context, k...
  function NewSystemSettingRepo (line 17) | func NewSystemSettingRepo(db *pg.DB, logger *log.Logger) *SystemSettingR...

FILE: backend/repo/pg/user.go
  type UserRepository (line 19) | type UserRepository struct
    method UpsertDefaultUser (line 31) | func (r *UserRepository) UpsertDefaultUser(ctx context.Context, user *...
    method CreateUser (line 56) | func (r *UserRepository) CreateUser(ctx context.Context, user *domain....
    method VerifyUser (line 78) | func (r *UserRepository) VerifyUser(ctx context.Context, account strin...
    method GetUser (line 90) | func (r *UserRepository) GetUser(ctx context.Context, userID string) (...
    method ListUsers (line 101) | func (r *UserRepository) ListUsers(ctx context.Context) ([]v1.UserList...
    method GetUsersAccountMap (line 113) | func (r *UserRepository) GetUsersAccountMap(ctx context.Context) (map[...
    method UpdateUserPassword (line 129) | func (r *UserRepository) UpdateUserPassword(ctx context.Context, userI...
    method DeleteUser (line 137) | func (r *UserRepository) DeleteUser(ctx context.Context, userID string...
  function NewUserRepository (line 24) | func NewUserRepository(db *pg.DB, logger *log.Logger) *UserRepository {

FILE: backend/repo/pg/user_access.go
  type UserAccessRepository (line 16) | type UserAccessRepository struct
    method UpdateAccessTime (line 34) | func (r *UserAccessRepository) UpdateAccessTime(userID string) {
    method GetAccessTime (line 39) | func (r *UserAccessRepository) GetAccessTime(userID string) (time.Time...
    method startSyncTask (line 47) | func (r *UserAccessRepository) startSyncTask() {
    method syncToDatabase (line 57) | func (r *UserAccessRepository) syncToDatabase() {
    method ValidateRole (line 106) | func (r *UserAccessRepository) ValidateRole(userID string, role consts...
    method ValidateKBPerm (line 123) | func (r *UserAccessRepository) ValidateKBPerm(kbId, userId string, per...
  function NewUserAccessRepository (line 22) | func NewUserAccessRepository(db *pg.DB, logger *log.Logger) *UserAccessR...

FILE: backend/repo/pg/wechat.go
  type WechatRepository (line 11) | type WechatRepository struct
    method GetWechatStatic (line 20) | func (r *WechatRepository) GetWechatStatic(ctx context.Context, kbID s...
    method GetWechatBaseURL (line 32) | func (r *WechatRepository) GetWechatBaseURL(ctx context.Context, kbID ...
  function NewWechatRepository (line 16) | func NewWechatRepository(db *pg.DB, logger *log.Logger) *WechatRepository {

FILE: backend/server/http/http.go
  type HTTPServer (line 25) | type HTTPServer struct
  type echoValidator (line 29) | type echoValidator struct
    method Validate (line 33) | func (v *echoValidator) Validate(i any) error {
  function NewEcho (line 40) | func NewEcho(
  type MyBinder (line 130) | type MyBinder struct
    method Bind (line 134) | func (b *MyBinder) Bind(i interface{}, c echo.Context) (err error) {

FILE: backend/setup/cert.go
  constant keyFile (line 16) | keyFile  = "/app/etc/nginx/ssl/panda-wiki.key"
  constant certFile (line 17) | certFile = "/app/etc/nginx/ssl/panda-wiki.crt"
  function CheckInitCert (line 21) | func CheckInitCert() error {
  function createSelfSignedCerts (line 42) | func createSelfSignedCerts() error {

FILE: backend/store/cache/redis.go
  type Cache (line 12) | type Cache struct
    method GetOrSet (line 30) | func (cache *Cache) GetOrSet(ctx context.Context, key string, value in...
    method DeleteKeysWithPrefix (line 46) | func (cache *Cache) DeleteKeysWithPrefix(ctx context.Context, prefix s...
    method AcquireLock (line 59) | func (cache *Cache) AcquireLock(ctx context.Context, key string) bool {
    method ReleaseLock (line 67) | func (cache *Cache) ReleaseLock(ctx context.Context, key string) bool {
  function NewCache (line 16) | func NewCache(config *config.Config) (*Cache, error) {

FILE: backend/store/ipdb/ipdb.go
  type IPDB (line 18) | type IPDB struct
    method Lookup (line 35) | func (a *IPDB) Lookup(ip string) (*domain.IPAddress, error) {
  function NewIPDB (line 23) | func NewIPDB(config *config.Config, logger *log.Logger) (*IPDB, error) {

FILE: backend/store/pg/migration/000001_init.up.sql
  type "public" (line 2) | CREATE TABLE
  type "public" (line 15) | CREATE INDEX "idx_apps_kb_id" ON "public"."apps" ("kb_id")
  type "public" (line 18) | CREATE TABLE
  type "public" (line 36) | CREATE INDEX "idx_conversation_messages_app_id" ON "public"."conversatio...
  type "public" (line 39) | CREATE INDEX "idx_conversation_messages_conversation_id" ON "public"."co...
  type "public" (line 42) | CREATE TABLE
  type "public" (line 53) | CREATE INDEX "idx_conversation_references_conversation_id" ON "public"."...
  type "public" (line 56) | CREATE TABLE
  type "public" (line 69) | CREATE INDEX "idx_conversations_kb_id" ON "public"."conversations" ("kb_...
  type "public" (line 72) | CREATE INDEX "idx_conversations_app_id" ON "public"."conversations" ("ap...
  type "public" (line 75) | CREATE TABLE
  type "public" (line 92) | CREATE INDEX "idx_nodes_kb_id" ON "public"."nodes" ("kb_id")
  type "public" (line 95) | CREATE INDEX "idx_nodes_doc_id" ON "public"."nodes" ("doc_id")
  type "public" (line 98) | CREATE INDEX "idx_nodes_parent_id" ON "public"."nodes" ("parent_id")
  type "public" (line 101) | CREATE TABLE
  type "public" (line 112) | CREATE TABLE
  type "public" (line 131) | CREATE TABLE
  type "public" (line 142) | CREATE UNIQUE INDEX "idx_users_account" ON "public"."users" ("account")

FILE: backend/store/pg/migration/000002_add_type_for_model.up.sql
  type idx_models_type (line 5) | create unique index idx_models_type on models (type)

FILE: backend/store/pg/migration/000005_app_kb_id_type_uniq.down.sql
  type "public" (line 5) | CREATE INDEX "idx_apps_kb_id" ON "public"."apps" ("kb_id")

FILE: backend/store/pg/migration/000005_app_kb_id_type_uniq.up.sql
  type "public" (line 2) | CREATE UNIQUE INDEX "idx_apps_kb_id_type" ON "public"."apps" ("kb_id", "...

FILE: backend/store/pg/migration/000006_node_version.up.sql
  type "public" (line 2) | CREATE TABLE
  type "public" (line 20) | CREATE INDEX "idx_node_releases_kb_id" ON "public"."node_releases" ("kb_...
  type "public" (line 21) | CREATE INDEX "idx_node_releases_node_id" ON "public"."node_releases" ("n...
  type "public" (line 22) | CREATE INDEX "idx_node_releases_doc_id" ON "public"."node_releases" ("do...
  type "public" (line 25) | CREATE TABLE
  type "public" (line 36) | CREATE INDEX "idx_kb_releases_kb_id" ON "public"."kb_releases" ("kb_id")
  type "public" (line 39) | CREATE TABLE
  type "public" (line 51) | CREATE INDEX "idx_kb_release_node_releases_kb_id" ON "public"."kb_releas...
  type "public" (line 52) | CREATE INDEX "idx_kb_release_node_releases_release_id_node_release_id" O...
  type "public" (line 53) | CREATE INDEX "idx_kb_release_node_releases_node_id" ON "public"."kb_rele...
  type "public" (line 64) | CREATE TABLE "public"."migrations" (
  type "public" (line 71) | CREATE UNIQUE INDEX "idx_migrations_name" ON "public"."migrations" ("name")

FILE: backend/store/pg/migration/000009_create_stat_pages.up.sql
  type stat_pages (line 2) | CREATE TABLE IF NOT EXISTS stat_pages (
  type idx_stat_pages_kb_id_node_id (line 18) | CREATE INDEX IF NOT EXISTS idx_stat_pages_kb_id_node_id ON stat_pages(kb...

FILE: backend/store/pg/migration/000011_create_user_comment.up.sql
  type "public" (line 1) | CREATE TABLE "public"."comments" (
  type "public" (line 14) | CREATE INDEX "idx_comments_node_id" ON "public"."comments" ("node_id")
  type "public" (line 15) | CREATE INDEX "idx_comments_kb_id" ON "public"."comments"("kb_id")

FILE: backend/store/pg/migration/000013_create_license.up.sql
  type licenses (line 2) | CREATE TABLE IF NOT EXISTS licenses (

FILE: backend/store/pg/migration/000015_create_auth.up.sql
  type auths (line 2) | CREATE TABLE IF NOT EXISTS auths (
  type auth_configs (line 14) | CREATE TABLE IF NOT EXISTS auth_configs (

FILE: backend/store/pg/migration/000016_create_document_feedback.up.sql
  type document_feedbacks (line 1) | CREATE TABLE IF NOT EXISTS document_feedbacks (

FILE: backend/store/pg/migration/000018_create_settings.up.sql
  type settings (line 2) | CREATE TABLE IF NOT EXISTS settings (
  type idx_settings_kb_id_key (line 13) | CREATE UNIQUE INDEX idx_settings_kb_id_key ON settings (kb_id, key)

FILE: backend/store/pg/migration/000020_add_user_role_and_kb_users.up.sql
  type "public" (line 8) | CREATE TABLE "public"."kb_users" (

FILE: backend/store/pg/migration/000021_create_auth_groups.up.sql
  type auth_groups (line 2) | CREATE TABLE IF NOT EXISTS auth_groups (
  type node_auth_groups (line 12) | CREATE TABLE IF NOT EXISTS node_auth_groups (

FILE: backend/store/pg/migration/000023_create_stat_page_hours.up.sql
  type stat_page_hours (line 1) | CREATE TABLE IF NOT EXISTS stat_page_hours (
  type idx_stat_page_hours_hour (line 19) | CREATE INDEX IF NOT EXISTS idx_stat_page_hours_hour ON stat_page_hours (...

FILE: backend/store/pg/migration/000025_create_api_tokens_table.up.sql
  type api_tokens (line 1) | CREATE TABLE IF NOT EXISTS api_tokens (

FILE: backend/store/pg/migration/000027_create_contributes_table.up.sql
  type contributes (line 1) | CREATE TABLE IF NOT EXISTS contributes (

FILE: backend/store/pg/migration/000032_create_system_settings.up.sql
  type system_settings (line 2) | CREATE TABLE IF NOT EXISTS system_settings (
  type idx_uniq_system_settings_key (line 11) | CREATE UNIQUE INDEX idx_uniq_system_settings_key ON system_settings(key)

FILE: backend/store/pg/migration/000033_create_mcp_calls.up.sql
  type mcp_calls (line 1) | CREATE TABLE IF NOT EXISTS mcp_calls (

FILE: backend/store/pg/migration/000034_create_node_stats.up.sql
  type node_stats (line 1) | CREATE TABLE IF NOT EXISTS node_stats (

FILE: backend/store/pg/migration/000037_create_nav_tabs.up.sql
  type navs (line 1) | CREATE TABLE IF NOT EXISTS navs (
  type nav_releases (line 12) | CREATE TABLE IF NOT EXISTS nav_releases (
  type idx_nav_releases_release_id (line 22) | CREATE INDEX IF NOT EXISTS idx_nav_releases_release_id ON nav_releases(r...
  type idx_nav_releases_kb_id (line 23) | CREATE INDEX IF NOT EXISTS idx_nav_releases_kb_id ON nav_releases(kb_id)

FILE: backend/store/pg/migration/000038_create_node_release_backups.up.sql
  type node_release_backup (line 1) | CREATE TABLE IF NOT EXISTS node_release_backup (
  type node_release_backup_deleted_at_idx (line 20) | CREATE INDEX IF NOT EXISTS node_release_backup_deleted_at_idx ON node_re...

FILE: backend/store/pg/pg.go
  type DB (line 20) | type DB struct
  function NewDB (line 24) | func NewDB(config *config.Config) (*DB, error) {
  function doMigrate (line 57) | func doMigrate(dsn string) error {

FILE: backend/store/rag/ct.go
  type CTRAG (line 19) | type CTRAG struct
    method CreateKnowledgeBase (line 40) | func (s *CTRAG) CreateKnowledgeBase(ctx context.Context) (string, erro...
    method QueryRecords (line 50) | func (s *CTRAG) QueryRecords(ctx context.Context, req *QueryRecordsReq...
    method UpsertRecords (line 97) | func (s *CTRAG) UpsertRecords(ctx context.Context, req *UpsertRecordsR...
    method DeleteRecords (line 128) | func (s *CTRAG) DeleteRecords(ctx context.Context, datasetID string, d...
    method DeleteKnowledgeBase (line 138) | func (s *CTRAG) DeleteKnowledgeBase(ctx context.Context, datasetID str...
    method AddModel (line 145) | func (s *CTRAG) AddModel(ctx context.Context, model *domain.Model) (st...
    method UpsertModel (line 171) | func (s *CTRAG) UpsertModel(ctx context.Context, model *domain.Model) ...
    method UpdateModel (line 199) | func (s *CTRAG) UpdateModel(ctx context.Context, model *domain.Model) ...
    method DeleteModel (line 226) | func (s *CTRAG) DeleteModel(ctx context.Context, model *domain.Model) ...
    method GetModelList (line 234) | func (s *CTRAG) GetModelList(ctx context.Context) ([]*domain.Model, er...
    method UpdateDocumentGroupIDs (line 252) | func (s *CTRAG) UpdateDocumentGroupIDs(ctx context.Context, datasetID ...
    method ListDocuments (line 268) | func (s *CTRAG) ListDocuments(ctx context.Context, datasetID string, d...
  function NewCTRAG (line 25) | func NewCTRAG(config *config.Config, logger *log.Logger) (*CTRAG, error) {

FILE: backend/store/rag/html2md.go
  function NewHTML2MDConverter (line 15) | func NewHTML2MDConverter() *converter.Converter {
  function renderAttachment (line 37) | func renderAttachment(ctx converter.Context, w converter.Writer, node *h...
  function renderTaskList (line 77) | func renderTaskList(ctx converter.Context, w converter.Writer, node *htm...
  function getTextFromTaskItem (line 114) | func getTextFromTaskItem(node *html.Node) string {
  function renderFlowchart (line 133) | func renderFlowchart(ctx converter.Context, w converter.Writer, node *ht...

FILE: backend/store/rag/rag.go
  type QueryRecordsRequest (line 15) | type QueryRecordsRequest struct
  type UpsertRecordsRequest (line 25) | type UpsertRecordsRequest struct
  type DocumentMetadata (line 35) | type DocumentMetadata struct
  type Document (line 39) | type Document struct
  type RAGService (line 49) | type RAGService interface
  function NewRAGService (line 65) | func NewRAGService(config *config.Config, logger *log.Logger) (RAGServic...

FILE: backend/store/s3/minio.go
  type MinioClient (line 15) | type MinioClient struct
    method SignURL (line 65) | func (c *MinioClient) SignURL(ctx context.Context, bucket, object stri...
  function NewMinioClient (line 20) | func NewMinioClient(config *config.Config) (*MinioClient, error) {

FILE: backend/telemetry/aes.go
  function Encrypt (line 10) | func Encrypt(key []byte, data []byte) (string, error) {

FILE: backend/telemetry/client.go
  constant machineIDFile (line 26) | machineIDFile  = "/data/.machine_id"
  constant reportInterval (line 27) | reportInterval = time.Hour
  type Client (line 31) | type Client struct
    method GetMachineID (line 90) | func (c *Client) GetMachineID() string {
    method getOrCreateMachineID (line 94) | func (c *Client) getOrCreateMachineID() (string, error) {
    method startPeriodicReport (line 159) | func (c *Client) startPeriodicReport() {
    method nextReportDataDelay (line 185) | func (c *Client) nextReportDataDelay() time.Duration {
    method reportInstallation (line 225) | func (c *Client) reportInstallation() error {
    method reportData (line 279) | func (c *Client) reportData() error {
    method isAdminLoggedInYesterday (line 376) | func (c *Client) isAdminLoggedInYesterday() (bool, error) {
    method Stop (line 394) | func (c *Client) Stop() {
  function NewClient (line 49) | func NewClient(logger *log.Logger, repo *pg.KnowledgeBaseRepository, mod...
  type InstallationEvent (line 399) | type InstallationEvent struct
  type DailyReportEvent (line 407) | type DailyReportEvent struct

FILE: backend/usecase/app.go
  type AppUsecase (line 24) | type AppUsecase struct
    method ValidateUpdateApp (line 94) | func (u *AppUsecase) ValidateUpdateApp(ctx context.Context, id string,...
    method UpdateApp (line 162) | func (u *AppUsecase) UpdateApp(ctx context.Context, id string, appRequ...
    method getQAFunc (line 190) | func (u *AppUsecase) getQAFunc(kbID string, appType domain.AppType) bo...
    method updateFeishuBot (line 257) | func (u *AppUsecase) updateFeishuBot(app *domain.App) {
    method updateLarkBot (line 297) | func (u *AppUsecase) updateLarkBot(app *domain.App) {
    method updateDingTalkBot (line 343) | func (u *AppUsecase) updateDingTalkBot(app *domain.App) {
    method updateDisCordBot (line 388) | func (u *AppUsecase) updateDisCordBot(app *domain.App) {
    method DeleteApp (line 424) | func (u *AppUsecase) DeleteApp(ctx context.Context, id, kbID string) e...
    method GetLarkBotClient (line 430) | func (u *AppUsecase) GetLarkBotClient(appID string) (*lark.LarkClient,...
    method GetAppDetailByKBIDAndAppType (line 437) | func (u *AppUsecase) GetAppDetailByKBIDAndAppType(ctx context.Context,...
    method GetMCPServerAppInfo (line 586) | func (u *AppUsecase) GetMCPServerAppInfo(ctx context.Context, kbID str...
    method ShareGetWebAppInfo (line 599) | func (u *AppUsecase) ShareGetWebAppInfo(ctx context.Context, kbID stri...
    method GetWidgetAppInfo (line 708) | func (u *AppUsecase) GetWidgetAppInfo(ctx context.Context, kbID string...
    method GetWechatAppInfo (line 746) | func (u *AppUsecase) GetWechatAppInfo(ctx context.Context, kbID string...
    method handleBotAuths (line 767) | func (u *AppUsecase) handleBotAuths(ctx context.Context, id string, ne...
    method handleBotAuth (line 860) | func (u *AppUsecase) handleBotAuth(ctx context.Context, kbID, appId st...
    method GetOpenAIAPIAppInfo (line 895) | func (u *AppUsecase) GetOpenAIAPIAppInfo(ctx context.Context, kbID str...
    method GetRecommendNodesByIds (line 909) | func (u *AppUsecase) GetRecommendNodesByIds(ctx context.Context, kbId ...
  function NewAppUsecase (line 44) | func NewAppUsecase(

FILE: backend/usecase/auth.go
  type AuthUsecase (line 25) | type AuthUsecase struct
    method GetAuthBySourceType (line 48) | func (u *AuthUsecase) GetAuthBySourceType(ctx context.Context, sourceT...
    method DeleteAuth (line 52) | func (u *AuthUsecase) DeleteAuth(ctx context.Context, req v1.AuthDelet...
    method SetAuth (line 56) | func (u *AuthUsecase) SetAuth(ctx context.Context, req v1.AuthSetReq) ...
    method GetAuthInfo (line 71) | func (u *AuthUsecase) GetAuthInfo(ctx context.Context, kbId string, au...
    method GetAuth (line 81) | func (u *AuthUsecase) GetAuth(ctx context.Context, kbID string, source...
    method ValidateRedirectUrl (line 119) | func (u *AuthUsecase) ValidateRedirectUrl(ctx context.Context, kbId, r...
    method genState (line 140) | func (u *AuthUsecase) genState(ctx context.Context, stateInfo StateInf...
    method SaveNewSession (line 155) | func (u *AuthUsecase) SaveNewSession(c echo.Context, auth *domain.Auth...
  function NewAuthUsecase (line 32) | func NewAuthUsecase(authRepo *pg.AuthRepo, logger *log.Logger, kbRepo *p...
  type StateInfo (line 42) | type StateInfo struct

FILE: backend/usecase/auth_github.go
  method getGitHubClient (line 14) | func (u *AuthUsecase) getGitHubClient(ctx context.Context, kbId, redirec...
  method GenerateGitHubAuthUrl (line 25) | func (u *AuthUsecase) GenerateGitHubAuthUrl(ctx context.Context, req sha...
  method GitHubCallback (line 43) | func (u *AuthUsecase) GitHubCallback(ctx context.Context, req shareV1.Gi...
  method getStateInfo (line 79) | func (u *AuthUsecase) getStateInfo(ctx context.Context, state string) (*...

FILE: backend/usecase/chat.go
  type ChatUsecase (line 23) | type ChatUsecase struct
    method initDFA (line 58) | func (u *ChatUsecase) initDFA() error {
    method Chat (line 79) | func (u *ChatUsecase) Chat(ctx context.Context, req *domain.ChatReques...
    method ChatRagOnly (line 309) | func (u *ChatUsecase) ChatRagOnly(ctx context.Context, req *domain.Cha...
    method CreateAcOnChunk (line 374) | func (u *ChatUsecase) CreateAcOnChunk(ctx context.Context, kbID string...
    method replaceWithSimpleString (line 431) | func (u *ChatUsecase) replaceWithSimpleString(content string, filter *...
    method Search (line 436) | func (u *ChatUsecase) Search(ctx context.Context, req *domain.ChatSear...
  function NewChatUsecase (line 36) | func NewChatUsecase(llmUsecase *LLMUsecase, kbRepo *pg.KnowledgeBaseRepo...

FILE: backend/usecase/comment.go
  type CommentUsecase (line 18) | type CommentUsecase struct
    method CreateComment (line 37) | func (u *CommentUsecase) CreateComment(ctx context.Context, commentReq...
    method GetCommentListByNodeID (line 75) | func (u *CommentUsecase) GetCommentListByNodeID(ctx context.Context, n...
    method GetCommentListByKbID (line 120) | func (u *CommentUsecase) GetCommentListByKbID(ctx context.Context, req...
    method DeleteCommentList (line 163) | func (u *CommentUsecase) DeleteCommentList(ctx context.Context, req *d...
  function NewCommentUsecase (line 26) | func NewCommentUsecase(commentRepo *pg.CommentRepository, logger *log.Lo...
  function maskIP (line 171) | func maskIP(ip string) string {

FILE: backend/usecase/conversation.go
  type ConversationUsecase (line 17) | type ConversationUsecase struct
    method CreateChatConversationMessage (line 44) | func (u *ConversationUsecase) CreateChatConversationMessage(ctx contex...
    method GetConversationList (line 49) | func (u *ConversationUsecase) GetConversationList(ctx context.Context,...
    method GetConversationDetail (line 107) | func (u *ConversationUsecase) GetConversationDetail(ctx context.Contex...
    method ValidateConversationNonce (line 168) | func (u *ConversationUsecase) ValidateConversationNonce(ctx context.Co...
    method CreateConversation (line 172) | func (u *ConversationUsecase) CreateConversation(ctx context.Context, ...
    method FeedBack (line 189) | func (u *ConversationUsecase) FeedBack(ctx context.Context, feedback *...
    method GetMessageList (line 209) | func (u *ConversationUsecase) GetMessageList(ctx context.Context, req ...
    method GetMessageDetail (line 254) | func (u *ConversationUsecase) GetMessageDetail(ctx context.Context, kb...
    method GetShareConversationDetail (line 262) | func (u *ConversationUsecase) GetShareConversationDetail(ctx context.C...
  function NewConversationUsecase (line 26) | func NewConversationUsecase(
  function extractReferencesBlock (line 134) | func extractReferencesBlock(conversationID, appID, text string) []*domai...

FILE: backend/usecase/crawler.go
  type CrawlerUsecase (line 21) | type CrawlerUsecase struct
    method ParseUrl (line 47) | func (u *CrawlerUsecase) ParseUrl(ctx context.Context, req *v1.Crawler...
    method ExportDoc (line 145) | func (u *CrawlerUsecase) ExportDoc(ctx context.Context, req *v1.Crawle...
    method ScrapeGetResult (line 166) | func (u *CrawlerUsecase) ScrapeGetResult(ctx context.Context, taskId s...
    method ScrapeGetResults (line 197) | func (u *CrawlerUsecase) ScrapeGetResults(ctx context.Context, taskIds...
  function NewCrawlerUsecase (line 28) | func NewCrawlerUsecase(logger *log.Logger, mqConsumer mq.MQConsumer, cac...

FILE: backend/usecase/creation.go
  type CreationUsecase (line 15) | type CreationUsecase struct
    method TextCreation (line 32) | func (u *CreationUsecase) TextCreation(ctx context.Context, req *domai...
    method TabComplete (line 84) | func (u *CreationUsecase) TabComplete(ctx context.Context, req *domain...
  function NewCreationUsecase (line 22) | func NewCreationUsecase(logger *log.Logger, llm *LLMUsecase, model *Mode...

FILE: backend/usecase/dingtalk_bot.go
  type DingTalkBotUsecase (line 7) | type DingTalkBotUsecase struct
  function NewDingTalkBotUsecase (line 12) | func NewDingTalkBotUsecase(logger *log.Logger, appUsecase *AppUsecase) *...

FILE: backend/usecase/file.go
  type FileUsecase (line 30) | type FileUsecase struct
    method UploadFileGetUrl (line 58) | func (u *FileUsecase) UploadFileGetUrl(ctx context.Context, kbID strin...
    method UploadFile (line 66) | func (u *FileUsecase) UploadFile(ctx context.Context, kbID string, fil...
    method UploadFileFromBytes (line 109) | func (u *FileUsecase) UploadFileFromBytes(ctx context.Context, kbID st...
    method UploadFileFromReader (line 150) | func (u *FileUsecase) UploadFileFromReader(
    method AnyDocUploadFile (line 194) | func (u *FileUsecase) AnyDocUploadFile(ctx context.Context, file *mult...
    method UploadFileByUrl (line 235) | func (u *FileUsecase) UploadFileByUrl(ctx context.Context, kbID string...
    method checkDeniedExtension (line 311) | func (u *FileUsecase) checkDeniedExtension(ctx context.Context, ext st...
  function NewFileUsecase (line 38) | func NewFileUsecase(logger *log.Logger, s3Client *s3.MinioClient, config...

FILE: backend/usecase/knowledge_base.go
  type KnowledgeBaseUsecase (line 21) | type KnowledgeBaseUsecase struct
    method CreateKnowledgeBase (line 48) | func (u *KnowledgeBaseUsecase) CreateKnowledgeBase(ctx context.Context...
    method GetKnowledgeBaseList (line 84) | func (u *KnowledgeBaseUsecase) GetKnowledgeBaseList(ctx context.Contex...
    method GetKnowledgeBaseListByUserId (line 92) | func (u *KnowledgeBaseUsecase) GetKnowledgeBaseListByUserId(ctx contex...
    method UpdateKnowledgeBase (line 100) | func (u *KnowledgeBaseUsecase) UpdateKnowledgeBase(ctx context.Context...
    method GetKnowledgeBase (line 119) | func (u *KnowledgeBaseUsecase) GetKnowledgeBase(ctx context.Context, k...
    method GetKnowledgeBasePerm (line 137) | func (u *KnowledgeBaseUsecase) GetKnowledgeBasePerm(ctx context.Contex...
    method DeleteKnowledgeBase (line 147) | func (u *KnowledgeBaseUsecase) DeleteKnowledgeBase(ctx context.Context...
    method CreateKBRelease (line 161) | func (u *KnowledgeBaseUsecase) CreateKBRelease(ctx context.Context, re...
    method GetKBReleaseList (line 199) | func (u *KnowledgeBaseUsecase) GetKBReleaseList(ctx context.Context, r...
    method GetKBUserList (line 208) | func (u *KnowledgeBaseUsecase) GetKBUserList(ctx context.Context, req ...
    method KBUserInvite (line 217) | func (u *KnowledgeBaseUsecase) KBUserInvite(ctx context.Context, req v...
    method UpdateUserKB (line 238) | func (u *KnowledgeBaseUsecase) UpdateUserKB(ctx context.Context, req v...
    method KBUserDelete (line 267) | func (u *KnowledgeBaseUsecase) KBUserDelete(ctx context.Context, req v...
  function NewKnowledgeBaseUsecase (line 33) | func NewKnowledgeBaseUsecase(repo *pg.KnowledgeBaseRepository, nodeRepo ...

FILE: backend/usecase/llm.go
  type LLMUsecase (line 28) | type LLMUsecase struct
    method BuildConversationMessageWithRAG (line 61) | func (u *LLMUsecase) BuildConversationMessageWithRAG(
    method ChatWithAgent (line 142) | func (u *LLMUsecase) ChatWithAgent(
    method Generate (line 196) | func (u *LLMUsecase) Generate(
    method SummaryNode (line 208) | func (u *LLMUsecase) SummaryNode(ctx context.Context, kbID string, mod...
    method trimThinking (line 259) | func (u *LLMUsecase) trimThinking(summary string) string {
    method requestSummary (line 270) | func (u *LLMUsecase) requestSummary(ctx context.Context, kbID string, ...
    method SplitByTokenLimit (line 292) | func (u *LLMUsecase) SplitByTokenLimit(text string, maxTokens int) ([]...
    method GetRankNodes (line 332) | func (u *LLMUsecase) GetRankNodes(ctx context.Context, req GetRankNode...
    method formatMessageWithImages (line 382) | func (u *LLMUsecase) formatMessageWithImages(message string, imagePath...
  constant summaryChunkTokenLimit (line 41) | summaryChunkTokenLimit = 30720
  constant summaryMaxChunks (line 42) | summaryMaxChunks       = 4
  function NewLLMUsecase (line 45) | func NewLLMUsecase(config *config.Config, rag rag.RAGService, conversati...
  type GetRankNodesRequest (line 323) | type GetRankNodesRequest struct

FILE: backend/usecase/model.go
  type ModelUsecase (line 22) | type ModelUsecase struct
    method Create (line 50) | func (u *ModelUsecase) Create(ctx context.Context, model *domain.Model...
    method GetList (line 67) | func (u *ModelUsecase) GetList(ctx context.Context) ([]*domain.ModelLi...
    method TriggerUpsertRecords (line 72) | func (u *ModelUsecase) TriggerUpsertRecords(ctx context.Context) error {
    method Update (line 111) | func (u *ModelUsecase) Update(ctx context.Context, req *domain.UpdateM...
    method GetChatModel (line 146) | func (u *ModelUsecase) GetChatModel(ctx context.Context) (*domain.Mode...
    method GetModelByType (line 176) | func (u *ModelUsecase) GetModelByType(ctx context.Context, modelType d...
    method UpdateUsage (line 180) | func (u *ModelUsecase) UpdateUsage(ctx context.Context, modelID string...
    method SwitchMode (line 184) | func (u *ModelUsecase) SwitchMode(ctx context.Context, req *domain.Swi...
    method updateModeSettingConfig (line 257) | func (u *ModelUsecase) updateModeSettingConfig(ctx context.Context, mo...
    method GetModelModeSetting (line 293) | func (u *ModelUsecase) GetModelModeSetting(ctx context.Context) (domai...
    method updateRAGModelsByMode (line 310) | func (u *ModelUsecase) updateRAGModelsByMode(ctx context.Context, mode...
  function NewModelUsecase (line 34) | func NewModelUsecase(modelRepo *pg.ModelRepository, nodeRepo *pg.NodeRep...

FILE: backend/usecase/nav.go
  type NavUsecase (line 16) | type NavUsecase struct
    method GetList (line 37) | func (u *NavUsecase) GetList(ctx context.Context, kbID string) ([]v1.N...
    method GetReleaseList (line 45) | func (u *NavUsecase) GetReleaseList(ctx context.Context, kbID string) ...
    method Add (line 53) | func (u *NavUsecase) Add(ctx context.Context, req *v1.NavAddReq) error {
    method Move (line 67) | func (u *NavUsecase) Move(ctx context.Context, req *v1.NavMoveReq) err...
    method Delete (line 71) | func (u *NavUsecase) Delete(ctx context.Context, req *v1.NavDeleteReq)...
    method Update (line 98) | func (u *NavUsecase) Update(ctx context.Context, req *v1.NavUpdateReq)...
  function NewNavUsecase (line 23) | func NewNavUsecase(

FILE: backend/usecase/node.go
  type NodeUsecase (line 29) | type NodeUsecase struct
    method Create (line 79) | func (u *NodeUsecase) Create(ctx context.Context, req *domain.CreateNo...
    method GetList (line 87) | func (u *NodeUsecase) GetList(ctx context.Context, req *domain.GetNode...
    method GetNodeByKBID (line 110) | func (u *NodeUsecase) GetNodeByKBID(ctx context.Context, id, kbId, for...
    method NodeAction (line 142) | func (u *NodeUsecase) NodeAction(ctx context.Context, req *domain.Node...
    method Update (line 164) | func (u *NodeUsecase) Update(ctx context.Context, req *domain.UpdateNo...
    method ValidateNodePerm (line 178) | func (u *NodeUsecase) ValidateNodePerm(ctx context.Context, kbID, node...
    method GetNodeReleaseDetailByKBIDAndID (line 219) | func (u *NodeUsecase) GetNodeReleaseDetailByKBIDAndID(ctx context.Cont...
    method MoveNode (line 266) | func (u *NodeUsecase) MoveNode(ctx context.Context, req *domain.MoveNo...
    method SummaryNode (line 270) | func (u *NodeUsecase) SummaryNode(ctx context.Context, req *domain.Nod...
    method GetRecommendNodeList (line 305) | func (u *NodeUsecase) GetRecommendNodeList(ctx context.Context, req *d...
    method BatchMoveNode (line 351) | func (u *NodeUsecase) BatchMoveNode(ctx context.Context, req *domain.B...
    method MoveNodeNav (line 355) | func (u *NodeUsecase) MoveNodeNav(ctx context.Context, req *v1.NodeMov...
    method convertMDToHTML (line 369) | func (u *NodeUsecase) convertMDToHTML(mdStr string) string {
    method GetShareNodeList (line 384) | func (u *NodeUsecase) GetShareNodeList(ctx context.Context, kbId strin...
    method GetNodeReleaseListByParentID (line 437) | func (u *NodeUsecase) GetNodeReleaseListByParentID(ctx context.Context...
    method buildNodeTree (line 475) | func (u *NodeUsecase) buildNodeTree(parentID string, childrenMap map[s...
    method GetNodeIdsByAuthId (line 506) | func (u *NodeUsecase) GetNodeIdsByAuthId(ctx context.Context, authId u...
    method GetNodePermissionsByID (line 530) | func (u *NodeUsecase) GetNodePermissionsByID(ctx context.Context, id, ...
    method ValidateNodePermissionsEdit (line 562) | func (u *NodeUsecase) ValidateNodePermissionsEdit(req v1.NodePermissio...
    method NodePermissionsEdit (line 574) | func (u *NodeUsecase) NodePermissionsEdit(ctx context.Context, req v1....
    method SyncRagNodeStatus (line 642) | func (u *NodeUsecase) SyncRagNodeStatus(ctx context.Context) error {
    method NodeRestudy (line 731) | func (u *NodeUsecase) NodeRestudy(ctx context.Context, req *v1.NodeRes...
    method GetNodeStats (line 763) | func (u *NodeUsecase) GetNodeStats(ctx context.Context, kbId string) (...
    method GetNodeListGroupByNav (line 793) | func (u *NodeUsecase) GetNodeListGroupByNav(ctx context.Context, kbId,...
  function NewNodeUsecase (line 45) | func NewNodeUsecase(
  constant ragSyncChunkSize (line 77) | ragSyncChunkSize = 100

FILE: backend/usecase/sitemap.go
  type SitemapUsecase (line 14) | type SitemapUsecase struct
    method GetSitemap (line 24) | func (u *SitemapUsecase) GetSitemap(ctx context.Context, kbID string) ...
  function NewSitemapUsecase (line 20) | func NewSitemapUsecase(nodeUsecase *pg.NodeRepository, appUsecase *pg.Kn...

FILE: backend/usecase/stat.go
  type StatUseCase (line 23) | type StatUseCase struct
    method RecordPage (line 49) | func (u *StatUseCase) RecordPage(ctx context.Context, stat *domain.Sta...
    method ValidateStatDay (line 66) | func (u *StatUseCase) ValidateStatDay(statDay consts.StatDay, edition ...
    method GetHotPages (line 86) | func (u *StatUseCase) GetHotPages(ctx context.Context, kbID string, da...
    method GetHotRefererHosts (line 158) | func (u *StatUseCase) GetHotRefererHosts(ctx context.Context, kbID str...
    method GetHotBrowsers (line 193) | func (u *StatUseCase) GetHotBrowsers(ctx context.Context, kbID string,...
    method GetStatCount (line 212) | func (u *StatUseCase) GetStatCount(ctx context.Context, kbID string, d...
    method GetInstantCount (line 238) | func (u *StatUseCase) GetInstantCount(ctx context.Context, kbID string...
    method GetInstantPages (line 246) | func (u *StatUseCase) GetInstantPages(ctx context.Context, kbID string...
    method GetGeoCount (line 309) | func (u *StatUseCase) GetGeoCount(ctx context.Context, kbID string, da...
    method GetConversationDistribution (line 328) | func (u *StatUseCase) GetConversationDistribution(ctx context.Context,...
    method AggregateHourlyStats (line 382) | func (u *StatUseCase) AggregateHourlyStats(ctx context.Context) error {
    method CleanupOldHourlyStats (line 461) | func (u *StatUseCase) CleanupOldHourlyStats(ctx context.Context) error {
    method MigrateYesterdayPVToNodeStats (line 466) | func (u *StatUseCase) MigrateYesterdayPVToNodeStats(ctx context.Contex...
  function NewStatUseCase (line 35) | func NewStatUseCase(repo *pg.StatRepository, nodeRepo *pg.NodeRepository...

FILE: backend/usecase/user.go
  type UserUsecase (line 19) | type UserUsecase struct
    method CreateUser (line 43) | func (u *UserUsecase) CreateUser(ctx context.Context, user *domain.Use...
    method VerifyUserAndGenerateToken (line 47) | func (u *UserUsecase) VerifyUserAndGenerateToken(ctx context.Context, ...
    method GetUser (line 62) | func (u *UserUsecase) GetUser(ctx context.Context, userID string) (*do...
    method ListUsers (line 66) | func (u *UserUsecase) ListUsers(ctx context.Context) (*v1.UserListResp...
    method ResetPassword (line 75) | func (u *UserUsecase) ResetPassword(ctx context.Context, req *v1.Reset...
    method DeleteUser (line 79) | func (u *UserUsecase) DeleteUser(ctx context.Context, userID string) e...
  function NewUserUsecase (line 25) | func NewUserUsecase(repo *pg.UserRepository, logger *log.Logger, config ...

FILE: backend/usecase/wechat_app.go
  type WechatAppUsecase (line 13) | type WechatAppUsecase struct
    method VerifyUrlWechatAPP (line 33) | func (u *WechatAppUsecase) VerifyUrlWechatAPP(ctx context.Context, sig...
    method Wechat (line 42) | func (u *WechatAppUsecase) Wechat(ctx context.Context, msg *wechat.Rec...
    method NewWechatConfig (line 66) | func (u *WechatAppUsecase) NewWechatConfig(ctx context.Context, appInf...
    method getQAFunc (line 79) | func (u *WechatAppUsecase) getQAFunc(kbID string, appType domain.AppTy...
  function NewWechatAppUsecase (line 22) | func NewWechatAppUsecase(logger *log.Logger, AppUsecase *AppUsecase, cha...

FILE: backend/usecase/wechat_official_account.go
  method GetWechatOfficialAccountResponse (line 15) | func (u *AppUsecase) GetWechatOfficialAccountResponse(ctx context.Contex...
  method SendCustomerServiceMessage (line 38) | func (u *AppUsecase) SendCustomerServiceMessage(oa *officialaccount.Offi...

FILE: backend/usecase/wechat_service.go
  type WechatServiceUsecase (line 13) | type WechatServiceUsecase struct
    method VerifyUrlWechatService (line 31) | func (u *WechatServiceUsecase) VerifyUrlWechatService(ctx context.Cont...
    method WechatService (line 41) | func (u *WechatServiceUsecase) WechatService(ctx context.Context, msg ...
    method NewWechatServiceConfig (line 53) | func (u *WechatServiceUsecase) NewWechatServiceConfig(ctx context.Cont...
    method getQAFunc (line 68) | func (u *WechatServiceUsecase) getQAFunc(kbID string, appType domain.A...
  function NewWechatUsecase (line 21) | func NewWechatUsecase(logger *log.Logger, AppUsecase *AppUsecase, chatUs...

FILE: backend/usecase/wecom.go
  type WecomUsecase (line 18) | type WecomUsecase struct
    method createAIBotClient (line 36) | func (u *WecomUsecase) createAIBotClient(ctx context.Context, appInfo ...
    method VerifyUrlService (line 45) | func (u *WecomUsecase) VerifyUrlService(ctx context.Context, signature...
    method HandleMsg (line 71) | func (u *WecomUsecase) HandleMsg(ctx context.Context, kbID, signature,...
    method SendQuestionToAI (line 213) | func (u *WecomUsecase) SendQuestionToAI(conversationID string, eventCh...
  function NewWecomUsecase (line 26) | func NewWecomUsecase(logger *log.Logger, cache *cache.Cache, AppUsecase ...

FILE: backend/utils/DFA.go
  type DFAInstance (line 13) | type DFAInstance struct
  function GetDFA (line 19) | func GetDFA(kbID string) *DFAInstance {
  function InitDFA (line 26) | func InitDFA(kbID string, words []string) {
  type TrieNode (line 49) | type TrieNode struct
  function NewTrieNode (line 55) | func NewTrieNode() *TrieNode {
  type DFA (line 63) | type DFA struct
    method AddWord (line 68) | func (d *DFA) AddWord(word string) {
    method UpdateOldWord (line 80) | func (d *DFA) UpdateOldWord(oldWord, newWord string) {
    method DeleteWord (line 86) | func (d *DFA) DeleteWord(word string) bool {
    method DeleteWordBatch (line 124) | func (d *DFA) DeleteWordBatch(words []string) {
    method Filter (line 137) | func (d *DFA) Filter(text string) string {
    method Check (line 160) | func (d *DFA) Check(text string) error {

FILE: backend/utils/epub.go
  type EpubConverter (line 27) | type EpubConverter struct
    method Convert (line 49) | func (e *EpubConverter) Convert(ctx context.Context, kbID string, data...
    method uploadFile (line 158) | func (e *EpubConverter) uploadFile(ctx context.Context, kbID string, z...
    method processFile (line 194) | func (e *EpubConverter) processFile(ctx context.Context, f *zip.File, ...
    method exchangeUrl (line 226) | func (e *EpubConverter) exchangeUrl(ctx context.Context, content strin...
  function NewEpubConverter (line 39) | func NewEpubConverter(logger *log.Logger, minio *s3.MinioClient) *EpubCo...
  function clearFileName (line 153) | func clearFileName(str string) string {
  function isSkippableFile (line 221) | func isSkippableFile(name string) bool {
  function getFullPath (line 259) | func getFullPath(zipReader *zip.Reader) (string, error) {
  function valid (line 298) | func valid(zipReader *zip.Reader) error {
  type Package (line 319) | type Package struct
  type Spine (line 332) | type Spine struct
  type ItemRef (line 338) | type ItemRef struct
  type Guide (line 343) | type Guide struct
  type Reference (line 348) | type Reference struct
  type Item (line 355) | type Item struct
  function getOpf (line 361) | func getOpf(zipReader *zip.Reader) (*Package, error) {
  type NCX (line 387) | type NCX struct
  type NavMap (line 392) | type NavMap struct
  type NavPoint (line 396) | type NavPoint struct
  type NavLabel (line 403) | type NavLabel struct
  type Content (line 407) | type Content struct
  function ParseNCX (line 412) | func ParseNCX(r io.Reader) ([]map[string]string, error) {

FILE: backend/utils/feed.go
  type FeedItem (line 17) | type FeedItem struct
  type Feed (line 25) | type Feed struct
  function cleanXMLContent (line 33) | func cleanXMLContent(content string) string {
  function ParseFeed (line 50) | func ParseFeed(url string) (*Feed, error) {
  function parseRSS (line 79) | func parseRSS(content []byte) (*Feed, error) {
  function parseAtom (line 151) | func parseAtom(content []byte) (*Feed, error) {
  function parseJSONFeed (line 203) | func parseJSONFeed(content []byte) (*Feed, error) {

FILE: backend/utils/file.go
  function IsImageFile (line 9) | func IsImageFile(filename string) bool {

FILE: backend/utils/ip_addr.go
  function GetClientIPFromRemoteAddr (line 21) | func GetClientIPFromRemoteAddr(c echo.Context) string {
  function ExtractHostFromRemoteAddr (line 25) | func ExtractHostFromRemoteAddr(r *http.Request) string {
  function IsPrivateOrReservedIP (line 38) | func IsPrivateOrReservedIP(ipStr string) bool {
  function isDocumentationIP (line 84) | func isDocumentationIP(ip net.IP) bool {
  function isOtherReservedIP (line 102) | func isOtherReservedIP(ip net.IP) bool {
  function IsIPv6 (line 140) | func IsIPv6(ipStr string) bool {
  function ValidateURLForSSRF (line 151) | func ValidateURLForSSRF(urlStr string) error {

FILE: backend/utils/processor.go
  type Node (line 10) | type Node struct
  function newNode (line 15) | func newNode() *Node {
  type ProcessorTree (line 19) | type ProcessorTree struct
    method GetNode (line 34) | func (t *ProcessorTree) GetNode(farther *Node) (*Node, error) {
    method Add (line 45) | func (t *ProcessorTree) Add(node *Node, data []byte) error {
    method GetResult (line 55) | func (t *ProcessorTree) GetResult() ([]byte, error) {
    method getRes (line 62) | func (t *ProcessorTree) getRes(node *Node) error {
  function NewProcessorTree (line 25) | func NewProcessorTree() *ProcessorTree {

FILE: backend/utils/time.go
  function GetTimeHourOffset (line 5) | func GetTimeHourOffset(hours int64) time.Time {

FILE: backend/utils/utils.go
  function HTTPGet (line 35) | func HTTPGet(url string) ([]byte, error) {
  function DecodeBytes (line 59) | func DecodeBytes(data []byte) string {
  function IsURLValid (line 71) | func IsURLValid(urlStr string) bool {
  function URLNormalize (line 80) | func URLNormalize(urlStr string) string {
  function URLRemovePath (line 102) | func URLRemovePath(rawURL string) (string, error) {
  function decode (line 117) | func decode(data []byte, encoding string) (string, error) {
  function GetHeaderMap (line 124) | func GetHeaderMap(header string) map[string]string {
  function UrlEncode (line 134) | func UrlEncode(s string) string {
  function RemoveFirstDir (line 148) | func RemoveFirstDir(path string) string {
  function RemoveURLParams (line 160) | func RemoveURLParams(rawURL string) (string, error) {
  function UploadImage (line 174) | func UploadImage(ctx context.Context, minioClient *s3.MinioClient, image...
  function GetTitleFromMarkdown (line 248) | func GetTitleFromMarkdown(markdown string) string {
  function ExchangeMarkDownImageUrl (line 257) | func ExchangeMarkDownImageUrl(
  type Localloader (line 345) | type Localloader struct
    method LoadTiktokenBpe (line 347) | func (m *Localloader) LoadTiktokenBpe(_ string) (map[string]int, error) {
  function GetFileNameWithoutExt (line 353) | func GetFileNameWithoutExt(path string) string {
  function IsUUID (line 358) | func IsUUID(s string) bool {
  function IsLikelyHTML (line 363) | func IsLikelyHTML(text string) bool {

FILE: sdk/rag/chunk.go
  method AddChunk (line 9) | func (c *Client) AddChunk(ctx context.Context, datasetID, documentID str...
  method ListChunks (line 23) | func (c *Client) ListChunks(ctx context.Context, datasetID, documentID s...
  method DeleteChunks (line 42) | func (c *Client) DeleteChunks(ctx context.Context, datasetID, documentID...
  method UpdateChunk (line 54) | func (c *Client) UpdateChunk(ctx context.Context, datasetID, documentID,...
  method ParseDocuments (line 65) | func (c *Client) ParseDocuments(ctx context.Context, datasetID string, d...
  method StopParseDocuments (line 77) | func (c *Client) StopParseDocuments(ctx context.Context, datasetID strin...

FILE: sdk/rag/client.go
  constant defaultBaseURL (line 16) | defaultBaseURL = "http://localhost:8080/api/v1"
  constant defaultTimeout (line 17) | defaultTimeout = 30 * time.Second
  type Client (line 21) | type Client struct
    method newRequest (line 51) | func (c *Client) newRequest(ctx context.Context, method, path string, ...
    method do (line 74) | func (c *Client) do(req *http.Request, v interface{}) error {
  type ClientOption (line 27) | type ClientOption
  function New (line 30) | func New(apiBase string, apiKey string, opts ...ClientOption) *Client {
  function WithHTTPClient (line 44) | func WithHTTPClient(httpClient *http.Client) ClientOption {
  function parseErrorResponse (line 102) | func parseErrorResponse(resp *http.Response) error {

FILE: sdk/rag/dataset.go
  method CreateDataset (line 9) | func (c *Client) CreateDataset(ctx context.Context, req CreateDatasetReq...
  method DeleteDatasets (line 22) | func (c *Client) DeleteDatasets(ctx context.Context, ids []string) error {
  method UpdateDataset (line 33) | func (c *Client) UpdateDataset(ctx context.Context, datasetID string, re...
  method ListDatasets (line 44) | func (c *Client) ListDatasets(ctx context.Context, req ListDatasetsReque...

FILE: sdk/rag/document.go
  method UploadDocumentsAndParse (line 17) | func (c *Client) UploadDocumentsAndParse(ctx context.Context, datasetID ...
  method UploadDocuments (line 40) | func (c *Client) UploadDocuments(ctx context.Context, datasetID string, ...
  method DownloadDocument (line 107) | func (c *Client) DownloadDocument(ctx context.Context, datasetID, docume...
  method ListDocuments (line 135) | func (c *Client) ListDocuments(ctx context.Context, datasetID string, pa...
  method DeleteDocuments (line 155) | func (c *Client) DeleteDocuments(ctx context.Context, datasetID string, ...
  method UpdateDocument (line 167) | func (c *Client) UpdateDocument(ctx context.Context, datasetID, document...
  method UpdateDocumentGroupIDs (line 178) | func (c *Client) UpdateDocumentGroupIDs(ctx context.Context, datasetID, ...
  method UpdateDocumentsGroupIDsBatch (line 193) | func (c *Client) UpdateDocumentsGroupIDsBatch(ctx context.Context, datas...
  method UploadDocumentText (line 211) | func (c *Client) UploadDocumentText(ctx context.Context, datasetID strin...
  method UploadDocumentTextAndParse (line 346) | func (c *Client) UploadDocumentTextAndParse(ctx context.Context, dataset...
  method UpdateDocumentText (line 370) | func (c *Client) UpdateDocumentText(ctx context.Context, datasetID strin...

FILE: sdk/rag/model_config.go
  method AddModelConfig (line 8) | func (c *Client) AddModelConfig(ctx context.Context, req AddModelConfigR...
  method GetModelConfigList (line 20) | func (c *Client) GetModelConfigList(ctx context.Context) ([]ModelConfig,...
  method DeleteModelConfig (line 32) | func (c *Client) DeleteModelConfig(ctx context.Context, models []ModelIt...

FILE: sdk/rag/models.go
  type CommonResponse (line 5) | type CommonResponse struct
  type Chunk (line 11) | type Chunk struct
  type AddChunkRequest (line 25) | type AddChunkRequest struct
  type AddChunkResponse (line 31) | type AddChunkResponse struct
  type ListChunksResponse (line 39) | type ListChunksResponse struct
  type DeleteChunksRequest (line 48) | type DeleteChunksRequest struct
  type DeleteChunksResponse (line 52) | type DeleteChunksResponse struct
  type UpdateChunkRequest (line 57) | type UpdateChunkRequest struct
  type UpdateChunkResponse (line 63) | type UpdateChunkResponse struct
  type ParseDocumentsRequest (line 70) | type ParseDocumentsRequest struct
  type ParseDocumentsResponse (line 74) | type ParseDocumentsResponse struct
  type StopParseDocumentsRequest (line 81) | type StopParseDocumentsRequest struct
  type StopParseDocumentsResponse (line 85) | type StopParseDocumentsResponse struct
  type Dataset (line 91) | type Dataset struct
  type RaptorConfig (line 119) | type RaptorConfig struct
  type GraphragConfig (line 131) | type GraphragConfig struct
  type ParserConfig (line 140) | type ParserConfig struct
  type CreateDatasetRequest (line 157) | type CreateDatasetRequest struct
  type CreateDatasetResponse (line 168) | type CreateDatasetResponse struct
  type UpdateDatasetRequest (line 174) | type UpdateDatasetRequest struct
  type UpdateDatasetResponse (line 185) | type UpdateDatasetResponse struct
  type ListDatasetsRequest (line 190) | type ListDatasetsRequest struct
  type ListDatasetsResponse (line 199) | type ListDatasetsResponse struct
  type DeleteDatasetsRequest (line 205) | type DeleteDatasetsRequest struct
  type DeleteDatasetsResponse (line 209) | type DeleteDatasetsResponse struct
  type Document (line 214) | type Document struct
  type UploadDocumentResponse (line 242) | type UploadDocumentResponse struct
  type ListDocumentsResponse (line 248) | type ListDocumentsResponse struct
  type DeleteDocumentsRequest (line 257) | type DeleteDocumentsRequest struct
  type DeleteDocumentsResponse (line 261) | type DeleteDocumentsResponse struct
  type UpdateDocumentRequest (line 266) | type UpdateDocumentRequest struct
  type UpdateDocumentResponse (line 273) | type UpdateDocumentResponse struct
  type DocumentMetadata (line 278) | type DocumentMetadata struct
  type ChatMessage (line 286) | type ChatMessage struct
  type RetrievalRequest (line 292) | type RetrievalRequest struct
  type RetrievalChunk (line 309) | type RetrievalChunk struct
  type RetrievalResponse (line 326) | type RetrievalResponse struct
  type RelatedQuestionsRequest (line 336) | type RelatedQuestionsRequest struct
  type RelatedQuestionsResponse (line 341) | type RelatedQuestionsResponse struct
  type ModelConfig (line 348) | type ModelConfig struct
  type AddModelConfigRequest (line 368) | type AddModelConfigRequest struct
  type AddModelConfigResponse (line 387) | type AddModelConfigResponse struct
  type ListModelConfigsResponse (line 392) | type ListModelConfigsResponse struct
  type ModelItem (line 397) | type ModelItem struct
  type DeleteModelConfigsRequest (line 402) | type DeleteModelConfigsRequest struct

FILE: sdk/rag/retrieval.go
  method RetrieveChunks (line 8) | func (c *Client) RetrieveChunks(ctx context.Context, req RetrievalReques...
  method RelatedQuestions (line 22) | func (c *Client) RelatedQuestions(ctx context.Context, loginToken string...

FILE: web/admin/scripts/generate-routes.js
  function sortRoutesBySpecificity (line 15) | function sortRoutesBySpecificity(routes) {
  function buildFullPath (line 60) | function buildFullPath(path, parentPath) {
  function normalizePath (line 77) | function normalizePath(path) {
  function parseRouteObject (line 85) | function parseRouteObject(objContent, parentPath = '') {
  function parseRoutes (line 166) | function parseRoutes(content) {
  function updateIndexHtml (line 199) | function updateIndexHtml() {

FILE: web/admin/src/App.tsx
  function App (line 14) | function App() {

FILE: web/admin/src/api/request.ts
  type BasicResponse (line 9) | type BasicResponse<T> = {
  type ErrorResponse (line 15) | type ErrorResponse = {
  type Response (line 21) | type Response<T> = BasicResponse<T> | ErrorResponse;

FILE: web/admin/src/api/type.ts
  type Paging (line 7) | type Paging = {
  type ResposeList (line 12) | type ResposeList<T> = {
  type BaseItem (line 17) | interface BaseItem {
  type TrendData (line 21) | type TrendData = { count: number; name: string; color?: string };
  type UserForm (line 24) | type UserForm = {
  type UserInfo (line 29) | type UserInfo = {
  type UpdateUserInfo (line 36) | type UpdateUserInfo = {
  type UpdateKnowledgeBaseData (line 42) | type UpdateKnowledgeBaseData = {
  type KnowledgeBaseFormData (line 57) | interface KnowledgeBaseFormData {
  type KnowledgeBaseAccessSettings (line 68) | type KnowledgeBaseAccessSettings = {
  type KnowledgeBaseStats (line 79) | type KnowledgeBaseStats = {
  type KnowledgeBaseListItem (line 85) | type KnowledgeBaseListItem = Pick<
  type CardWebHeaderBtn (line 95) | interface CardWebHeaderBtn {
  type ReleaseListItem (line 105) | type ReleaseListItem = {
  type AuthSetting (line 113) | type AuthSetting = {
  type NodeListItem (line 119) | type NodeListItem = {
  type GetNodeRecommendData (line 132) | type GetNodeRecommendData = {
  type CreateNodeSummaryData (line 137) | type CreateNodeSummaryData = {
  type NodeDetail (line 142) | type NodeDetail = {
  type CreateNodeData (line 158) | type CreateNodeData = {
  type NodeListFilterData (line 167) | type NodeListFilterData = {
  type NodeAction (line 172) | type NodeAction = 'delete' | 'public' | 'private';
  type UpdateNodeActionData (line 174) | type UpdateNodeActionData = {
  type UpdateNodeData (line 180) | type UpdateNodeData = {
  type ITreeItem (line 190) | interface ITreeItem {
  type NodeReleaseItem (line 211) | interface NodeReleaseItem {
  type NodeReleaseDetail (line 225) | interface NodeReleaseDetail {
  type ScrapeRSSItem (line 236) | type ScrapeRSSItem = {
  type AppCommonInfo (line 245) | type AppCommonInfo = {
  type AppStats (line 250) | type AppStats = {
  type AppListItem (line 256) | type AppListItem = {
  type DingBotSetting (line 265) | type DingBotSetting = {
  type WechatOfficeAccountSetting (line 273) | type WechatOfficeAccountSetting = {
  type WecomBotSetting (line 281) | type WecomBotSetting = {
  type WecomBotServiceSetting (line 290) | type WecomBotServiceSetting = {
  type FeishuBotSetting (line 298) | type FeishuBotSetting = {
  type DiscordBotSetting (line 305) | type DiscordBotSetting = {
  type HeaderSetting (line 310) | type HeaderSetting = {
  type WelcomeSetting (line 316) | type WelcomeSetting = {
  type SEOSetting (line 323) | type SEOSetting = {
  type CustomCodeSetting (line 328) | type CustomCodeSetting = {
  type ThemeAndStyleSetting (line 333) | type ThemeAndStyleSetting = {
  type ThemeMode (line 338) | type ThemeMode = {
  type FooterSetting (line 342) | type FooterSetting = {
  type CatalogSetting (line 358) | type CatalogSetting = {
  type WebComponentSetting (line 364) | type WebComponentSetting = {
  type OtherSetting (line 371) | type OtherSetting = {
  type CustomSetting (line 379) | type CustomSetting = {
  type DomainSocialMediaAccount (line 388) | interface DomainSocialMediaAccount {
  type AppSetting (line 396) | type AppSetting = HeaderSetting &
  type RecommendNode (line 410) | type RecommendNode = {
  type AppDetail (line 420) | type AppDetail = {
  type UpdateAppDetailData (line 429) | type UpdateAppDetailData = {
  type AppConfigEditData (line 434) | type AppConfigEditData = {
  type GetModelNameData (line 448) | type GetModelNameData = {
  type CreateModelData (line 457) | type CreateModelData = {
  type CheckModelData (line 462) | type CheckModelData = {
  type UpdateModelData (line 466) | type UpdateModelData = {
  type DomainModelParam (line 471) | interface DomainModelParam {
  type ModelListItem (line 481) | type ModelListItem = {
  type GetConversationListData (line 494) | type GetConversationListData = {
  type ConversationListItem (line 500) | type ConversationListItem = {
  type FeedbackListItem (line 527) | type FeedbackListItem = {
  type FeedbackInfo (line 546) | type FeedbackInfo = {
  type ConversationDetail (line 552) | type ConversationDetail = {
  type ChatConversationItem (line 583) | type ChatConversationItem = {
  type ChatConversationPair (line 588) | type ChatConversationPair = {
  type StatInstantPageItme (line 602) | type StatInstantPageItme = {
  type RefererHostItem (line 620) | type RefererHostItem = {
  type HotDocsItem (line 625) | type HotDocsItem = {
  type StatTypeItem (line 631) | type StatTypeItem = {
  type ConversationDistributionItem (line 637) | type ConversationDistributionItem = {
  type LicenseInfo (line 644) | type LicenseInfo = {

FILE: web/admin/src/components/Avatar/index.tsx
  type AvatarProps (line 6) | interface AvatarProps {

FILE: web/admin/src/components/BarTrend/index.tsx
  type ECharts (line 5) | type ECharts = ReturnType<typeof echarts.init>;
  type PropsData (line 6) | interface PropsData {

FILE: web/admin/src/components/Card/index.tsx
  type CardProps (line 3) | interface CardProps {

FILE: web/admin/src/components/Cascader/index.tsx
  type Item (line 4) | interface Item {
  type CascaderProps (line 16) | interface CascaderProps {

FILE: web/admin/src/components/CreateWikiModal/steps/Step1Model.tsx
  type Step1ModelProps (line 17) | interface Step1ModelProps {

FILE: web/admin/src/components/CreateWikiModal/steps/Step2Config.tsx
  constant VALIDATION_RULES (line 24) | const VALIDATION_RULES = {
  type Step2ConfigProps (line 76) | interface Step2ConfigProps {

FILE: web/admin/src/components/CreateWikiModal/steps/Step3Import.tsx
  type Step3ImportProps (line 8) | interface Step3ImportProps {

FILE: web/admin/src/components/CreateWikiModal/steps/Step6Decorate.tsx
  type Step6DecorateProps (line 8) | interface Step6DecorateProps {

FILE: web/admin/src/components/CreateWikiModal/steps/initData.ts
  constant INIT_DOC_DATA (line 4) | const INIT_DOC_DATA = [
  constant INIT_LADING_DATA (line 35) | const INIT_LADING_DATA = {

FILE: web/admin/src/components/CustomImage/index.tsx
  type ImageProps (line 6) | interface ImageProps {

FILE: web/admin/src/components/CustomModal/components/ShowContent.tsx
  type ShowContentProps (line 37) | interface ShowContentProps {
  type SortableItemProps (line 48) | interface SortableItemProps {

FILE: web/admin/src/components/CustomModal/components/basicComponents/DragBrand/Item.tsx
  type ItemProps (line 32) | type ItemProps = Omit<HTMLAttributes<HTMLDivElement>, 'onChange'> & {
  type LinkItemProps (line 46) | interface LinkItemProps extends HTMLAttributes<HTMLDivElement> {

FILE: web/admin/src/components/CustomModal/components/basicComponents/DragBrand/SortableItem.tsx
  type SortableItemProps (line 6) | type SortableItemProps = Omit<

FILE: web/admin/src/components/CustomModal/components/basicComponents/DragBrand/index.tsx
  type BrandGroup (line 26) | interface BrandGroup {
  type DragBrandProps (line 34) | interface DragBrandProps {

FILE: web/admin/src/components/CustomModal/components/basicComponents/DragBtn/Item.tsx
  type ItemProps (line 26) | type ItemProps = Omit<HTMLAttributes<HTMLDivElement>, 'onChange'> & {

FILE: web/admin/src/components/CustomModal/components/basicComponents/DragBtn/SortableItem.tsx
  type SortableItemProps (line 6) | type SortableItemProps = ItemProps & {};

FILE: web/admin/src/components/CustomModal/components/basicComponents/DragBtn/index.tsx
  type DragBtnProps (line 24) | interface DragBtnProps {

FILE: web/admin/src/components/CustomModal/components/basicComponents/DragSocialInfo/Item.tsx
  type SocialInfoProps (line 24) | interface SocialInfoProps extends HTMLAttributes<HTMLDivElement> {

FILE: web/admin/src/components/CustomModal/components/basicComponents/DragSocialInfo/SortableItem.tsx
  type SortableItemProps (line 6) | type SortableItemProps = SocialInfoProps & {};

FILE: web/admin/src/components/CustomModal/components/basicComponents/DragSocialInfo/index.tsx
  type DragSocialInfoProps (line 24) | interface DragSocialInfoProps {

FILE: web/admin/src/components/CustomModal/components/components/ColorPickerField.tsx
  type ColorPickerFieldProps (line 8) | type ColorPickerFieldProps = {

FILE: web/admin/src/components/CustomModal/components/components/ComponentBar.tsx
  type ComponentBarProps (line 38) | interface ComponentBarProps {

FILE: web/admin/src/components/CustomModal/components/components/DragList.tsx
  type DragListProps (line 30) | interface DragListProps<T extends { id?: string | null }> {
  function DragList (line 54) | function DragList<T extends { id?: string | null }>({

FILE: web/admin/src/components/CustomModal/components/components/SortableItem.tsx
  type SortableItemProps (line 5) | interface SortableItemProps<T extends { id?: string | null }> {
  function SortableItem (line 14) | function SortableItem<T extends { id?: string | null }>({

FILE: web/admin/src/components/CustomModal/components/config/BannerConfig/HotSearchItem.tsx
  type HotSearchItem (line 11) | type HotSearchItem = {
  type HotSearchItemProps (line 16) | type HotSearchItemProps = Omit<

FILE: web/admin/src/components/CustomModal/components/config/BannerConfig/Item.tsx
  type Item (line 20) | type Item = {
  type ItemProps (line 27) | type ItemProps = Omit<HTMLAttributes<HTMLDivElement>, 'onChange'> & {

FILE: web/admin/src/components/CustomModal/components/config/BasicDocConfig/Item.tsx
  type ItemProps (line 14) | type ItemProps = HTMLAttributes<HTMLDivElement> & {

FILE: web/admin/src/components/CustomModal/components/config/BlockGridConfig/Item.tsx
  type ItemType (line 12) | type ItemType = {
  type ItemProps (line 18) | type ItemProps = Omit<HTMLAttributes<HTMLDivElement>, 'onChange'> & {

FILE: web/admin/src/components/CustomModal/components/config/CarouselConfig/Item.tsx
  type Item (line 12) | type Item = {
  type ItemProps (line 19) | type ItemProps = Omit<HTMLAttributes<HTMLDivElement>, 'onChange'> & {

FILE: web/admin/src/components/CustomModal/components/config/CaseConfig/Item.tsx
  type ItemType (line 11) | type ItemType = {
  type ItemTypeProps (line 17) | type ItemTypeProps = Omit<HTMLAttributes<HTMLDivElement>, 'onChange'> & {

FILE: web/admin/src/components/CustomModal/components/config/CommentConfig/Item.tsx
  type ItemType (line 12) | type ItemType = {
  type ItemTypeProps (line 20) | type ItemTypeProps = Omit<HTMLAttributes<HTMLDivElement>, 'onChange'> & {

FILE: web/admin/src/components/CustomModal/components/config/ConfigBar.tsx
  type ConfigBarProps (line 6) | interface ConfigBarProps {

FILE: web/admin/src/components/CustomModal/components/config/DirDocConfig/Item.tsx
  type ItemProps (line 14) | type ItemProps = HTMLAttributes<HTMLDivElement> & {

FILE: web/admin/src/components/CustomModal/components/config/FaqConfig/Item.tsx
  type FaqItem (line 11) | type FaqItem = {
  type FaqItemProps (line 17) | type FaqItemProps = Omit<HTMLAttributes<HTMLDivElement>, 'onChange'> & {

FILE: web/admin/src/components/CustomModal/components/config/FeatureConfig/Item.tsx
  type ItemType (line 11) | type ItemType = {
  type ItemProps (line 17) | type ItemProps = Omit<HTMLAttributes<HTMLDivElement>, 'onChange'> & {

FILE: web/admin/src/components/CustomModal/components/config/FooterConfig.tsx
  type FooterConfigProps (line 22) | interface FooterConfigProps {
  type Option (line 27) | interface Option {

FILE: web/admin/src/components/CustomModal/components/config/HeaderConfig.tsx
  type CardWebHeaderProps (line 11) | interface CardWebHeaderProps {

FILE: web/admin/src/components/CustomModal/components/config/MetricsConfig/Item.tsx
  type ItemType (line 11) | type ItemType = {
  type ItemTypeProps (line 17) | type ItemTypeProps = Omit<HTMLAttributes<HTMLDivElement>, 'onChange'> & {

FILE: web/admin/src/components/CustomModal/components/config/QuestionConfig/Item.tsx
  type ItemType (line 11) | type ItemType = {
  type ItemProps (line 16) | type ItemProps = Omit<HTMLAttributes<HTMLDivElement>, 'onChange'> & {

FILE: web/admin/src/components/CustomModal/components/config/SimpleDocConfig/Item.tsx
  type ItemProps (line 12) | type ItemProps = HTMLAttributes<HTMLDivElement> & {

FILE: web/admin/src/components/CustomModal/components/config/type.ts
  type ConfigProps (line 3) | interface ConfigProps {

FILE: web/admin/src/components/CustomModal/constants.tsx
  constant DEFAULT_DATA (line 20) | const DEFAULT_DATA = {
  constant COMPONENTS_MAP (line 133) | const COMPONENTS_MAP = {
  constant TYPE_TO_CONFIG_LABEL (line 303) | const TYPE_TO_CONFIG_LABEL = {

FILE: web/admin/src/components/CustomModal/index.tsx
  type WebAppLandingConfigWithId (line 27) | type WebAppLandingConfigWithId = DomainWebAppLandingConfigResp & { id: s...
  type CustomModalProps (line 29) | interface CustomModalProps {
  type Component (line 38) | interface Component {

FILE: web/admin/src/components/Drag/DragRecommend/Item.tsx
  type ItemProps (line 9) | type ItemProps = HTMLAttributes<HTMLDivElement> & {

FILE: web/admin/src/components/Drag/DragRecommend/SortableItem.tsx
  type SortableItemProps (line 6) | type SortableItemProps = ItemProps & {

FILE: web/admin/src/components/Drag/DragRecommend/index.tsx
  type DragRecommendProps (line 23) | interface DragRecommendProps {

FILE: web/admin/src/components/Drag/DragTree/TreeItem.tsx
  constant ANSWERABLE_PERMISSIONS_MAP (line 54) | const ANSWERABLE_PERMISSIONS_MAP = {
  constant VISITABLE_PERMISSIONS_MAP (line 69) | const VISITABLE_PERMISSIONS_MAP = {
  constant VISIBLE_PERMISSIONS_MAP (line 84) | const VISIBLE_PERMISSIONS_MAP = {

FILE: web/admin/src/components/Drag/DragTree/TreeMenu.tsx
  type TreeMenuItem (line 7) | type TreeMenuItem = {
  type TreeMenuOptions (line 22) | type TreeMenuOptions = {

FILE: web/admin/src/components/Drag/DragTree/index.tsx
  type DragTreeHandle (line 14) | type DragTreeHandle = {

FILE: web/admin/src/components/Emoji/index.tsx
  type EmojiPickerProps (line 12) | interface EmojiPickerProps {

FILE: web/admin/src/components/EmptyState/index.tsx
  type EmptyStateProps (line 4) | interface EmptyStateProps {

FILE: web/admin/src/components/FreeSoloAutocomplete/index.tsx
  type FreeSoloAutocompleteProps (line 12) | type FreeSoloAutocompleteProps<T> = {
  function FreeSoloAutocomplete (line 28) | function FreeSoloAutocomplete<T>({

FILE: web/admin/src/components/KB/KBCreate.tsx
  constant VALIDATION_RULES (line 19) | const VALIDATION_RULES = {

FILE: web/admin/src/components/KB/KBDelete.tsx
  type KBDeleteProps (line 10) | interface KBDeleteProps {

FILE: web/admin/src/components/KB/KBModify.tsx
  type KBModifyProps (line 8) | interface KBModifyProps {

FILE: web/admin/src/components/Loading/index.tsx
  type LoadingProps (line 3) | interface LoadingProps {

FILE: web/admin/src/components/MapChart/index.tsx
  type Props (line 7) | interface Props {
  type EchartsGlobal (line 81) | type EchartsGlobal = { init: (el: HTMLDivElement) => ECharts };

FILE: web/admin/src/components/MarkDown/index.tsx
  type MarkDownProps (line 17) | interface MarkDownProps {
  method code (line 177) | code({

FILE: web/admin/src/components/PieTrend/index.tsx
  type ECharts (line 5) | type ECharts = ReturnType<typeof echarts.init>;
  type PropsData (line 6) | interface PropsData {

FILE: web/admin/src/components/ShowText/index.tsx
  type ShowTextProps (line 7) | interface ShowTextProps {

FILE: web/admin/src/components/Sidebar/AuthTypeModal.tsx
  type AuthTypeModalProps (line 22) | interface AuthTypeModalProps {

FILE: web/admin/src/components/Sidebar/index.tsx
  constant MENUS (line 25) | const MENUS = [

FILE: web/admin/src/components/System/component/AutoModelConfig.tsx
  type AutoModelConfigRef (line 16) | interface AutoModelConfigRef {
  type AutoModelConfigProps (line 23) | interface AutoModelConfigProps {

FILE: web/admin/src/components/System/component/MemberAdd.tsx
  type Role (line 17) | type Role = 'admin' | 'user';
  constant PERM_MAP (line 19) | const PERM_MAP = {
  constant VERSION_MAP (line 25) | const
Condensed preview — 1181 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (7,082K chars).
[
  {
    "path": ".gitattributes",
    "chars": 69,
    "preview": "backend/store/ipdb/ip2region.xdb filter=lfs diff=lfs merge=lfs -text\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/功能建议.md",
    "chars": 232,
    "preview": "---\nname: 功能建议\nabout: 为PandaWiki提出新的想法或建议\ntitle: \"[功能建议] \"\nlabels: enhancement\nassignees: ''\n\n---\n\n**功能描述**\n请简明扼要地描述您希望添"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/故障报告.md",
    "chars": 344,
    "preview": "---\nname: 故障报告\nabout: 创建故障报告以改进产品\ntitle: \"[故障报告] \"\nlabels: bug\nassignees: ''\n\n---\n\n**描述问题**\n请简明扼要地描述您遇到的问题。\n\n**复现步骤**\n请描"
  },
  {
    "path": ".github/PULL_REQUEST_TEMPLATE.md",
    "chars": 390,
    "preview": "# PR 标题\n\n简要描述这次 PR 的目的和内容\n\n## 相关 Issue\n\n关闭或关联的 Issue (如有):\n- 修复 #123\n- 关联 #456\n\n## 变更类型\n\n请勾选适用的变更类型:\n- [ ] Bug 修复 (不兼容变更"
  },
  {
    "path": ".github/workflows/backend.yml",
    "chars": 2092,
    "preview": "name: Backend Build and Push\n\non:\n  push:\n    tags:\n      - \"v[0-9]+.[0-9]+.[0-9]+*\"\n\njobs:\n  build:\n    runs-on: ubuntu"
  },
  {
    "path": ".github/workflows/backend_check.yml",
    "chars": 2886,
    "preview": "name: Backend Pull Request Check\n\non:\n  pull_request:\n    branches:\n      - main\n    paths:\n      - 'backend/**'\n\npermis"
  },
  {
    "path": ".github/workflows/web.yml",
    "chars": 4581,
    "preview": "name: Web Build and Push\n\non:\n  push:\n    branches:\n      - frontend-*\n      - admin-*\n      - app-*\n    tags:\n      - '"
  },
  {
    "path": ".gitignore",
    "chars": 560,
    "preview": "# If you prefer the allow list template instead of the deny list, see community template:\n# https://github.com/github/gi"
  },
  {
    "path": ".gitmodules",
    "chars": 93,
    "preview": "[submodule \"backend/pro\"]\n\tpath = backend/pro\n\turl = git@github.com:chaitin/PandaWikiPro.git\n"
  },
  {
    "path": "CODE_OF_CONDUCT.md",
    "chars": 5202,
    "preview": "# Contributor Covenant Code of Conduct\n\n## Our Pledge\n\nWe as members, contributors, and leaders pledge to make participa"
  },
  {
    "path": "CONTRIBUTING.md",
    "chars": 583,
    "preview": "# 贡献指南\n\n欢迎为 PandaWiki 项目做贡献!本指南将帮助你开始贡献代码。\n\n\n## 代码提交流程\n\n1. 创建新的功能分支:\n```bash\ngit checkout -b feat/your-feature-name\n```\n"
  },
  {
    "path": "LICENSE",
    "chars": 34523,
    "preview": "                    GNU AFFERO GENERAL PUBLIC LICENSE\n                       Version 3, 19 November 2007\n\n Copyright (C)"
  },
  {
    "path": "PROJECT_STRUCTURE.md",
    "chars": 2751,
    "preview": "# PandaWiki 项目结构文档\n\n## 项目概述\n\nPandaWiki 是一个由 AI 大模型驱动的开源知识库搭建系统。该项目采用前后端分离的架构,包含后端服务、前端管理界面、前端用户界面以及 SDK。\n\n## 根目录结构\n\n```\n"
  },
  {
    "path": "README.md",
    "chars": 3364,
    "preview": "<p align=\"center\">\n  <img src=\"/images/banner.png\" width=\"400\" />\n</p>\n\n<p align=\"center\">\n  <a target=\"_blank\" href=\"ht"
  },
  {
    "path": "SECURITY.md",
    "chars": 346,
    "preview": "# 安全策略\n\n## 受支持的版本\n\nPandaWiki 采用 rolling release 的方式进行发行,非最新版 release 中存在的安全问题不在本计划的考虑范围之内。\n\n## 报告安全漏洞\n说明如何报告安全问题。建议使用私下报"
  },
  {
    "path": "backend/.dockerignore",
    "chars": 7,
    "preview": "deploy\n"
  },
  {
    "path": "backend/.golangci.toml",
    "chars": 170,
    "preview": "version = \"2\"\n\nlinters.default = \"standard\"\n\n[[linters.exclusions.rules]]\nlinters = [ \"errcheck\" ]\nsource = \"^\\\\s*defer\\"
  },
  {
    "path": "backend/Dockerfile.api",
    "chars": 1230,
    "preview": "FROM --platform=$BUILDPLATFORM golang:1.24.3-alpine AS builder\n\nWORKDIR /src\nENV CGO_ENABLED=0\n\nCOPY go.mod go.sum ./\nRU"
  },
  {
    "path": "backend/Dockerfile.api.pro",
    "chars": 1246,
    "preview": "FROM --platform=$BUILDPLATFORM golang:1.24.3-alpine AS builder\n\nWORKDIR /src\nENV CGO_ENABLED=0\n\nCOPY go.mod go.sum ./\nRU"
  },
  {
    "path": "backend/Dockerfile.consumer",
    "chars": 856,
    "preview": "FROM --platform=$BUILDPLATFORM golang:1.24.3-alpine AS builder\n\nWORKDIR /src\nENV CGO_ENABLED=0\n\nCOPY go.mod go.sum ./\nRU"
  },
  {
    "path": "backend/Dockerfile.consumer.pro",
    "chars": 872,
    "preview": "FROM --platform=$BUILDPLATFORM golang:1.24.3-alpine AS builder\n\nWORKDIR /src\nENV CGO_ENABLED=0\n\nCOPY go.mod go.sum ./\nRU"
  },
  {
    "path": "backend/Makefile",
    "chars": 2256,
    "preview": "generate:\n\tswag fmt --dir handler && swag init --exclude pro -g cmd/api/main.go --pd \\\n\t&& wire cmd/api/wire.go \\\n\t&& wi"
  },
  {
    "path": "backend/api/auth/v1/auth.go",
    "chars": 1704,
    "preview": "package v1\n\nimport (\n\t\"time\"\n\n\t\"github.com/chaitin/panda-wiki/consts\"\n)\n\ntype AuthGetReq struct {\n\tKBID       string    "
  },
  {
    "path": "backend/api/conversation/v1/conversation.go",
    "chars": 407,
    "preview": "package v1\n\ntype GetConversationDetailReq struct {\n\tKbId string `query:\"kb_id\" json:\"kb_id\" validate:\"required\"`\n\tID   s"
  },
  {
    "path": "backend/api/crawler/v1/confluence.go",
    "chars": 586,
    "preview": "package v1\n\ntype ConfluenceParseReq struct {\n\tKbID string `json:\"kb_id\" validate:\"required\"`\n}\n\ntype ConfluenceParseItem"
  },
  {
    "path": "backend/api/crawler/v1/crawler.go",
    "chars": 1605,
    "preview": "package v1\n\nimport (\n\t\"github.com/chaitin/panda-wiki/consts\"\n\t\"github.com/chaitin/panda-wiki/pkg/anydoc\"\n)\n\ntype Crawler"
  },
  {
    "path": "backend/api/crawler/v1/epub.go",
    "chars": 261,
    "preview": "package v1\n\ntype EpubParseReq struct {\n\tKbID     string `json:\"kb_id\" validate:\"required\"`\n\tFilename string `json:\"filen"
  },
  {
    "path": "backend/api/crawler/v1/feishu.go",
    "chars": 1663,
    "preview": "package v1\n\ntype FeishuSpaceListReq struct {\n\tUserAccessToken string `json:\"user_access_token\" validate:\"required\"`\n\tApp"
  },
  {
    "path": "backend/api/crawler/v1/mindoc.go",
    "chars": 558,
    "preview": "package v1\n\ntype MindocParseReq struct {\n\tKbID string `json:\"kb_id\" validate:\"required\"`\n}\n\ntype MindocParseItem struct "
  },
  {
    "path": "backend/api/crawler/v1/notion.go",
    "chars": 543,
    "preview": "package v1\n\ntype NotionParseReq struct {\n\tIntegration string `json:\"integration\" validate:\"required\"`\n}\ntype NotionParse"
  },
  {
    "path": "backend/api/crawler/v1/siyuan.go",
    "chars": 558,
    "preview": "package v1\n\ntype SiyuanParseReq struct {\n\tKbID string `json:\"kb_id\" validate:\"required\"`\n}\n\ntype SiyuanParseItem struct "
  },
  {
    "path": "backend/api/crawler/v1/wikijs.go",
    "chars": 531,
    "preview": "package v1\n\ntype WikijsParseReq struct {\n\tKbID string `json:\"kb_id\" validate:\"required\"`\n}\n\ntype WikijsParseItem struct "
  },
  {
    "path": "backend/api/crawler/v1/yuque.go",
    "chars": 362,
    "preview": "package v1\n\ntype YuqueParseReq struct {\n\tKbID     string `json:\"kb_id\" validate:\"required\"`\n\tFilename string `json:\"file"
  },
  {
    "path": "backend/api/kb/v1/kb.go",
    "chars": 1185,
    "preview": "package v1\n\nimport (\n\t\"github.com/chaitin/panda-wiki/consts\"\n)\n\ntype KBUserListReq struct {\n\tKBId string `json:\"kb_id\" q"
  },
  {
    "path": "backend/api/nav/v1/nav.go",
    "chars": 1040,
    "preview": "package v1\n\nimport \"time\"\n\ntype NavListReq struct {\n\tKbId string `json:\"kb_id\" query:\"kb_id\" validate:\"required\"`\n}\n\ntyp"
  },
  {
    "path": "backend/api/node/v1/node.go",
    "chars": 3872,
    "preview": "package v1\n\nimport (\n\t\"time\"\n\n\t\"github.com/chaitin/panda-wiki/domain\"\n)\n\ntype GetNodeDetailReq struct {\n\tKbId   string `"
  },
  {
    "path": "backend/api/openapi/v1/openapi.go",
    "chars": 166,
    "preview": "package v1\n\ntype GitHubCallbackReq struct {\n\tCode  string `json:\"code\" query:\"code\"`\n\tState string `json:\"state\" query:\""
  },
  {
    "path": "backend/api/share/v1/auth.go",
    "chars": 741,
    "preview": "package v1\n\nimport \"github.com/chaitin/panda-wiki/consts\"\n\ntype AuthLoginSimpleReq struct {\n\tPassword string `json:\"pass"
  },
  {
    "path": "backend/api/share/v1/common.go",
    "chars": 514,
    "preview": "package v1\n\ntype ShareFileUploadReq struct {\n\tKbId         string `json:\"-\"`\n\tFile         string `form:\"file\"`\n\tCaptcha"
  },
  {
    "path": "backend/api/share/v1/nav.go",
    "chars": 106,
    "preview": "package v1\n\ntype ShareNavListReq struct {\n\tKbId string `json:\"kb_id\" query:\"kb_id\" validate:\"required\"`\n}\n"
  },
  {
    "path": "backend/api/share/v1/node.go",
    "chars": 1708,
    "preview": "package v1\n\nimport (\n\t\"time\"\n\n\t\"github.com/chaitin/panda-wiki/domain\"\n)\n\ntype ShareNodeDetailResp struct {\n\tID          "
  },
  {
    "path": "backend/api/share/v1/wechat.go",
    "chars": 269,
    "preview": "package v1\n\ntype WechatAppInfoResp struct {\n\tWeChatAppIsEnabled bool     `json:\"wechat_app_is_enabled\"`\n\tFeedbackEnable "
  },
  {
    "path": "backend/api/stat/v1/stat.go",
    "chars": 1791,
    "preview": "package v1\n\nimport (\n\t\"github.com/chaitin/panda-wiki/consts\"\n\t\"github.com/chaitin/panda-wiki/domain\"\n)\n\ntype StatInstant"
  },
  {
    "path": "backend/api/user/v1/user.go",
    "chars": 1480,
    "preview": "package v1\n\nimport (\n\t\"time\"\n\n\t\"github.com/chaitin/panda-wiki/consts\"\n)\n\ntype CreateUserReq struct {\n\tAccount  string   "
  },
  {
    "path": "backend/apm/provider.go",
    "chars": 87,
    "preview": "package apm\n\nimport \"github.com/google/wire\"\n\nvar ProviderSet = wire.NewSet(NewTracer)\n"
  },
  {
    "path": "backend/apm/trace.go",
    "chars": 1708,
    "preview": "package apm\n\nimport (\n\t\"context\"\n\t\"log\"\n\t\"strings\"\n\n\t\"go.opentelemetry.io/otel\"\n\t\"go.opentelemetry.io/otel/attribute\"\n\t\""
  },
  {
    "path": "backend/cSpell.json",
    "chars": 392,
    "preview": "{\n    \"$schema\": \"https://raw.githubusercontent.com/streetsidesoftware/cspell/main/cspell.schema.json\",\n    \"version\": \""
  },
  {
    "path": "backend/cmd/api/main.go",
    "chars": 639,
    "preview": "package main\n\nimport (\n\t\"fmt\"\n\n\t\"github.com/chaitin/panda-wiki/setup\"\n)\n\n// @title panda-wiki API\n// @version 1.0\n// @de"
  },
  {
    "path": "backend/cmd/api/wire.go",
    "chars": 803,
    "preview": "//go:build wireinject\n\npackage main\n\nimport (\n\t\"github.com/google/wire\"\n\n\t\"github.com/chaitin/panda-wiki/config\"\n\tshare "
  },
  {
    "path": "backend/cmd/api/wire_gen.go",
    "chars": 11006,
    "preview": "// Code generated by Wire. DO NOT EDIT.\n\n//go:generate go run -mod=mod github.com/google/wire/cmd/wire\n//go:build !wirei"
  },
  {
    "path": "backend/cmd/consumer/main.go",
    "chars": 275,
    "preview": "package main\n\nimport (\n\t\"context\"\n)\n\nfunc main() {\n\tapp, err := createApp()\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\tif err := "
  },
  {
    "path": "backend/cmd/consumer/wire.go",
    "chars": 588,
    "preview": "//go:build wireinject\n\npackage main\n\nimport (\n\t\"github.com/google/wire\"\n\n\t\"github.com/chaitin/panda-wiki/config\"\n\thandle"
  },
  {
    "path": "backend/cmd/consumer/wire_gen.go",
    "chars": 4072,
    "preview": "// Code generated by Wire. DO NOT EDIT.\n\n//go:generate go run -mod=mod github.com/google/wire/cmd/wire\n//go:build !wirei"
  },
  {
    "path": "backend/cmd/migrate/main.go",
    "chars": 160,
    "preview": "package main\n\nfunc main() {\n\tapp, err := createApp()\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\tif err := app.MigrationManager.Ex"
  },
  {
    "path": "backend/cmd/migrate/wire.go",
    "chars": 477,
    "preview": "//go:build wireinject\n\npackage main\n\nimport (\n\t\"github.com/google/wire\"\n\n\t\"github.com/chaitin/panda-wiki/config\"\n\t\"githu"
  },
  {
    "path": "backend/cmd/migrate/wire_gen.go",
    "chars": 3916,
    "preview": "// Code generated by Wire. DO NOT EDIT.\n\n//go:generate go run -mod=mod github.com/google/wire/cmd/wire\n//go:build !wirei"
  },
  {
    "path": "backend/config/config.go",
    "chars": 5977,
    "preview": "package config\n\nimport (\n\t\"fmt\"\n\t\"os\"\n\t\"strconv\"\n\n\t\"github.com/spf13/viper\"\n)\n\ntype Config struct {\n\tLog           LogCo"
  },
  {
    "path": "backend/config/provider.go",
    "chars": 90,
    "preview": "package config\n\nimport \"github.com/google/wire\"\n\nvar ProviderSet = wire.NewSet(NewConfig)\n"
  },
  {
    "path": "backend/consts/admin.go",
    "chars": 525,
    "preview": "package consts\n\ntype UserKBPermission string\n\nconst (\n\tUserKBPermissionNull        UserKBPermission = \"\"             // "
  },
  {
    "path": "backend/consts/app.go",
    "chars": 583,
    "preview": "package consts\n\ntype CopySetting string\n\nconst (\n\tCopySettingNone     CopySetting = \"\"         // 无限制\n\tCopySettingAppend"
  },
  {
    "path": "backend/consts/auth.go",
    "chars": 2066,
    "preview": "package consts\n\ntype SourceType string\n\nvar (\n\tBotSourceTypes = []SourceType{SourceTypeWidget, SourceTypeDingtalkBot, So"
  },
  {
    "path": "backend/consts/captcha.go",
    "chars": 121,
    "preview": "package consts\n\ntype RedeemCaptchaReq struct {\n\tToken     string  `json:\"token\"`\n\tSolutions []int64 `json:\"solutions\"`\n}"
  },
  {
    "path": "backend/consts/consts.go",
    "chars": 138,
    "preview": "package consts\n\ntype StatDay int\n\nconst (\n\tStatDay1  StatDay = 1\n\tStatDay7  StatDay = 7\n\tStatDay30 StatDay = 30\n\tStatDay"
  },
  {
    "path": "backend/consts/contribute.go",
    "chars": 349,
    "preview": "package consts\n\ntype ContributeStatus string\n\nconst (\n\tContributeStatusPending  ContributeStatus = \"pending\"\n\tContribute"
  },
  {
    "path": "backend/consts/crawler.go",
    "chars": 257,
    "preview": "package consts\n\ntype CrawlerStatus string\n\nconst (\n\tCrawlerStatusPending   CrawlerStatus = \"pending\"\n\tCrawlerStatusInPro"
  },
  {
    "path": "backend/consts/license.go",
    "chars": 500,
    "preview": "package consts\n\nimport (\n\t\"github.com/labstack/echo/v4\"\n)\n\ntype contextKey string\n\nconst ContextKeyEdition contextKey = "
  },
  {
    "path": "backend/consts/model.go",
    "chars": 1089,
    "preview": "package consts\n\ntype AutoModeDefaultModel string\n\nconst (\n\tAutoModeDefaultChatModel       AutoModeDefaultModel = \"deepse"
  },
  {
    "path": "backend/consts/node.go",
    "chars": 827,
    "preview": "package consts\n\ntype NodeAccessPerm string\n\nconst (\n\tNodeAccessPermOpen    NodeAccessPerm = \"open\"    // 完全开放\n\tNodeAcces"
  },
  {
    "path": "backend/consts/parse.go",
    "chars": 1435,
    "preview": "package consts\n\ntype CrawlerSource string\n\nconst (\n\t// CrawlerSourceUrl key或url形式 直接走parse接口\n\tCrawlerSourceUrl      Craw"
  },
  {
    "path": "backend/consts/system_setting.go",
    "chars": 172,
    "preview": "package consts\n\ntype SystemSettingKey string\n\nconst (\n\tSystemSettingModelMode SystemSettingKey = \"model_setting_mode\"\n\tS"
  },
  {
    "path": "backend/docs/docs.go",
    "chars": 310916,
    "preview": "// Package docs Code generated by swaggo/swag. DO NOT EDIT\npackage docs\n\nimport \"github.com/swaggo/swag\"\n\nconst docTempl"
  },
  {
    "path": "backend/docs/swagger.json",
    "chars": 310233,
    "preview": "{\n    \"swagger\": \"2.0\",\n    \"info\": {\n        \"description\": \"panda-wiki API documentation\",\n        \"title\": \"panda-wik"
  },
  {
    "path": "backend/docs/swagger.yaml",
    "chars": 139915,
    "preview": "basePath: /\ndefinitions:\n  anydoc.Child:\n    properties:\n      children:\n        items:\n          $ref: '#/definitions/a"
  },
  {
    "path": "backend/domain/api_token.go",
    "chars": 1110,
    "preview": "package domain\n\nimport (\n\t\"context\"\n\t\"time\"\n\n\t\"github.com/chaitin/panda-wiki/consts\"\n)\n\ntype APIToken struct {\n\tID      "
  },
  {
    "path": "backend/domain/app.go",
    "chars": 23925,
    "preview": "package domain\n\nimport (\n\t\"database/sql/driver\"\n\t\"encoding/json\"\n\t\"errors\"\n\t\"fmt\"\n\t\"time\"\n\n\t\"github.com/chaitin/panda-wi"
  },
  {
    "path": "backend/domain/auth.go",
    "chars": 4436,
    "preview": "package domain\n\nimport (\n\t\"database/sql/driver\"\n\t\"encoding/json\"\n\t\"errors\"\n\t\"fmt\"\n\t\"time\"\n\n\t\"github.com/labstack/echo/v4"
  },
  {
    "path": "backend/domain/chat.go",
    "chars": 2162,
    "preview": "package domain\n\nimport (\n\t\"database/sql/driver\"\n\t\"encoding/json\"\n\t\"errors\"\n\t\"fmt\"\n)\n\ntype ChatRequest struct {\n\tConversa"
  },
  {
    "path": "backend/domain/comment.go",
    "chars": 3183,
    "preview": "package domain\n\nimport (\n\t\"database/sql/driver\"\n\t\"encoding/json\"\n\t\"errors\"\n\t\"fmt\"\n\t\"time\"\n\n\t\"github.com/lib/pq\"\n)\n\ntype "
  },
  {
    "path": "backend/domain/contribute.go",
    "chars": 1281,
    "preview": "package domain\n\nimport (\n\t\"time\"\n\n\t\"github.com/chaitin/panda-wiki/consts\"\n)\n\ntype Contribute struct {\n\tId          strin"
  },
  {
    "path": "backend/domain/conversation.go",
    "chars": 4521,
    "preview": "package domain\n\nimport (\n\t\"database/sql/driver\"\n\t\"encoding/json\"\n\t\"errors\"\n\t\"time\"\n\n\t\"github.com/cloudwego/eino/schema\"\n"
  },
  {
    "path": "backend/domain/creation.go",
    "chars": 454,
    "preview": "package domain\n\ntype TextReq struct {\n\tText   string `json:\"text\" validate:\"required\"`\n\tAction string `json:\"action\"` //"
  },
  {
    "path": "backend/domain/epub.go",
    "chars": 225,
    "preview": "package domain\n\ntype EpubReq struct {\n\tKbID string `json:\"kb_id\" binding:\"required\" validate:\"required\"`\n}\n\ntype EpubRes"
  },
  {
    "path": "backend/domain/errors.go",
    "chars": 515,
    "preview": "package domain\n\nimport \"errors\"\n\nvar ErrModelNotConfigured = errors.New(\"model not configured\")\n\nvar ErrPortHostAlreadyE"
  },
  {
    "path": "backend/domain/file.go",
    "chars": 373,
    "preview": "package domain\n\nconst (\n\tBucket = \"static-file\"\n)\n\ntype ObjectUploadResp struct {\n\tKey      string `json:\"key\"`\n\tFilenam"
  },
  {
    "path": "backend/domain/icon.go",
    "chars": 9374,
    "preview": "package domain\n\nconst (\n\tDefaultGitHubIconB64    = `data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMgAAADICAYAAACtWK6eAA"
  },
  {
    "path": "backend/domain/ip.go",
    "chars": 171,
    "preview": "package domain\n\ntype IPAddress struct {\n\tIP       string `json:\"ip\"`\n\tCountry  string `json:\"country\"`\n\tProvince string "
  },
  {
    "path": "backend/domain/json.go",
    "chars": 485,
    "preview": "package domain\n\nimport (\n\t\"database/sql/driver\"\n\t\"encoding/json\"\n\t\"fmt\"\n)\n\ntype MapStrInt64 map[string]int64\n\nfunc (m *M"
  },
  {
    "path": "backend/domain/knowledge_base.go",
    "chars": 5201,
    "preview": "package domain\n\nimport (\n\t\"database/sql/driver\"\n\t\"encoding/json\"\n\t\"errors\"\n\t\"fmt\"\n\t\"strings\"\n\t\"time\"\n\n\t\"github.com/chait"
  },
  {
    "path": "backend/domain/license.go",
    "chars": 1656,
    "preview": "package domain\n\nimport (\n\t\"context\"\n\t\"encoding/json\"\n)\n\nconst ContextKeyEditionLimitation contextKey = \"edition_limitati"
  },
  {
    "path": "backend/domain/llm.go",
    "chars": 4519,
    "preview": "package domain\n\nimport (\n\t\"fmt\"\n\t\"regexp\"\n\t\"strings\"\n)\n\nconst PromptHeader = `你是一个专业的AI知识库问答助手,要按照以下步骤回答用户问题。\n\n请仔细阅读以下信息"
  },
  {
    "path": "backend/domain/model.go",
    "chars": 5794,
    "preview": "package domain\n\nimport (\n\t\"database/sql/driver\"\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"time\"\n\n\tmodelkitConsts \"github.com/chaitin/Mod"
  },
  {
    "path": "backend/domain/mq.go",
    "chars": 1230,
    "preview": "package domain\n\nconst (\n\tVectorTaskTopic       = \"apps.panda-wiki.vector.task\"\n\tAnydocTaskExportTopic = \"anydoc.persiste"
  },
  {
    "path": "backend/domain/nav.go",
    "chars": 1151,
    "preview": "package domain\n\nimport \"time\"\n\ntype Nav struct {\n\tID        string    `json:\"id\" gorm:\"primaryKey;type:text\"`\n\tName     "
  },
  {
    "path": "backend/domain/node.go",
    "chars": 11503,
    "preview": "package domain\n\nimport (\n\t\"database/sql/driver\"\n\t\"encoding/json\"\n\t\"errors\"\n\t\"fmt\"\n\t\"time\"\n\n\t\"github.com/lib/pq\"\n\n\t\"githu"
  },
  {
    "path": "backend/domain/notion.go",
    "chars": 248,
    "preview": "package domain\n\ntype Page struct {\n\tID       string `json:\"id\"`\n\tTitle    string `json:\"title\"`\n\tParentId string `json:\""
  },
  {
    "path": "backend/domain/openai.go",
    "chars": 5901,
    "preview": "package domain\n\nimport (\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"strings\"\n)\n\n// OpenAI API 请求结构体\ntype OpenAICompletionsRequest struct "
  },
  {
    "path": "backend/domain/openai_test.go",
    "chars": 4561,
    "preview": "package domain\n\nimport (\n\t\"encoding/json\"\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/assert\"\n\t\"github.com/stretchr/testif"
  },
  {
    "path": "backend/domain/pager.go",
    "chars": 806,
    "preview": "package domain\n\ntype Pager struct {\n\tPage     int `json:\"page\" query:\"page\" validate:\"required,min=1\" message:\"page must"
  },
  {
    "path": "backend/domain/prompt.go",
    "chars": 470,
    "preview": "package domain\n\ntype Prompt struct {\n\tContent                  string `json:\"content\"`\n\tSummaryContent           string "
  },
  {
    "path": "backend/domain/response.go",
    "chars": 537,
    "preview": "package domain\n\ntype PWResponse struct {\n\tMessage string `json:\"message\"`\n\tSuccess bool   `json:\"success\"`\n\tData    any "
  },
  {
    "path": "backend/domain/setting.go",
    "chars": 798,
    "preview": "package domain\n\nimport (\n\t\"context\"\n\t\"time\"\n)\n\nconst (\n\tSettingKeySystemPrompt = \"system_prompt\"\n\tSettingBlockWords     "
  },
  {
    "path": "backend/domain/siyuan.go",
    "chars": 209,
    "preview": "package domain\n\ntype SiYuanReq struct {\n\tKBID string `json:\"kb_id\" validate:\"required\"`\n}\ntype SiYuanResp struct {\n\tId  "
  },
  {
    "path": "backend/domain/sse_event.go",
    "chars": 265,
    "preview": "package domain\n\ntype SSEEvent struct {\n\tType        string               `json:\"type\"`\n\tContent     string              "
  },
  {
    "path": "backend/domain/stat.go",
    "chars": 3521,
    "preview": "package domain\n\nimport (\n\t\"time\"\n)\n\ntype StatPageScene int\n\nconst (\n\tStatPageSceneWelcome StatPageScene = iota + 1\n\tStat"
  },
  {
    "path": "backend/domain/system_setting.go",
    "chars": 1347,
    "preview": "package domain\n\nimport (\n\t\"time\"\n\n\t\"github.com/chaitin/panda-wiki/consts\"\n)\n\n// table: settings\ntype SystemSetting struc"
  },
  {
    "path": "backend/domain/user.go",
    "chars": 1054,
    "preview": "package domain\n\nimport (\n\t\"time\"\n\n\t\"github.com/chaitin/panda-wiki/consts\"\n)\n\ntype User struct {\n\tID         string      "
  },
  {
    "path": "backend/domain/userfeedback.go",
    "chars": 599,
    "preview": "package domain\n\n// 用户反馈请求\ntype FeedbackRequest struct {\n\tConversationId  string       `json:\"conversation_id\"`\n\tMessageI"
  },
  {
    "path": "backend/domain/wechat.go",
    "chars": 426,
    "preview": "package domain\n\nimport (\n\t\"bytes\"\n\t\"sync\"\n)\n\n// ConversationState\ntype ConversationState struct {\n\tMutex            sync"
  },
  {
    "path": "backend/go.mod",
    "chars": 10648,
    "preview": "module github.com/chaitin/panda-wiki\n\ngo 1.24.3\n\nrequire (\n\tgithub.com/JohannesKaufmann/dom v0.2.0\n\tgithub.com/JohannesK"
  },
  {
    "path": "backend/go.sum",
    "chars": 83074,
    "preview": "cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=\ncloud.google.com/go v0.116.0 h1:B3fRr"
  },
  {
    "path": "backend/handler/base.go",
    "chars": 2082,
    "preview": "package handler\n\nimport (\n\t\"fmt\"\n\t\"log/slog\"\n\t\"net/http\"\n\n\t\"github.com/google/uuid\"\n\t\"github.com/labstack/echo/v4\"\n\t\"go."
  },
  {
    "path": "backend/handler/mq/cron.go",
    "chars": 4400,
    "preview": "package mq\n\nimport (\n\t\"context\"\n\t\"time\"\n\n\t\"github.com/robfig/cron/v3\"\n\n\t\"github.com/chaitin/panda-wiki/log\"\n\t\"github.com"
  },
  {
    "path": "backend/handler/mq/provider.go",
    "chars": 761,
    "preview": "package mq\n\nimport (\n\t\"github.com/google/wire\"\n\n\t\"github.com/chaitin/panda-wiki/repo/ipdb\"\n\t\"github.com/chaitin/panda-wi"
  },
  {
    "path": "backend/handler/mq/rag.go",
    "chars": 6245,
    "preview": "package mq\n\nimport (\n\t\"context\"\n\t\"encoding/json\"\n\n\t\"github.com/chaitin/panda-wiki/consts\"\n\t\"github.com/chaitin/panda-wik"
  },
  {
    "path": "backend/handler/mq/rag_doc_update.go",
    "chars": 1788,
    "preview": "package mq\n\nimport (\n\t\"context\"\n\t\"encoding/json\"\n\t\"time\"\n\n\t\"github.com/chaitin/panda-wiki/consts\"\n\t\"github.com/chaitin/p"
  },
  {
    "path": "backend/handler/share/app.go",
    "chars": 8375,
    "preview": "package share\n\nimport (\n\t\"context\"\n\t\"net/http\"\n\n\t\"github.com/labstack/echo/v4\"\n\twechat_v2 \"github.com/silenceper/wechat/"
  },
  {
    "path": "backend/handler/share/auth.go",
    "chars": 5034,
    "preview": "package share\n\nimport (\n\t\"context\"\n\n\t\"github.com/gorilla/sessions\"\n\t\"github.com/labstack/echo/v4\"\n\n\tv1 \"github.com/chait"
  },
  {
    "path": "backend/handler/share/captcha.go",
    "chars": 2434,
    "preview": "package share\n\nimport (\n\t\"net/http\"\n\n\tgocap \"github.com/ackcoder/go-cap\"\n\t\"github.com/getsentry/sentry-go\"\n\t\"github.com/"
  },
  {
    "path": "backend/handler/share/chat.go",
    "chars": 16493,
    "preview": "package share\n\nimport (\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"net/http\"\n\t\"strings\"\n\t\"time\"\n\n\t\"github.com/labstack/echo/v4\"\n\n\t\"github"
  },
  {
    "path": "backend/handler/share/comment.go",
    "chars": 4743,
    "preview": "package share\n\nimport (\n\t\"net/http\"\n\t\"strings\"\n\n\t\"github.com/labstack/echo/v4\"\n\n\t\"github.com/chaitin/panda-wiki/domain\"\n"
  },
  {
    "path": "backend/handler/share/common.go",
    "chars": 4436,
    "preview": "package share\n\nimport (\n\t\"fmt\"\n\t\"net/http\"\n\t\"net/url\"\n\n\t\"github.com/labstack/echo/v4\"\n\n\tv1 \"github.com/chaitin/panda-wik"
  },
  {
    "path": "backend/handler/share/coversation.go",
    "chars": 1701,
    "preview": "package share\n\nimport (\n\t\"github.com/labstack/echo/v4\"\n\n\t\"github.com/chaitin/panda-wiki/handler\"\n\t\"github.com/chaitin/pa"
  },
  {
    "path": "backend/handler/share/nav.go",
    "chars": 1634,
    "preview": "package share\n\nimport (\n\t\"github.com/labstack/echo/v4\"\n\n\tv1 \"github.com/chaitin/panda-wiki/api/share/v1\"\n\t\"github.com/ch"
  },
  {
    "path": "backend/handler/share/node.go",
    "chars": 2885,
    "preview": "package share\n\nimport (\n\t\"github.com/labstack/echo/v4\"\n\n\t\"github.com/chaitin/panda-wiki/domain\"\n\t\"github.com/chaitin/pan"
  },
  {
    "path": "backend/handler/share/openapi.go",
    "chars": 4271,
    "preview": "package share\n\nimport (\n\t\"context\"\n\t\"errors\"\n\t\"io\"\n\t\"net/http\"\n\n\t\"github.com/labstack/echo/v4\"\n\tlarkevent \"github.com/la"
  },
  {
    "path": "backend/handler/share/provider.go",
    "chars": 1119,
    "preview": "package share\n\nimport (\n\t\"github.com/google/wire\"\n\n\t\"github.com/chaitin/panda-wiki/pkg/captcha\"\n)\n\ntype ShareHandler str"
  },
  {
    "path": "backend/handler/share/sitemap.go",
    "chars": 1249,
    "preview": "package share\n\nimport (\n\t\"net/http\"\n\n\t\"github.com/labstack/echo/v4\"\n\n\t\"github.com/chaitin/panda-wiki/handler\"\n\t\"github.c"
  },
  {
    "path": "backend/handler/share/stat.go",
    "chars": 2712,
    "preview": "package share\n\nimport (\n\t\"net/url\"\n\t\"time\"\n\n\t\"github.com/labstack/echo/v4\"\n\t\"github.com/mileusna/useragent\"\n\n\t\"github.co"
  },
  {
    "path": "backend/handler/share/wechat.go",
    "chars": 15165,
    "preview": "package share\n\nimport (\n\t\"context\"\n\t\"encoding/json\"\n\t\"errors\"\n\t\"fmt\"\n\t\"io\"\n\t\"net/http\"\n\t\"strconv\"\n\n\t\"github.com/labstack"
  },
  {
    "path": "backend/handler/v1/app.go",
    "chars": 4299,
    "preview": "package v1\n\nimport (\n\t\"strconv\"\n\n\t\"github.com/labstack/echo/v4\"\n\n\t\"github.com/chaitin/panda-wiki/config\"\n\t\"github.com/ch"
  },
  {
    "path": "backend/handler/v1/auth.go",
    "chars": 3196,
    "preview": "package v1\n\nimport (\n\t\"github.com/labstack/echo/v4\"\n\n\tv1 \"github.com/chaitin/panda-wiki/api/auth/v1\"\n\t\"github.com/chaiti"
  },
  {
    "path": "backend/handler/v1/comment.go",
    "chars": 2768,
    "preview": "package v1\n\nimport (\n\t\"github.com/labstack/echo/v4\"\n\n\t\"github.com/chaitin/panda-wiki/consts\"\n\t\"github.com/chaitin/panda-"
  },
  {
    "path": "backend/handler/v1/conversation.go",
    "chars": 4912,
    "preview": "package v1\n\nimport (\n\t\"github.com/labstack/echo/v4\"\n\n\tv1 \"github.com/chaitin/panda-wiki/api/conversation/v1\"\n\t\"github.co"
  },
  {
    "path": "backend/handler/v1/crawler.go",
    "chars": 5408,
    "preview": "package v1\n\nimport (\n\t\"github.com/labstack/echo/v4\"\n\n\tv1 \"github.com/chaitin/panda-wiki/api/crawler/v1\"\n\t\"github.com/cha"
  },
  {
    "path": "backend/handler/v1/creation.go",
    "chars": 3139,
    "preview": "package v1\n\nimport (\n\t\"context\"\n\n\t\"github.com/labstack/echo/v4\"\n\n\t\"github.com/chaitin/panda-wiki/domain\"\n\t\"github.com/ch"
  },
  {
    "path": "backend/handler/v1/file.go",
    "chars": 4348,
    "preview": "package v1\n\nimport (\n\t\"fmt\"\n\t\"net/http\"\n\t\"strings\"\n\n\t\"github.com/google/uuid\"\n\t\"github.com/labstack/echo/v4\"\n\n\t\"github.c"
  },
  {
    "path": "backend/handler/v1/kb_user.go",
    "chars": 3986,
    "preview": "package v1\n\nimport (\n\t\"github.com/labstack/echo/v4\"\n\n\tv1 \"github.com/chaitin/panda-wiki/api/kb/v1\"\n\t\"github.com/chaitin/"
  },
  {
    "path": "backend/handler/v1/knowledge_base.go",
    "chars": 9107,
    "preview": "package v1\n\nimport (\n\t\"errors\"\n\n\t\"github.com/labstack/echo/v4\"\n\t\"github.com/samber/lo\"\n\n\t\"github.com/chaitin/panda-wiki/"
  },
  {
    "path": "backend/handler/v1/model.go",
    "chars": 8223,
    "preview": "package v1\n\nimport (\n\t\"github.com/google/uuid\"\n\t\"github.com/labstack/echo/v4\"\n\n\tmodelkitDomain \"github.com/chaitin/Model"
  },
  {
    "path": "backend/handler/v1/nav.go",
    "chars": 4871,
    "preview": "package v1\n\nimport (\n\t\"github.com/labstack/echo/v4\"\n\n\tv1 \"github.com/chaitin/panda-wiki/api/nav/v1\"\n\t\"github.com/chaitin"
  },
  {
    "path": "backend/handler/v1/node.go",
    "chars": 15358,
    "preview": "package v1\n\nimport (\n\t\"errors\"\n\n\t\"github.com/labstack/echo/v4\"\n\n\tv1 \"github.com/chaitin/panda-wiki/api/node/v1\"\n\t\"github"
  },
  {
    "path": "backend/handler/v1/provider.go",
    "chars": 1082,
    "preview": "package v1\n\nimport (\n\t\"github.com/google/wire\"\n\n\t\"github.com/chaitin/panda-wiki/handler\"\n\t\"github.com/chaitin/panda-wiki"
  },
  {
    "path": "backend/handler/v1/stat.go",
    "chars": 9364,
    "preview": "package v1\n\nimport (\n\t\"github.com/labstack/echo/v4\"\n\n\tv1 \"github.com/chaitin/panda-wiki/api/stat/v1\"\n\t\"github.com/chaiti"
  },
  {
    "path": "backend/handler/v1/user.go",
    "chars": 8570,
    "preview": "package v1\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\n\t\"github.com/google/uuid\"\n\t\"github.com/labstack/echo/v4\"\n\n\tv1 \"github.com/chaiti"
  },
  {
    "path": "backend/log/log.go",
    "chars": 805,
    "preview": "package log\n\nimport (\n\t\"log/slog\"\n\t\"os\"\n\n\t\"github.com/chaitin/panda-wiki/config\"\n)\n\ntype Logger struct {\n\t*slog.Logger\n}"
  },
  {
    "path": "backend/log/provider.go",
    "chars": 87,
    "preview": "package log\n\nimport \"github.com/google/wire\"\n\nvar ProviderSet = wire.NewSet(NewLogger)\n"
  },
  {
    "path": "backend/middleware/api_token.go",
    "chars": 204,
    "preview": "package middleware\n\nimport (\n\t\"context\"\n\n\t\"github.com/chaitin/panda-wiki/domain\"\n)\n\ntype APITokenRepository interface {\n"
  },
  {
    "path": "backend/middleware/auth.go",
    "chars": 934,
    "preview": "package middleware\n\nimport (\n\t\"fmt\"\n\n\t\"github.com/labstack/echo/v4\"\n\n\t\"github.com/chaitin/panda-wiki/config\"\n\t\"github.co"
  },
  {
    "path": "backend/middleware/jwt.go",
    "chars": 7831,
    "preview": "package middleware\n\nimport (\n\t\"bytes\"\n\t\"context\"\n\t\"encoding/json\"\n\t\"io\"\n\t\"net/http\"\n\t\"slices\"\n\t\"strings\"\n\n\t\"github.com/g"
  },
  {
    "path": "backend/middleware/provider.go",
    "chars": 178,
    "preview": "package middleware\n\nimport \"github.com/google/wire\"\n\nvar ProviderSet = wire.NewSet(\n\tNewAuthMiddleware,\n\tNewShareAuthMid"
  },
  {
    "path": "backend/middleware/readonly.go",
    "chars": 1344,
    "preview": "package middleware\n\nimport (\n\t\"os\"\n\t\"strings\"\n\n\t\"github.com/labstack/echo/v4\"\n\n\t\"github.com/chaitin/panda-wiki/domain\"\n\t"
  },
  {
    "path": "backend/middleware/session.go",
    "chars": 1432,
    "preview": "package middleware\n\nimport (\n\t\"context\"\n\t\"net/http\"\n\t\"time\"\n\n\t\"github.com/boj/redistore\"\n\t\"github.com/google/uuid\"\n\t\"git"
  },
  {
    "path": "backend/middleware/share_auth.go",
    "chars": 3459,
    "preview": "package middleware\n\nimport (\n\t\"net/http\"\n\n\t\"github.com/getsentry/sentry-go\"\n\t\"github.com/labstack/echo-contrib/session\"\n"
  },
  {
    "path": "backend/migration/fns/0001_migrate_node_version.go",
    "chars": 2549,
    "preview": "package fns\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\n\t\"github.com/samber/lo\"\n\t\"gorm.io/gorm\"\n\n\t\"github.com/chaitin/panda-wiki/domain"
  },
  {
    "path": "backend/migration/fns/0002_create_bot_auth.go",
    "chars": 3666,
    "preview": "package fns\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"time\"\n\n\t\"gorm.io/gorm\"\n\n\t\"github.com/chaitin/panda-wiki/domain\"\n\t\"github.com/c"
  },
  {
    "path": "backend/migration/fns/0003_fix_group_ids.go",
    "chars": 1957,
    "preview": "package fns\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\n\t\"github.com/chaitin/panda-wiki/consts\"\n\t\"github.com/chaitin/panda-wiki/domain\""
  },
  {
    "path": "backend/migration/fns/0004_update_node_status_unreleased.go",
    "chars": 978,
    "preview": "package fns\n\nimport (\n\t\"gorm.io/gorm\"\n\n\t\"github.com/chaitin/panda-wiki/domain\"\n\t\"github.com/chaitin/panda-wiki/log\"\n)\n\nt"
  },
  {
    "path": "backend/migration/fns/0005_create_first_nav_tabs.go",
    "chars": 1772,
    "preview": "package fns\n\nimport (\n\t\"errors\"\n\t\"time\"\n\n\t\"github.com/google/uuid\"\n\t\"gorm.io/gorm\"\n\n\t\"github.com/chaitin/panda-wiki/doma"
  },
  {
    "path": "backend/migration/fns/provider.go",
    "chars": 235,
    "preview": "package fns\n\nimport (\n\t\"github.com/google/wire\"\n)\n\nvar ProviderSet = wire.NewSet(\n\tNewMigrationNodeVersion,\n\tNewMigratio"
  },
  {
    "path": "backend/migration/func.go",
    "chars": 1157,
    "preview": "package migration\n\nimport (\n\t\"github.com/chaitin/panda-wiki/migration/fns\"\n)\n\ntype MigrationFuncs struct {\n\tNodeMigratio"
  },
  {
    "path": "backend/migration/manager.go",
    "chars": 2106,
    "preview": "package migration\n\nimport (\n\t\"fmt\"\n\t\"time\"\n\n\t\"gorm.io/gorm\"\n\n\t\"github.com/chaitin/panda-wiki/log\"\n\t\"github.com/chaitin/p"
  },
  {
    "path": "backend/migration/provider.go",
    "chars": 294,
    "preview": "package migration\n\nimport (\n\t\"github.com/google/wire\"\n\n\t\"github.com/chaitin/panda-wiki/migration/fns\"\n\t\"github.com/chait"
  },
  {
    "path": "backend/mq/mq.go",
    "chars": 1189,
    "preview": "package mq\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\n\t\"github.com/google/wire\"\n\n\t\"github.com/chaitin/panda-wiki/config\"\n\t\"github.com/"
  },
  {
    "path": "backend/mq/nats/consumer.go",
    "chars": 4092,
    "preview": "package nats\n\nimport (\n\t\"context\"\n\t\"sync\"\n\n\t\"github.com/nats-io/nats.go\"\n\n\t\"github.com/chaitin/panda-wiki/config\"\n\t\"gith"
  },
  {
    "path": "backend/mq/nats/message.go",
    "chars": 299,
    "preview": "package nats\n\nimport (\n\t\"github.com/nats-io/nats.go\"\n\n\t\"github.com/chaitin/panda-wiki/mq/types\"\n)\n\ntype Message struct {"
  },
  {
    "path": "backend/mq/nats/producer.go",
    "chars": 2841,
    "preview": "package nats\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"time\"\n\n\t\"github.com/nats-io/nats.go\"\n\n\t\"github.com/chaitin/panda-wiki/config\""
  },
  {
    "path": "backend/mq/types/message.go",
    "chars": 157,
    "preview": "package types\n\n// Message represents a generic message that can be from either Kafka or NATS\ntype Message interface {\n\tG"
  },
  {
    "path": "backend/pkg/anydoc/anydoc.go",
    "chars": 7885,
    "preview": "package anydoc\n\nimport (\n\t\"bytes\"\n\t\"context\"\n\t\"crypto/tls\"\n\t\"encoding/json\"\n\t\"errors\"\n\t\"fmt\"\n\t\"io\"\n\t\"net/http\"\n\t\"net/url"
  },
  {
    "path": "backend/pkg/anydoc/confluence.go",
    "chars": 3652,
    "preview": "package anydoc\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/url\"\n)\n\nconst (\n\t"
  },
  {
    "path": "backend/pkg/anydoc/dingtalk.go",
    "chars": 1543,
    "preview": "package anydoc\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/url\"\n)\n\nconst (\n\t"
  },
  {
    "path": "backend/pkg/anydoc/epub.go",
    "chars": 3902,
    "preview": "package anydoc\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/url\"\n)\n\nconst (\n\t"
  },
  {
    "path": "backend/pkg/anydoc/feishu.go",
    "chars": 4038,
    "preview": "package anydoc\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/url\"\n)\n\nconst (\n\t"
  },
  {
    "path": "backend/pkg/anydoc/mindoc.go",
    "chars": 3952,
    "preview": "package anydoc\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/url\"\n)\n\nconst (\n\t"
  },
  {
    "path": "backend/pkg/anydoc/notion.go",
    "chars": 3130,
    "preview": "package anydoc\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/url\"\n)\n\nconst (\n\t"
  },
  {
    "path": "backend/pkg/anydoc/req.go",
    "chars": 432,
    "preview": "package anydoc\n\ntype FeishuSetting struct {\n\tUserAccessToken string `json:\"user_access_token\"`\n\tAppID           string `"
  },
  {
    "path": "backend/pkg/anydoc/res.go",
    "chars": 1579,
    "preview": "package anydoc\n\ntype GetUrlListResponse struct {\n\tSuccess bool           `json:\"success\"`\n\tData    GetUrlListData `json:"
  },
  {
    "path": "backend/pkg/anydoc/rss.go",
    "chars": 3454,
    "preview": "package anydoc\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/url\"\n)\n\nconst (\n\t"
  },
  {
    "path": "backend/pkg/anydoc/sitemap.go",
    "chars": 3630,
    "preview": "package anydoc\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/url\"\n)\n\nconst (\n\t"
  },
  {
    "path": "backend/pkg/anydoc/siyuan.go",
    "chars": 3952,
    "preview": "package anydoc\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/url\"\n)\n\nconst (\n\t"
  },
  {
    "path": "backend/pkg/anydoc/wikijs.go",
    "chars": 3504,
    "preview": "package anydoc\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/url\"\n)\n\nconst (\n\t"
  },
  {
    "path": "backend/pkg/anydoc/yuque.go",
    "chars": 3872,
    "preview": "package anydoc\n\nimport (\n\t\"bytes\"\n\t\"context\"\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"io\"\n\t\"net/http\"\n\t\"net/url\"\n)\n\nconst (\n\tyuqueListP"
  },
  {
    "path": "backend/pkg/bot/common.go",
    "chars": 203,
    "preview": "package bot\n\nimport (\n\t\"context\"\n\n\t\"github.com/chaitin/panda-wiki/domain\"\n)\n\ntype GetQAFun func(ctx context.Context, msg"
  },
  {
    "path": "backend/pkg/bot/dingtalk/stream.go",
    "chars": 12033,
    "preview": "package dingtalk\n\nimport (\n\t\"bytes\"\n\t\"context\"\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"io\"\n\t\"net/http\"\n\t\"strings\"\n\t\"sync\"\n\t\"time\"\n\n\top"
  },
  {
    "path": "backend/pkg/bot/discord/discord_test.go",
    "chars": 693,
    "preview": "package discord\n\nimport (\n\t\"context\"\n\t\"testing\"\n\n\t\"github.com/chaitin/panda-wiki/config\"\n\t\"github.com/chaitin/panda-wiki"
  },
  {
    "path": "backend/pkg/bot/discord/stream.go",
    "chars": 2573,
    "preview": "package discord\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"strings\"\n\n\t\"github.com/chaitin/panda-wiki/domain\"\n\t\"github.com/chaitin/pan"
  },
  {
    "path": "backend/pkg/bot/feishu/stream.go",
    "chars": 9337,
    "preview": "package feishu\n\nimport (\n\t\"context\"\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"strings\"\n\t\"sync\"\n\t\"time\"\n\n\t\"github.com/google/uuid\"\n\tlark "
  },
  {
    "path": "backend/pkg/bot/lark/client.go",
    "chars": 11480,
    "preview": "package lark\n\nimport (\n\t\"context\"\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"regexp\"\n\t\"strings\"\n\t\"sync\"\n\t\"time\"\n\n\t\"github.com/google/uuid"
  },
  {
    "path": "backend/pkg/bot/utils/utils.go",
    "chars": 297,
    "preview": "package utils\n\nimport (\n\t\"github.com/russross/blackfriday/v2\"\n)\n\nfunc Markdown2HTML(md string) string {\n\treturn string(b"
  },
  {
    "path": "backend/pkg/bot/wechat/domain.go",
    "chars": 2483,
    "preview": "package wechat\n\nimport (\n\t\"context\"\n\t\"encoding/xml\"\n\t\"sync\"\n\t\"time\"\n\n\t\"github.com/chaitin/panda-wiki/log\"\n\t\"github.com/c"
  },
  {
    "path": "backend/pkg/bot/wechat/wechat.go",
    "chars": 10733,
    "preview": "package wechat\n\nimport (\n\t\"bytes\"\n\t\"context\"\n\t\"encoding/json\"\n\t\"encoding/xml\"\n\t\"errors\"\n\t\"fmt\"\n\t\"io\"\n\t\"net/http\"\n\t\"time\""
  },
  {
    "path": "backend/pkg/bot/wechat_official_account/official_account.go",
    "chars": 813,
    "preview": "package wechat_official_account\n\nimport (\n\t\"context\"\n\n\t\"github.com/silenceper/wechat/v2/officialaccount/user\"\n\n\t\"github."
  },
  {
    "path": "backend/pkg/bot/wechat_service/domain.go",
    "chars": 4842,
    "preview": "package wechat_service\n\nimport (\n\t\"context\"\n\t\"sync\"\n\t\"time\"\n\n\t\"github.com/chaitin/panda-wiki/log\"\n\t\"github.com/chaitin/p"
  },
  {
    "path": "backend/pkg/bot/wechat_service/tools.go",
    "chars": 8569,
    "preview": "package wechat_service\n\nimport (\n\t\"bytes\"\n\t\"encoding/base64\"\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"io\"\n\t\"mime/multipart\"\n\t\"net/http\""
  },
  {
    "path": "backend/pkg/bot/wechat_service/wechat.go",
    "chars": 11161,
    "preview": "package wechat_service\n\nimport (\n\t\"bytes\"\n\t\"context\"\n\t\"encoding/json\"\n\t\"encoding/xml\"\n\t\"errors\"\n\t\"fmt\"\n\t\"io\"\n\t\"net/http\""
  },
  {
    "path": "backend/pkg/bot/wecom/ai_bot.go",
    "chars": 3012,
    "preview": "package wecom\n\nimport (\n\t\"context\"\n\t\"encoding/json\"\n\n\t\"github.com/chaitin/panda-wiki/log\"\n)\n\n// AIBotClient 微信智能机器人\n// h"
  },
  {
    "path": "backend/pkg/bot/wecom/crypt.go",
    "chars": 10649,
    "preview": "// Package wecom provides cryptographic utilities for WeChat Work (WeCom) message encryption and decryption.\n// It imple"
  },
  {
    "path": "backend/pkg/captcha/captcha.go",
    "chars": 277,
    "preview": "package captcha\n\nimport gocap \"github.com/ackcoder/go-cap\"\n\ntype Captcha struct {\n\t*gocap.Cap\n}\n\nfunc NewCaptcha() *Capt"
  },
  {
    "path": "backend/pkg/cas/cas.go",
    "chars": 6089,
    "preview": "package cas\n\nimport (\n\t\"context\"\n\t\"crypto/tls\"\n\t\"encoding/xml\"\n\t\"fmt\"\n\t\"io\"\n\t\"net/http\"\n\t\"net/url\"\n\t\"strings\"\n\n\t\"github."
  },
  {
    "path": "backend/pkg/dingtalk/dingtalk.go",
    "chars": 10189,
    "preview": "package dingtalk\n\nimport (\n\t\"bytes\"\n\t\"context\"\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"io\"\n\t\"net/http\"\n\t\"net/url\"\n\t\"time\"\n\n\topenapi \"g"
  },
  {
    "path": "backend/pkg/feishu/feishu.go",
    "chars": 3406,
    "preview": "package feishu\n\nimport (\n\t\"context\"\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"net/http\"\n\t\"net/url\"\n\n\t\"golang.org/x/oauth2\"\n\n\t\"github.com"
  }
]

// ... and 981 more files (download for full content)

About this extraction

This page contains the full source code of the chaitin/PandaWiki GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 1181 files (6.3 MB), approximately 1.7M tokens, and a symbol index with 3392 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.

Copied to clipboard!