cx-chat 0.0.2 → 0.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cx-chat.css +1 -0
- package/dist/cx-chat.es.js +97326 -0
- package/dist/cx-chat.umd.js +734 -0
- package/package.json +21 -1
- package/.cursor/rules/i18n-cn-gloss-comments.mdc +0 -31
- package/.cursor/rules/list-page-view-pageconfig.mdc +0 -32
- package/.cursor/rules/no-over-defensive-programming.mdc +0 -90
- package/.cursor/rules/requirement-description-for-agent.mdc +0 -33
- package/.cursor/rules/use-showToast-not-antd-message.mdc +0 -28
- package/.docker/Dockerfile +0 -7
- package/.env +0 -9
- package/.env.development +0 -7
- package/.env.production +0 -7
- package/.gitlab-ci/docker-build.yaml +0 -28
- package/.gitlab-ci/k8s-deploy-dev-master.yaml +0 -42
- package/.gitlab-ci/npm-build.yaml +0 -17
- package/.gitlab-ci.yml +0 -8
- package/.k8s/0-namespace.yaml +0 -6
- package/.k8s/1-configmap-web.yaml +0 -7
- package/.k8s/1-nginx-conf-dev.yaml +0 -110
- package/.k8s/2-deployment.yaml +0 -27
- package/.k8s/3-service.yaml +0 -16
- package/.k8s/4-ingress-dev.yaml +0 -30
- package/.lingma/rules/use-showToast-not-antd-message.md +0 -34
- package/.nginx/nginx.conf +0 -52
- package/.prettierrc +0 -9
- package/eslint.config.js +0 -32
- package/index.html +0 -13
- package/postcss.config.js +0 -6
- package/src/App.tsx +0 -96
- package/src/_doc/0.docs-overview.md +0 -28
- package/src/_doc/cx-ui/0.docs-overview.md +0 -30
- package/src/_doc/cx-ui/comp.1.cx-ui-overview.md +0 -82
- package/src/_doc/cx-ui/comp.2.cx-modal.md +0 -82
- package/src/_doc/cx-ui/comp.3.cx-button.md +0 -89
- package/src/_doc/cx-ui/comp.4.cx-form.md +0 -72
- package/src/_doc/cx-ui/comp.5.cx-fields.md +0 -76
- package/src/_doc/cx-ui/comp.6.cx-tag.md +0 -57
- package/src/_doc/cx-ui/comp.7.cx-empty-state.md +0 -29
- package/src/_doc/meta/0.docs-overview.md +0 -24
- package/src/_doc/meta/comp.1.enum-runtime.md +0 -33
- package/src/_doc/meta/comp.2.dict-runtime.md +0 -39
- package/src/_doc/router/0.docs-overview.md +0 -14
- package/src/_doc/router/guide.1.menu-component-config.md +0 -181
- package/src/_doc/router/guide.2.router-auto-registration.md +0 -114
- package/src/_doc/table-view/0.docs-overview.md +0 -30
- package/src/_doc/table-view/comp.1.table-view.md +0 -542
- package/src/_doc/table-view/props.1.create-table-view-config.md +0 -193
- package/src/_doc/table-view/props.2.table-view-search-fields.md +0 -106
- package/src/api/_mock/README.md +0 -340
- package/src/api/_mock/api.ts +0 -1642
- package/src/api/_mock/bundle-shim.ts +0 -16
- package/src/api/_mock/handler-shim.ts +0 -6
- package/src/api/_mock/handler.ts +0 -458
- package/src/api/_mock/index.ts +0 -711
- package/src/api/_mock/interceptor.ts +0 -15
- package/src/api/_mock/mod.ts +0 -12
- package/src/api/_mock/utils.ts +0 -65
- package/src/api/base/memory.js +0 -24
- package/src/api/chat.js +0 -210
- package/src/api/common/auth.js +0 -70
- package/src/api/menus/business-rules.js +0 -76
- package/src/api/menus/feedback.js +0 -102
- package/src/api/menus/knowledge.js +0 -159
- package/src/api/menus/model-metadata/manage.js +0 -70
- package/src/api/menus/model-metadata/role.js +0 -50
- package/src/api/menus/model-metadata/training-detail-mock-data.js +0 -569
- package/src/api/menus/model-metadata/training.js +0 -28
- package/src/api/menus/skill.js +0 -40
- package/src/api/system/agent-config.js +0 -16
- package/src/api/system/department.js +0 -94
- package/src/api/system/dict.js +0 -86
- package/src/api/system/menu.js +0 -37
- package/src/api/system/permission.js +0 -26
- package/src/api/system/role.js +0 -34
- package/src/api/system/sys-config.js +0 -16
- package/src/api/system/sys-log.js +0 -17
- package/src/api/system/user.js +0 -75
- package/src/api/upload.js +0 -39
- package/src/assets/react.svg +0 -1
- package/src/components/auth/current-user-avatar.tsx +0 -77
- package/src/components/common/code-view.tsx +0 -149
- package/src/components/common/detail-link.tsx +0 -67
- package/src/components/common/error-boundary.tsx +0 -98
- package/src/components/common/language-switcher.tsx +0 -91
- package/src/components/common/lite-table/index.tsx +0 -135
- package/src/components/common/md-editor.tsx +0 -126
- package/src/components/common/modal/confirm-dialog.tsx +0 -113
- package/src/components/common/modal/dep-user-select-multi.tsx +0 -324
- package/src/components/common/modal/dep-user-select.tsx +0 -249
- package/src/components/common/modal/user-select-multi.tsx +0 -266
- package/src/components/common/pagination.tsx +0 -472
- package/src/components/common/path.tsx +0 -175
- package/src/components/common/system-logo-mark.tsx +0 -48
- package/src/components/cx-ui/button/index.less +0 -208
- package/src/components/cx-ui/button/index.tsx +0 -611
- package/src/components/cx-ui/checkbox/index.tsx +0 -78
- package/src/components/cx-ui/date-picker/index.less +0 -17
- package/src/components/cx-ui/date-picker/index.tsx +0 -193
- package/src/components/cx-ui/drawer/index.tsx +0 -47
- package/src/components/cx-ui/empty-state/index.tsx +0 -20
- package/src/components/cx-ui/floating-shell/CxFloatingShell.tsx +0 -89
- package/src/components/cx-ui/floating-shell/cx-floating-shell.less +0 -283
- package/src/components/cx-ui/floating-shell/has-floating-value.ts +0 -41
- package/src/components/cx-ui/form/CxForm.tsx +0 -15
- package/src/components/cx-ui/form/index.tsx +0 -20
- package/src/components/cx-ui/form-item/index.less +0 -26
- package/src/components/cx-ui/form-item/index.tsx +0 -36
- package/src/components/cx-ui/index.ts +0 -70
- package/src/components/cx-ui/input/auto-complete.tsx +0 -134
- package/src/components/cx-ui/input/index.tsx +0 -259
- package/src/components/cx-ui/input-number/index.jsx +0 -66
- package/src/components/cx-ui/modal/index.jsx +0 -212
- package/src/components/cx-ui/modal/index.less +0 -144
- package/src/components/cx-ui/modal/useCxModal.ts +0 -125
- package/src/components/cx-ui/multi-select/index.jsx +0 -74
- package/src/components/cx-ui/multi-select/index.less +0 -40
- package/src/components/cx-ui/multi-select/index2.tsx +0 -361
- package/src/components/cx-ui/radio/index.tsx +0 -33
- package/src/components/cx-ui/range-picker/index.less +0 -65
- package/src/components/cx-ui/range-picker/index.tsx +0 -219
- package/src/components/cx-ui/select/index.less +0 -34
- package/src/components/cx-ui/select/index.tsx +0 -196
- package/src/components/cx-ui/skeleton/index.tsx +0 -12
- package/src/components/cx-ui/steps/index.tsx +0 -14
- package/src/components/cx-ui/styles/_tokens.less +0 -79
- package/src/components/cx-ui/styles/index.less +0 -246
- package/src/components/cx-ui/switch/index.less +0 -106
- package/src/components/cx-ui/switch/index.tsx +0 -120
- package/src/components/cx-ui/table/index.less +0 -160
- package/src/components/cx-ui/table/index.tsx +0 -152
- package/src/components/cx-ui/tabs/index.less +0 -15
- package/src/components/cx-ui/tabs/index.tsx +0 -34
- package/src/components/cx-ui/tag/index.less +0 -51
- package/src/components/cx-ui/tag/index.tsx +0 -140
- package/src/components/cx-ui/timeline/index.tsx +0 -14
- package/src/components/cx-ui/tooltip/index.tsx +0 -67
- package/src/components/cx-ui/tree/index.tsx +0 -193
- package/src/components/cx-ui/tree-select/index.jsx +0 -91
- package/src/components/cx-ui/tree-select/index.less +0 -27
- package/src/components/cx-ui/upload-file/index.less +0 -223
- package/src/components/cx-ui/upload-file/index.tsx +0 -640
- package/src/components/cx-ui/upload-img/index.tsx +0 -291
- package/src/components/layout/components/Header.tsx +0 -216
- package/src/components/layout/components/Sidebar.tsx +0 -717
- package/src/components/layout/index.tsx +0 -95
- package/src/components/table-view/components/search-area.tsx +0 -411
- package/src/components/table-view/components/table-view-config.tsx +0 -528
- package/src/components/table-view/components/table-view.types.ts +0 -478
- package/src/components/table-view/components/tree-api-normalize.ts +0 -38
- package/src/components/table-view/components/tree-data-annotate.ts +0 -31
- package/src/components/table-view/components/tree-sidebar.tsx +0 -74
- package/src/components/table-view/index.tsx +0 -61
- package/src/components/table-view/list-page-view.tsx +0 -1049
- package/src/components/table-view/select-table-view.tsx +0 -1094
- package/src/components/table-view/styles/select-table-view.less +0 -51
- package/src/config/default-system-name.ts +0 -9
- package/src/config/system.ts +0 -165
- package/src/constants/countryCodes.ts +0 -3
- package/src/contexts/AuthContext.tsx +0 -256
- package/src/contexts/ChatContext.tsx +0 -839
- package/src/contexts/MenuContext.tsx +0 -62
- package/src/contexts/ToastContext.tsx +0 -181
- package/src/hooks/useCopyToClipboard.ts +0 -47
- package/src/hooks/useModalSubmit.ts +0 -104
- package/src/hooks/useRouter.ts +0 -240
- package/src/hooks/useStepForm.ts +0 -46
- package/src/hooks/useStickyHeader.ts +0 -42
- package/src/hooks/useThreadActions.ts +0 -105
- package/src/hooks/useUserPreferences.ts +0 -101
- package/src/http/axios.js +0 -372
- package/src/http/mock.interceptor.ts +0 -9
- package/src/http/obfuscationKey.ts +0 -41
- package/src/i18n.ts +0 -60
- package/src/index.js +0 -1
- package/src/index.less +0 -169
- package/src/locales/en/auth.ts +0 -70
- package/src/locales/en/base/memory.ts +0 -28
- package/src/locales/en/base/settings.ts +0 -41
- package/src/locales/en/chat.ts +0 -40
- package/src/locales/en/common.ts +0 -173
- package/src/locales/en/enum.ts +0 -27
- package/src/locales/en/menus/business-rules.ts +0 -48
- package/src/locales/en/menus/feedback.ts +0 -62
- package/src/locales/en/menus/knowledge.ts +0 -120
- package/src/locales/en/menus/model-metadata/index.ts +0 -10
- package/src/locales/en/menus/model-metadata/manage.ts +0 -151
- package/src/locales/en/menus/model-metadata/role.ts +0 -48
- package/src/locales/en/menus/model-metadata/training.ts +0 -65
- package/src/locales/en/menus/skill.ts +0 -34
- package/src/locales/en/system/agent-config.ts +0 -34
- package/src/locales/en/system/department.ts +0 -68
- package/src/locales/en/system/dict.ts +0 -44
- package/src/locales/en/system/menu.ts +0 -45
- package/src/locales/en/system/permission.ts +0 -89
- package/src/locales/en/system/role.ts +0 -25
- package/src/locales/en/system/sys-config.ts +0 -33
- package/src/locales/en/system/sys-log.ts +0 -38
- package/src/locales/en/system/user.ts +0 -113
- package/src/locales/en.ts +0 -68
- package/src/locales/zh/auth.ts +0 -70
- package/src/locales/zh/base/memory.ts +0 -29
- package/src/locales/zh/base/settings.ts +0 -41
- package/src/locales/zh/chat.ts +0 -47
- package/src/locales/zh/common.ts +0 -178
- package/src/locales/zh/enum.ts +0 -28
- package/src/locales/zh/menus/business-rules.ts +0 -47
- package/src/locales/zh/menus/feedback.ts +0 -62
- package/src/locales/zh/menus/knowledge.ts +0 -117
- package/src/locales/zh/menus/model-metadata/index.ts +0 -10
- package/src/locales/zh/menus/model-metadata/manage.ts +0 -151
- package/src/locales/zh/menus/model-metadata/role.ts +0 -47
- package/src/locales/zh/menus/model-metadata/training.ts +0 -64
- package/src/locales/zh/menus/skill.ts +0 -34
- package/src/locales/zh/system/agent-config.ts +0 -33
- package/src/locales/zh/system/department.ts +0 -69
- package/src/locales/zh/system/dict.ts +0 -44
- package/src/locales/zh/system/menu.ts +0 -47
- package/src/locales/zh/system/permission.ts +0 -94
- package/src/locales/zh/system/role.ts +0 -25
- package/src/locales/zh/system/sys-config.ts +0 -32
- package/src/locales/zh/system/sys-log.ts +0 -38
- package/src/locales/zh/system/user.ts +0 -114
- package/src/locales/zh.ts +0 -67
- package/src/main.tsx +0 -50
- package/src/meta/const/index.ts +0 -40
- package/src/meta/index-dict.ts +0 -56
- package/src/meta/index-enum.ts +0 -95
- package/src/meta/index.ts +0 -14
- package/src/meta/module/dict-data/runtime.ts +0 -199
- package/src/meta/module/dict-data/types.ts +0 -17
- package/src/meta/module/enum-data/runtime.ts +0 -75
- package/src/meta/module/enum-data/types.ts +0 -18
- package/src/router/index.tsx +0 -312
- package/src/styles/AntdThemeProvider.tsx +0 -40
- package/src/styles/antd-theme.ts +0 -20
- package/src/styles/global.less +0 -107
- package/src/styles/variable.less +0 -103
- package/src/types/feedback.ts +0 -43
- package/src/types/index.ts +0 -85
- package/src/types/menu.ts +0 -43
- package/src/utils/aesUtil.ts +0 -123
- package/src/utils/chatUtils.ts +0 -524
- package/src/utils/cn.ts +0 -6
- package/src/utils/crypto.ts +0 -164
- package/src/utils/date.ts +0 -72
- package/src/utils/file-icons.tsx +0 -79
- package/src/utils/index.ts +0 -168
- package/src/utils/markdown-math-plugins.ts +0 -21
- package/src/utils/menuI18n.ts +0 -305
- package/src/utils/menuRouteRegistry.ts +0 -78
- package/src/utils/permission-crud.ts +0 -147
- package/src/utils/routeConfig.ts +0 -350
- package/src/utils/storage.ts +0 -135
- package/src/utils/toastBridge.ts +0 -26
- package/src/utils/url.ts +0 -38
- package/src/utils/validation.ts +0 -16
- package/src/views/auth/auth-code/index.less +0 -169
- package/src/views/auth/auth-code/index.module.less +0 -174
- package/src/views/auth/auth-code/index.tsx +0 -233
- package/src/views/auth/login.tsx +0 -498
- package/src/views/auth/register.tsx +0 -388
- package/src/views/base/memory/index.tsx +0 -136
- package/src/views/base/memory/modal/detail-modal.tsx +0 -89
- package/src/views/base/memory/modal/submit-modal.tsx +0 -134
- package/src/views/base/settings/index.tsx +0 -657
- package/src/views/chat/chat.less +0 -323
- package/src/views/chat/components/chat-input.tsx +0 -298
- package/src/views/chat/components/header-thread-title.tsx +0 -210
- package/src/views/chat/components/message-list/content-answer.tsx +0 -100
- package/src/views/chat/components/message-list/content-question.tsx +0 -18
- package/src/views/chat/components/message-list/index.tsx +0 -520
- package/src/views/chat/components/message-list/message-item.tsx +0 -199
- package/src/views/chat/components/message-list/preparation-demo-items.ts +0 -147
- package/src/views/chat/components/message-list/preparation-steps.tsx +0 -506
- package/src/views/chat/components/message-list/suggestion-list.tsx +0 -36
- package/src/views/chat/components/message-list/thinking-process.tsx +0 -49
- package/src/views/chat/components/message-list/toolbar.tsx +0 -224
- package/src/views/chat/components/message-list/use-message-list-scroll.ts +0 -214
- package/src/views/chat/components/references-knowledge/context.tsx +0 -57
- package/src/views/chat/components/references-knowledge/index.ts +0 -9
- package/src/views/chat/components/references-knowledge/modal/knowledge-detail-drawer.tsx +0 -556
- package/src/views/chat/components/references-knowledge/modal/knowledge-doc-detail-drawer.tsx +0 -529
- package/src/views/chat/components/references-knowledge/panel.tsx +0 -115
- package/src/views/chat/hooks/use-chat-common.ts +0 -19
- package/src/views/chat/index-session.tsx +0 -647
- package/src/views/chat/index.tsx +0 -127
- package/src/views/page-error/401.tsx +0 -56
- package/src/views/page-error/404.tsx +0 -56
- package/src/views/page-menus/business-rules/index.tsx +0 -376
- package/src/views/page-menus/business-rules/modal/detail-modal.tsx +0 -186
- package/src/views/page-menus/business-rules/modal/scope-modal.tsx +0 -272
- package/src/views/page-menus/business-rules/modal/submit-modal.tsx +0 -142
- package/src/views/page-menus/feedback/components/feedback-dataset-list.tsx +0 -471
- package/src/views/page-menus/feedback/index.tsx +0 -166
- package/src/views/page-menus/feedback/modal/export-feedback-modal.tsx +0 -367
- package/src/views/page-menus/knowledge/components/doc-editor-by-type.tsx +0 -32
- package/src/views/page-menus/knowledge/components/doc-editor-type-file.tsx +0 -330
- package/src/views/page-menus/knowledge/detail.tsx +0 -600
- package/src/views/page-menus/knowledge/index.tsx +0 -337
- package/src/views/page-menus/knowledge/modal/detail-modal.tsx +0 -618
- package/src/views/page-menus/knowledge/modal/doc-detail-modal.tsx +0 -550
- package/src/views/page-menus/knowledge/modal/doc-parse.ts +0 -99
- package/src/views/page-menus/knowledge/modal/doc-submit-modal.tsx +0 -349
- package/src/views/page-menus/knowledge/modal/doc-type-picker-modal.tsx +0 -88
- package/src/views/page-menus/knowledge/modal/knowledge-user-select-modal.tsx +0 -283
- package/src/views/page-menus/knowledge/modal/submit-modal.tsx +0 -179
- package/src/views/page-menus/model-metadata/manage/components/metadata-detail-schema-tab.tsx +0 -114
- package/src/views/page-menus/model-metadata/manage/components/step1-basic-info.tsx +0 -232
- package/src/views/page-menus/model-metadata/manage/components/step2-schema.tsx +0 -316
- package/src/views/page-menus/model-metadata/manage/components/step3-permissions.tsx +0 -134
- package/src/views/page-menus/model-metadata/manage/components/step4-documents.tsx +0 -134
- package/src/views/page-menus/model-metadata/manage/components/step5-example-sql.tsx +0 -101
- package/src/views/page-menus/model-metadata/manage/components/submit-add.tsx +0 -338
- package/src/views/page-menus/model-metadata/manage/components/submit-edit.tsx +0 -276
- package/src/views/page-menus/model-metadata/manage/detail.tsx +0 -298
- package/src/views/page-menus/model-metadata/manage/hooks/model-metadata-submit-shared.ts +0 -113
- package/src/views/page-menus/model-metadata/manage/hooks/use-model-metadata-item-state.ts +0 -20
- package/src/views/page-menus/model-metadata/manage/index.tsx +0 -304
- package/src/views/page-menus/model-metadata/manage/modal/components/table-schema.ts +0 -374
- package/src/views/page-menus/model-metadata/manage/modal/components/use-table-detail-tabs.tsx +0 -151
- package/src/views/page-menus/model-metadata/manage/modal/components/use-table-submit-tabs.tsx +0 -423
- package/src/views/page-menus/model-metadata/manage/modal/detail-modal.tsx +0 -218
- package/src/views/page-menus/model-metadata/manage/modal/submit-modal.tsx +0 -261
- package/src/views/page-menus/model-metadata/manage/modal/table-detail-modal.tsx +0 -196
- package/src/views/page-menus/model-metadata/manage/modal/table-submit-modal.tsx +0 -229
- package/src/views/page-menus/model-metadata/manage/submit.tsx +0 -31
- package/src/views/page-menus/model-metadata/role/index.tsx +0 -207
- package/src/views/page-menus/model-metadata/role/modal/detail-modal.tsx +0 -97
- package/src/views/page-menus/model-metadata/role/modal/role-assign-users-modal.tsx +0 -254
- package/src/views/page-menus/model-metadata/role/modal/role-assign-users-panel.tsx +0 -393
- package/src/views/page-menus/model-metadata/role/modal/role-assign-users-utils.ts +0 -120
- package/src/views/page-menus/model-metadata/role/modal/role-permission-assign-panel.tsx +0 -698
- package/src/views/page-menus/model-metadata/role/modal/role-permission-modal.tsx +0 -237
- package/src/views/page-menus/model-metadata/role/modal/submit-modal.tsx +0 -135
- package/src/views/page-menus/model-metadata/training/components/detail-records/index.ts +0 -4
- package/src/views/page-menus/model-metadata/training/components/detail-records/node-card.tsx +0 -72
- package/src/views/page-menus/model-metadata/training/components/detail-records/summary-lines.ts +0 -196
- package/src/views/page-menus/model-metadata/training/components/detail-records/summary-list.tsx +0 -153
- package/src/views/page-menus/model-metadata/training/components/detail-records/timeline.tsx +0 -103
- package/src/views/page-menus/model-metadata/training/components/detail-records/types.ts +0 -82
- package/src/views/page-menus/model-metadata/training/detail.tsx +0 -159
- package/src/views/page-menus/model-metadata/training/index.tsx +0 -236
- package/src/views/page-menus/model-metadata/training/modal/update-detail-modal.tsx +0 -154
- package/src/views/page-menus/skill/index.tsx +0 -201
- package/src/views/page-menus/skill/modal/detail-modal.tsx +0 -156
- package/src/views/page-menus/skill/modal/submit-modal.tsx +0 -214
- package/src/views/page-system/agent-config/index.tsx +0 -370
- package/src/views/page-system/department/departmentFormShared.ts +0 -36
- package/src/views/page-system/department/index.tsx +0 -541
- package/src/views/page-system/department/modal/detail-modal.tsx +0 -94
- package/src/views/page-system/department/modal/member-role-modal.tsx +0 -128
- package/src/views/page-system/department/modal/submit-modal.tsx +0 -265
- package/src/views/page-system/dict/index.tsx +0 -440
- package/src/views/page-system/dict/modal/cate-submit-modal.tsx +0 -315
- package/src/views/page-system/dict/modal/submit-modal.tsx +0 -184
- package/src/views/page-system/logs/components/index.ts +0 -3
- package/src/views/page-system/logs/components/log-message-demo.tsx +0 -30
- package/src/views/page-system/logs/components/log-message-stream.ts +0 -184
- package/src/views/page-system/logs/components/message-list/content-answer.tsx +0 -100
- package/src/views/page-system/logs/components/message-list/content-question.tsx +0 -18
- package/src/views/page-system/logs/components/message-list/index.tsx +0 -515
- package/src/views/page-system/logs/components/message-list/message-item.tsx +0 -193
- package/src/views/page-system/logs/components/message-list/preparation-demo-items.ts +0 -147
- package/src/views/page-system/logs/components/message-list/preparation-steps.tsx +0 -506
- package/src/views/page-system/logs/components/message-list/suggestion-list.tsx +0 -36
- package/src/views/page-system/logs/components/message-list/thinking-process.tsx +0 -49
- package/src/views/page-system/logs/components/message-list/toolbar.tsx +0 -134
- package/src/views/page-system/logs/components/message-list/use-message-list-scroll.ts +0 -214
- package/src/views/page-system/logs/components/message-modal.tsx +0 -239
- package/src/views/page-system/logs/index.tsx +0 -132
- package/src/views/page-system/logs/modal/detail-modal.tsx +0 -157
- package/src/views/page-system/menu/components/menuFormShared.ts +0 -283
- package/src/views/page-system/menu/index.less +0 -12
- package/src/views/page-system/menu/index.tsx +0 -410
- package/src/views/page-system/menu/modal/icon-modal.less +0 -51
- package/src/views/page-system/menu/modal/icon-modal.tsx +0 -87
- package/src/views/page-system/menu/modal/submit-modal.tsx +0 -263
- package/src/views/page-system/permission/index.tsx +0 -562
- package/src/views/page-system/permission/modal/detail-modal.tsx +0 -179
- package/src/views/page-system/permission/modal/submit-modal.less +0 -146
- package/src/views/page-system/permission/modal/submit-modal.tsx +0 -650
- package/src/views/page-system/role/index.tsx +0 -163
- package/src/views/page-system/role/modal/detail-modal.tsx +0 -127
- package/src/views/page-system/role/modal/permission-assign-group-rules.ts +0 -86
- package/src/views/page-system/role/modal/permission-modal.tsx +0 -111
- package/src/views/page-system/role/modal/role-modal-shell-styles.ts +0 -21
- package/src/views/page-system/role/modal/role-permission-assign-panel.tsx +0 -916
- package/src/views/page-system/role/modal/role-permission-assign-shared.ts +0 -1047
- package/src/views/page-system/role/modal/submit-modal.tsx +0 -193
- package/src/views/page-system/sys-config/index.tsx +0 -294
- package/src/views/page-system/user/components/user-role-column.tsx +0 -87
- package/src/views/page-system/user/index.tsx +0 -439
- package/src/views/page-system/user/modal/assign-roles-modal.tsx +0 -389
- package/src/views/page-system/user/modal/detail-modal.tsx +0 -72
- package/src/views/page-system/user/modal/modal-style/submit-modal.less +0 -40
- package/src/views/page-system/user/modal/submit-modal.less +0 -40
- package/src/views/page-system/user/modal/submit-modal.tsx +0 -287
- package/src/views/page-system/user/userFormShared.ts +0 -51
- package/tailwind.config.js +0 -17
- package/tsconfig.app.json +0 -48
- package/tsconfig.json +0 -11
- package/tsconfig.node.json +0 -26
- package/vite.config.ts +0 -272
- /package/{public → dist}/favicon.ico +0 -0
- /package/{public → dist}/vite.svg +0 -0
package/src/utils/chatUtils.ts
DELETED
|
@@ -1,524 +0,0 @@
|
|
|
1
|
-
import type { Message, Thread } from '@/types';
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* 聊天工具:后端 Result / VO → 前端 Thread、Message 等模型(纯函数)。
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
/** 解开 Result 包裹:仅当业务 code === 200 时取 data */
|
|
8
|
-
export function unwrapChatApiBody(raw: unknown): unknown {
|
|
9
|
-
if (raw && typeof raw === 'object' && 'code' in raw) {
|
|
10
|
-
const o = raw as { code?: number; data?: unknown }
|
|
11
|
-
if (o.code === 200 && o.data !== undefined) return o.data
|
|
12
|
-
}
|
|
13
|
-
return raw
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
export function parseNewSessionId(raw: unknown): string {
|
|
17
|
-
const body = unwrapChatApiBody(raw)
|
|
18
|
-
if (typeof body === 'string' && body.trim()) return body.trim()
|
|
19
|
-
if (body && typeof body === 'object') {
|
|
20
|
-
const o = body as Record<string, unknown>
|
|
21
|
-
const id = o.sessionId ?? o.session_id ?? o.id
|
|
22
|
-
if (typeof id === 'string' && id) return id
|
|
23
|
-
if (id != null && id !== '') return String(id)
|
|
24
|
-
}
|
|
25
|
-
throw new Error('Invalid session-id response')
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
/** 从路由 `/chat/:sessionId` 解析会话 id(与 `encodeURIComponent` 后的路径一致);非会话页返回 null */
|
|
29
|
-
export function parseChatSessionIdFromPathname(pathname: string): string | null {
|
|
30
|
-
const m = pathname.match(/^\/chat\/([^/]+)\/?$/)
|
|
31
|
-
if (!m?.[1]) return null
|
|
32
|
-
try {
|
|
33
|
-
return decodeURIComponent(m[1])
|
|
34
|
-
} catch {
|
|
35
|
-
return m[1]
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
function coerceChatPromptItemsToStrings(items: unknown[]): string[] {
|
|
40
|
-
const out: string[] = []
|
|
41
|
-
for (const x of items) {
|
|
42
|
-
if (typeof x === 'string') {
|
|
43
|
-
const s = x.trim()
|
|
44
|
-
if (s) out.push(s)
|
|
45
|
-
continue
|
|
46
|
-
}
|
|
47
|
-
if (x && typeof x === 'object') {
|
|
48
|
-
const o = x as Record<string, unknown>
|
|
49
|
-
const t =
|
|
50
|
-
o.text ?? o.title ?? o.label ?? o.prompt ?? o.content ?? o.name
|
|
51
|
-
if (typeof t === 'string' && t.trim()) out.push(t.trim())
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
return out
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
/**
|
|
58
|
-
* 解析「会话搜索建议」接口体:`data` 常为 JSON 字符串,解析失败或非数组则返回 []。
|
|
59
|
-
* 支持数组、或对象内 items / suggestions / list / prompts / options 等数组字段。
|
|
60
|
-
*/
|
|
61
|
-
export function parseChatSessionPromptSuggestions(raw: unknown): string[] {
|
|
62
|
-
let node: unknown = unwrapChatApiBody(raw)
|
|
63
|
-
|
|
64
|
-
if (node && typeof node === 'object') {
|
|
65
|
-
const o = node as Record<string, unknown>
|
|
66
|
-
const rawData = o.data
|
|
67
|
-
if (typeof rawData === 'string') {
|
|
68
|
-
const s = rawData.trim()
|
|
69
|
-
if (!s) return []
|
|
70
|
-
try {
|
|
71
|
-
node = JSON.parse(s) as unknown
|
|
72
|
-
} catch {
|
|
73
|
-
return []
|
|
74
|
-
}
|
|
75
|
-
} else if (rawData !== undefined && rawData !== null) {
|
|
76
|
-
node = rawData
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
if (node == null) return []
|
|
81
|
-
if (Array.isArray(node)) {
|
|
82
|
-
return coerceChatPromptItemsToStrings(node)
|
|
83
|
-
}
|
|
84
|
-
if (typeof node === 'string') {
|
|
85
|
-
const s = node.trim()
|
|
86
|
-
if (!s) return []
|
|
87
|
-
try {
|
|
88
|
-
const parsed = JSON.parse(s) as unknown
|
|
89
|
-
return parseChatSessionPromptSuggestions(parsed)
|
|
90
|
-
} catch {
|
|
91
|
-
return [s]
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
if (typeof node === 'object') {
|
|
95
|
-
const o = node as Record<string, unknown>
|
|
96
|
-
const keys = [
|
|
97
|
-
'items',
|
|
98
|
-
'suggestions',
|
|
99
|
-
'list',
|
|
100
|
-
'prompts',
|
|
101
|
-
'options',
|
|
102
|
-
] as const
|
|
103
|
-
for (const k of keys) {
|
|
104
|
-
const v = o[k]
|
|
105
|
-
if (Array.isArray(v)) return coerceChatPromptItemsToStrings(v)
|
|
106
|
-
}
|
|
107
|
-
if (typeof o.prompt === 'string' && o.prompt.trim()) {
|
|
108
|
-
return [o.prompt.trim()]
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
return []
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
/** 从后往前第一条非 system 消息 */
|
|
115
|
-
export function findLastNonSystemMessage(messages: Message[]): Message | null {
|
|
116
|
-
for (let i = messages.length - 1; i >= 0; i -= 1) {
|
|
117
|
-
const m = messages[i]
|
|
118
|
-
if (m.role !== 'system') return m
|
|
119
|
-
}
|
|
120
|
-
return null
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
/** 从后往前第一条助手消息 */
|
|
124
|
-
export function findLastAssistantMessage(messages: Message[]): Message | null {
|
|
125
|
-
for (let i = messages.length - 1; i >= 0; i -= 1) {
|
|
126
|
-
const m = messages[i]
|
|
127
|
-
if (m.role === 'assistant') return m
|
|
128
|
-
}
|
|
129
|
-
return null
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
/**
|
|
133
|
-
* 把某次「搜索建议」接口结果绑到指定助手 messageId 的 options(与 suggested_replies 同槽展示);
|
|
134
|
-
* 仅当该条仍是当前列表中的最后一条助手、且线程末尾为该助手时写入,避免挂在新提问/流式占位上。
|
|
135
|
-
* 不与已有 suggested_replies 叠加:该条已有非空 options 时保持原样,避免两类建议合并成一长串。
|
|
136
|
-
*/
|
|
137
|
-
export function applySessionPromptBinding(
|
|
138
|
-
messages: Message[],
|
|
139
|
-
binding: { messageId: string; items: string[] } | null,
|
|
140
|
-
): Message[] {
|
|
141
|
-
if (!binding?.items.length) return messages
|
|
142
|
-
const tail = findLastNonSystemMessage(messages)
|
|
143
|
-
if (tail?.role !== 'assistant' || tail.id !== binding.messageId) {
|
|
144
|
-
return messages
|
|
145
|
-
}
|
|
146
|
-
const lastAsst = findLastAssistantMessage(messages)
|
|
147
|
-
if (!lastAsst || lastAsst.id !== binding.messageId) return messages
|
|
148
|
-
return messages.map((m) => {
|
|
149
|
-
if (m.id !== binding.messageId) return m
|
|
150
|
-
const existing = m.options ?? []
|
|
151
|
-
if (existing.length > 0) return m
|
|
152
|
-
return { ...m, options: [...binding.items] }
|
|
153
|
-
})
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
/** 流式新会话:接口列表尚未含该会话时,将乐观占位行插回列表(与 ChatContext.streamingPlaceholderThread 配合) */
|
|
157
|
-
export function mergeStreamingPlaceholderThread(
|
|
158
|
-
threads: Thread[],
|
|
159
|
-
opts: {
|
|
160
|
-
placeholder: Thread | null
|
|
161
|
-
activeThreadId: string | null
|
|
162
|
-
isStreaming: boolean
|
|
163
|
-
},
|
|
164
|
-
): Thread[] {
|
|
165
|
-
const { placeholder, activeThreadId, isStreaming } = opts
|
|
166
|
-
const base = [...threads]
|
|
167
|
-
if (
|
|
168
|
-
placeholder &&
|
|
169
|
-
activeThreadId &&
|
|
170
|
-
placeholder.id === activeThreadId &&
|
|
171
|
-
isStreaming &&
|
|
172
|
-
!base.some((x) => x.id === placeholder.id)
|
|
173
|
-
) {
|
|
174
|
-
return [placeholder, ...base]
|
|
175
|
-
}
|
|
176
|
-
return base
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
/** ChatSessionVO → Thread */
|
|
180
|
-
export function normalizeSessionsToThreads(raw: unknown): Thread[] {
|
|
181
|
-
const body = unwrapChatApiBody(raw)
|
|
182
|
-
let list: unknown[] = []
|
|
183
|
-
if (Array.isArray(body)) list = body
|
|
184
|
-
else if (body && typeof body === 'object') {
|
|
185
|
-
const o = body as Record<string, unknown>
|
|
186
|
-
if (Array.isArray(o.list)) list = o.list
|
|
187
|
-
else if (Array.isArray(o.items)) list = o.items
|
|
188
|
-
else if (Array.isArray(o.sessions)) list = o.sessions
|
|
189
|
-
else if (Array.isArray(o.data)) list = o.data
|
|
190
|
-
}
|
|
191
|
-
return list
|
|
192
|
-
.map((item): Thread | null => {
|
|
193
|
-
if (!item || typeof item !== 'object') return null
|
|
194
|
-
const s = item as Record<string, unknown>
|
|
195
|
-
const id = s.sessionId ?? s.session_id ?? s.id
|
|
196
|
-
if (id == null || id === '') return null
|
|
197
|
-
const createTime = String(s.createTime ?? s.create_time ?? '')
|
|
198
|
-
const topN = Number(s.topStatus ?? s.top_status)
|
|
199
|
-
const top_status = topN === 1 ? 1 : 0
|
|
200
|
-
return {
|
|
201
|
-
id: String(id),
|
|
202
|
-
title: String(s.title ?? ''),
|
|
203
|
-
created_at: createTime,
|
|
204
|
-
updated_at: String(s.updateTime ?? s.updated_at ?? createTime),
|
|
205
|
-
user_id: String(s.userId ?? s.user_id ?? ''),
|
|
206
|
-
top_status,
|
|
207
|
-
}
|
|
208
|
-
})
|
|
209
|
-
.filter((x): x is Thread => x !== null)
|
|
210
|
-
}
|
|
211
|
-
|
|
212
|
-
/** 列表展示:是否已赞 */
|
|
213
|
-
export function messageLikeActive(m: Message): boolean {
|
|
214
|
-
if (m.evaluation_type === null) return false
|
|
215
|
-
if (m.evaluation_type === 10) return true
|
|
216
|
-
if (m.evaluation_type === undefined && m.feedback_score === 1) return true
|
|
217
|
-
return false
|
|
218
|
-
}
|
|
219
|
-
|
|
220
|
-
/** 列表展示:是否已踩 */
|
|
221
|
-
export function messageDislikeActive(m: Message): boolean {
|
|
222
|
-
if (m.evaluation_type === null) return false
|
|
223
|
-
if (m.evaluation_type === 20 || m.evaluation_type === 30) return true
|
|
224
|
-
if (m.evaluation_type === undefined && m.feedback_score === -1) return true
|
|
225
|
-
return false
|
|
226
|
-
}
|
|
227
|
-
|
|
228
|
-
export type MessageEvaluationDisplay = 'none' | 'like' | 'dislike'
|
|
229
|
-
|
|
230
|
-
export function getMessageEvaluationDisplay(m: Message): MessageEvaluationDisplay {
|
|
231
|
-
if (messageLikeActive(m)) return 'like'
|
|
232
|
-
if (messageDislikeActive(m)) return 'dislike'
|
|
233
|
-
return 'none'
|
|
234
|
-
}
|
|
235
|
-
|
|
236
|
-
/**
|
|
237
|
-
* 提交 /chat/feedback/review:10=点赞、20=取消点赞、30=点踩、40=取消点踩
|
|
238
|
-
*/
|
|
239
|
-
export function buildChatFeedbackEvaluationType(
|
|
240
|
-
display: MessageEvaluationDisplay,
|
|
241
|
-
clickedLike: boolean,
|
|
242
|
-
): number {
|
|
243
|
-
if (clickedLike) {
|
|
244
|
-
return display === 'like' ? 20 : 10
|
|
245
|
-
}
|
|
246
|
-
return display === 'dislike' ? 40 : 30
|
|
247
|
-
}
|
|
248
|
-
|
|
249
|
-
/** 请求成功后与列表 VO 对齐的本地 evaluation_type(null=未评价) */
|
|
250
|
-
export function evaluationTypeAfterFeedbackRequest(sent: number): number | null {
|
|
251
|
-
switch (sent) {
|
|
252
|
-
case 10:
|
|
253
|
-
return 10
|
|
254
|
-
case 20:
|
|
255
|
-
return null
|
|
256
|
-
case 30:
|
|
257
|
-
return 20
|
|
258
|
-
case 40:
|
|
259
|
-
return null
|
|
260
|
-
default:
|
|
261
|
-
return null
|
|
262
|
-
}
|
|
263
|
-
}
|
|
264
|
-
|
|
265
|
-
/** 点赞点踩接口用 turnId;优先 turn_id,否则从合成 id(`{turnId}-10|20`)还原 */
|
|
266
|
-
export function resolveMessageTurnIdForFeedback(m: Message): string {
|
|
267
|
-
const tid = m.turn_id != null ? String(m.turn_id).trim() : ''
|
|
268
|
-
if (tid) return tid
|
|
269
|
-
const id = String(m.id ?? '')
|
|
270
|
-
return id.replace(/-(?:10|20)$/, '') || id
|
|
271
|
-
}
|
|
272
|
-
|
|
273
|
-
/** type:10=用户,20=智能体 */
|
|
274
|
-
function chatTypeToRole(type: unknown): 'user' | 'assistant' | 'system' {
|
|
275
|
-
const n = Number(type)
|
|
276
|
-
if (n === 10) return 'user'
|
|
277
|
-
if (n === 20) return 'assistant'
|
|
278
|
-
return 'assistant'
|
|
279
|
-
}
|
|
280
|
-
|
|
281
|
-
/**
|
|
282
|
-
* 解析历史消息里的 referenceMaterials 字段,转换为 references_knowledge_items。
|
|
283
|
-
*/
|
|
284
|
-
function parseReferenceMaterials(
|
|
285
|
-
referenceMaterials: unknown,
|
|
286
|
-
): NonNullable<Message['references_knowledge_items']> | undefined {
|
|
287
|
-
if (!referenceMaterials) return undefined
|
|
288
|
-
if (Array.isArray(referenceMaterials)) {
|
|
289
|
-
return referenceMaterials as NonNullable<Message['references_knowledge_items']>
|
|
290
|
-
}
|
|
291
|
-
if (typeof referenceMaterials === 'string') {
|
|
292
|
-
const jsonText = referenceMaterials.trim()
|
|
293
|
-
if (!jsonText) return undefined
|
|
294
|
-
try {
|
|
295
|
-
const parsed = JSON.parse(jsonText) as unknown
|
|
296
|
-
if (Array.isArray(parsed)) {
|
|
297
|
-
return parsed as NonNullable<Message['references_knowledge_items']>
|
|
298
|
-
}
|
|
299
|
-
if (parsed && typeof parsed === 'object') {
|
|
300
|
-
const parsedObj = parsed as Record<string, unknown>
|
|
301
|
-
if (Array.isArray(parsedObj.items)) {
|
|
302
|
-
return parsedObj.items as NonNullable<Message['references_knowledge_items']>
|
|
303
|
-
}
|
|
304
|
-
}
|
|
305
|
-
return undefined
|
|
306
|
-
} catch {
|
|
307
|
-
return undefined
|
|
308
|
-
}
|
|
309
|
-
}
|
|
310
|
-
if (referenceMaterials && typeof referenceMaterials === 'object') {
|
|
311
|
-
const rawObj = referenceMaterials as Record<string, unknown>
|
|
312
|
-
if (Array.isArray(rawObj.items)) {
|
|
313
|
-
return rawObj.items as NonNullable<Message['references_knowledge_items']>
|
|
314
|
-
}
|
|
315
|
-
}
|
|
316
|
-
return undefined
|
|
317
|
-
}
|
|
318
|
-
|
|
319
|
-
/** ChatMessageVO → Message,按 createTime 升序(上旧下新) */
|
|
320
|
-
export function normalizeMessagesList(raw: unknown): Message[] {
|
|
321
|
-
const body = unwrapChatApiBody(raw)
|
|
322
|
-
let list: unknown[] = []
|
|
323
|
-
if (Array.isArray(body)) list = body
|
|
324
|
-
else if (body && typeof body === 'object') {
|
|
325
|
-
const o = body as Record<string, unknown>
|
|
326
|
-
if (Array.isArray(o.messages)) list = o.messages
|
|
327
|
-
else if (Array.isArray(o.items)) list = o.items
|
|
328
|
-
else if (Array.isArray(o.list)) list = o.list
|
|
329
|
-
else if (Array.isArray(o.data)) list = o.data
|
|
330
|
-
}
|
|
331
|
-
const mapped = list
|
|
332
|
-
.map((item): Message | null => {
|
|
333
|
-
if (!item || typeof item !== 'object') return null
|
|
334
|
-
const m = item as Record<string, unknown>
|
|
335
|
-
const turnId = m.turnId ?? m.turn_id
|
|
336
|
-
const typeNum = Number(m.type)
|
|
337
|
-
const turnKey =
|
|
338
|
-
turnId != null && String(turnId) !== '' ? String(turnId) : null
|
|
339
|
-
let id: string | null = null
|
|
340
|
-
if (turnKey && (typeNum === 10 || typeNum === 20)) {
|
|
341
|
-
id = `${turnKey}-${typeNum}`
|
|
342
|
-
} else if (m.id != null && String(m.id) !== '') {
|
|
343
|
-
id = String(m.id)
|
|
344
|
-
}
|
|
345
|
-
if (!id) return null
|
|
346
|
-
const createTime = String(
|
|
347
|
-
m.createTime ?? m.create_time ?? new Date().toISOString(),
|
|
348
|
-
)
|
|
349
|
-
return {
|
|
350
|
-
id,
|
|
351
|
-
turn_id: turnKey ?? undefined,
|
|
352
|
-
role: chatTypeToRole(m.type),
|
|
353
|
-
content: String(m.content ?? m.text ?? ''),
|
|
354
|
-
created_at: createTime,
|
|
355
|
-
thoughts: Array.isArray(m.thoughts)
|
|
356
|
-
? (m.thoughts as string[])
|
|
357
|
-
: undefined,
|
|
358
|
-
options: Array.isArray(m.options)
|
|
359
|
-
? (m.options as string[])
|
|
360
|
-
: Array.isArray(m.suggested_replies)
|
|
361
|
-
? (m.suggested_replies as string[])
|
|
362
|
-
: undefined,
|
|
363
|
-
references_knowledge_items: (() => {
|
|
364
|
-
const refMaterials = parseReferenceMaterials(m.referenceMaterials)
|
|
365
|
-
if (refMaterials && refMaterials.length > 0) return refMaterials
|
|
366
|
-
const rawRefs =
|
|
367
|
-
(m.references_knowledge as unknown) ??
|
|
368
|
-
(m.referencesKnowledge as unknown) ??
|
|
369
|
-
undefined
|
|
370
|
-
if (Array.isArray(rawRefs)) return rawRefs as any[]
|
|
371
|
-
if (rawRefs && typeof rawRefs === 'object') {
|
|
372
|
-
const o = rawRefs as Record<string, unknown>
|
|
373
|
-
if (Array.isArray(o.items)) return o.items as any[]
|
|
374
|
-
}
|
|
375
|
-
return undefined
|
|
376
|
-
})(),
|
|
377
|
-
...(() => {
|
|
378
|
-
const etRaw = m.evaluationType ?? m.evaluation_type
|
|
379
|
-
let evaluation_type: number | null | undefined
|
|
380
|
-
let feedback_score: number | undefined
|
|
381
|
-
|
|
382
|
-
if (etRaw === null) {
|
|
383
|
-
evaluation_type = null
|
|
384
|
-
feedback_score = undefined
|
|
385
|
-
} else if (
|
|
386
|
-
etRaw !== undefined &&
|
|
387
|
-
etRaw !== '' &&
|
|
388
|
-
Number.isFinite(Number(etRaw))
|
|
389
|
-
) {
|
|
390
|
-
evaluation_type = Number(etRaw)
|
|
391
|
-
if (evaluation_type === 10) feedback_score = 1
|
|
392
|
-
else if (evaluation_type === 20 || evaluation_type === 30)
|
|
393
|
-
feedback_score = -1
|
|
394
|
-
else feedback_score = undefined
|
|
395
|
-
} else {
|
|
396
|
-
evaluation_type = undefined
|
|
397
|
-
feedback_score =
|
|
398
|
-
typeof m.feedback_score === 'number'
|
|
399
|
-
? m.feedback_score
|
|
400
|
-
: typeof m.feedbackScore === 'number'
|
|
401
|
-
? m.feedbackScore
|
|
402
|
-
: undefined
|
|
403
|
-
if (feedback_score === 1) evaluation_type = 10
|
|
404
|
-
else if (feedback_score === -1) evaluation_type = 20
|
|
405
|
-
}
|
|
406
|
-
return { evaluation_type, feedback_score }
|
|
407
|
-
})(),
|
|
408
|
-
}
|
|
409
|
-
})
|
|
410
|
-
.filter((x): x is Message => x !== null)
|
|
411
|
-
|
|
412
|
-
// 保持后端返回的原始顺序,不做重排序
|
|
413
|
-
return mapped
|
|
414
|
-
}
|
|
415
|
-
|
|
416
|
-
/** 会话标题:有非空字符串用原标题,否则用 fallback(如「新会话」) */
|
|
417
|
-
export function resolveThreadDisplayTitle(
|
|
418
|
-
title: string | undefined | null,
|
|
419
|
-
fallback: string,
|
|
420
|
-
): string {
|
|
421
|
-
const v = title != null ? String(title).trim() : ''
|
|
422
|
-
return v || fallback
|
|
423
|
-
}
|
|
424
|
-
|
|
425
|
-
/** 与 mergeMessagePreparationDelta 一致:以 code + name 唯一定位一行(如多条 tool_call) */
|
|
426
|
-
function findPreparationItemIndex(
|
|
427
|
-
list: NonNullable<Message['preparation_items']>,
|
|
428
|
-
code: string,
|
|
429
|
-
nameForMatch: string,
|
|
430
|
-
status: string,
|
|
431
|
-
): number {
|
|
432
|
-
const byCodeName = () =>
|
|
433
|
-
list.findIndex((x) => x.code === code && x.name === nameForMatch)
|
|
434
|
-
if (nameForMatch !== code) return byCodeName()
|
|
435
|
-
if (status === 'end') {
|
|
436
|
-
for (let i = list.length - 1; i >= 0; i--) {
|
|
437
|
-
if (list[i].code === code && list[i].phase === 'running') return i
|
|
438
|
-
}
|
|
439
|
-
}
|
|
440
|
-
return byCodeName()
|
|
441
|
-
}
|
|
442
|
-
|
|
443
|
-
/**
|
|
444
|
-
* 合并单条 SSE preparation.delta(code/name/status,可选 description);约定 start→running、end→done,其它 status 原样写入 phase。
|
|
445
|
-
* **同一 code + name 更新原位置**(如多条 tool_call 仅 code 相同);首次出现排在数组末尾。end 未带 name 时回退为同 code 的最后一条 running。
|
|
446
|
-
*/
|
|
447
|
-
export function mergeMessagePreparationDelta(
|
|
448
|
-
prev: Message['preparation_items'] | undefined,
|
|
449
|
-
delta: Record<string, unknown> | undefined,
|
|
450
|
-
): NonNullable<Message['preparation_items']> {
|
|
451
|
-
if (!delta || typeof delta !== 'object') return [...(prev ?? [])]
|
|
452
|
-
const codeRaw = delta.code
|
|
453
|
-
const code = typeof codeRaw === 'string' ? codeRaw.trim() : ''
|
|
454
|
-
if (!code) return [...(prev ?? [])]
|
|
455
|
-
const nameTrim =
|
|
456
|
-
typeof delta.name === 'string' && delta.name.trim()
|
|
457
|
-
? delta.name.trim()
|
|
458
|
-
: ''
|
|
459
|
-
const nameForMatch = nameTrim || code
|
|
460
|
-
const nameForRow = nameTrim || code
|
|
461
|
-
const status =
|
|
462
|
-
typeof delta.status === 'string' ? delta.status.trim() : ''
|
|
463
|
-
const list = [...(prev ?? [])]
|
|
464
|
-
const idx = findPreparationItemIndex(list, code, nameForMatch, status)
|
|
465
|
-
const prevRow = idx >= 0 ? list[idx] : undefined
|
|
466
|
-
let description: string | undefined = prevRow?.description
|
|
467
|
-
if ('description' in delta) {
|
|
468
|
-
const v = delta.description
|
|
469
|
-
if (typeof v === 'string') {
|
|
470
|
-
description = v.trim() || undefined
|
|
471
|
-
}
|
|
472
|
-
}
|
|
473
|
-
const descPatch = description ? { description } : {}
|
|
474
|
-
|
|
475
|
-
if (status === 'start') {
|
|
476
|
-
const next = { code, name: nameForRow, phase: 'running', ...descPatch }
|
|
477
|
-
if (idx >= 0) list[idx] = next
|
|
478
|
-
else list.push(next)
|
|
479
|
-
return list
|
|
480
|
-
}
|
|
481
|
-
if (status === 'end') {
|
|
482
|
-
const next = {
|
|
483
|
-
code,
|
|
484
|
-
name: nameTrim || prevRow?.name || code,
|
|
485
|
-
phase: 'done',
|
|
486
|
-
...descPatch,
|
|
487
|
-
}
|
|
488
|
-
if (idx >= 0) list[idx] = next
|
|
489
|
-
else list.push(next)
|
|
490
|
-
return list
|
|
491
|
-
}
|
|
492
|
-
// 非 start/end 的 status 原样记入 phase,便于后端新增状态时保留语义
|
|
493
|
-
if (status) {
|
|
494
|
-
const next = {
|
|
495
|
-
code,
|
|
496
|
-
name: nameTrim || prevRow?.name || code,
|
|
497
|
-
phase: status,
|
|
498
|
-
...descPatch,
|
|
499
|
-
}
|
|
500
|
-
if (idx >= 0) list[idx] = next
|
|
501
|
-
else list.push(next)
|
|
502
|
-
return list
|
|
503
|
-
}
|
|
504
|
-
return [...(prev ?? [])]
|
|
505
|
-
}
|
|
506
|
-
|
|
507
|
-
/** 流结束或块结束时,将准备步骤全部标为完成(避免缺少 end 时一直转圈) */
|
|
508
|
-
export function markMessagePreparationDone(msg: Message): Message {
|
|
509
|
-
if (!msg.preparation_items?.length) return msg
|
|
510
|
-
return {
|
|
511
|
-
...msg,
|
|
512
|
-
preparation_items: msg.preparation_items.map((x) => ({
|
|
513
|
-
...x,
|
|
514
|
-
phase: 'done',
|
|
515
|
-
})),
|
|
516
|
-
}
|
|
517
|
-
}
|
|
518
|
-
|
|
519
|
-
/** 写入消息列表缓存前去掉 preparation(仅流式 UI 使用) */
|
|
520
|
-
export function omitMessagePreparationForPersist(msg: Message): Message {
|
|
521
|
-
if (!msg.preparation_items) return msg
|
|
522
|
-
const { preparation_items: _drop, ...rest } = msg
|
|
523
|
-
return rest
|
|
524
|
-
}
|
package/src/utils/cn.ts
DELETED
package/src/utils/crypto.ts
DELETED
|
@@ -1,164 +0,0 @@
|
|
|
1
|
-
import forge from 'node-forge';
|
|
2
|
-
|
|
3
|
-
class EncryptionManager {
|
|
4
|
-
private publicKey: forge.pki.rsa.PublicKey | null = null;
|
|
5
|
-
private encryptionLevel: 'none' | 'partial' | 'full' = 'none';
|
|
6
|
-
private initialized = false;
|
|
7
|
-
|
|
8
|
-
async init() {
|
|
9
|
-
if (this.initialized) return;
|
|
10
|
-
try {
|
|
11
|
-
// We use fetch directly to avoid circular dependency with api client interceptors
|
|
12
|
-
const response = await fetch('/api/v1/auth/public-key', { method: 'POST' });
|
|
13
|
-
if (response.ok) {
|
|
14
|
-
const data = await response.json();
|
|
15
|
-
this.encryptionLevel = data.encryption_level;
|
|
16
|
-
if (data.public_key) {
|
|
17
|
-
try {
|
|
18
|
-
this.publicKey = forge.pki.publicKeyFromPem(data.public_key);
|
|
19
|
-
} catch (e) {
|
|
20
|
-
console.error('Failed to parse public key:', e);
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
}
|
|
24
|
-
this.initialized = true;
|
|
25
|
-
console.log(`Encryption initialized. Level: ${this.encryptionLevel}`);
|
|
26
|
-
} catch (error) {
|
|
27
|
-
console.error('Failed to initialize encryption:', error);
|
|
28
|
-
// Fallback to none if failed
|
|
29
|
-
this.encryptionLevel = 'none';
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
get level() {
|
|
34
|
-
return this.encryptionLevel;
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
encrypt(data: any, force: boolean = false): { encryptedData: any; headers: Record<string, string>; aesKey: string } | null {
|
|
38
|
-
if ((this.encryptionLevel === 'none' && !force) || !this.publicKey) {
|
|
39
|
-
return null;
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
try {
|
|
43
|
-
// 1. Generate AES Key (32 bytes)
|
|
44
|
-
const aesKey = forge.random.getBytesSync(32);
|
|
45
|
-
const iv = forge.random.getBytesSync(12);
|
|
46
|
-
|
|
47
|
-
// 2. Encrypt Data with AES-GCM
|
|
48
|
-
const jsonString = JSON.stringify(data);
|
|
49
|
-
const cipher = forge.cipher.createCipher('AES-GCM', aesKey);
|
|
50
|
-
cipher.start({ iv: iv });
|
|
51
|
-
cipher.update(forge.util.createBuffer(jsonString, 'utf8'));
|
|
52
|
-
cipher.finish();
|
|
53
|
-
const encryptedData = cipher.output.getBytes();
|
|
54
|
-
const tag = cipher.mode.tag.getBytes();
|
|
55
|
-
|
|
56
|
-
// Combine ciphertext + tag
|
|
57
|
-
const finalEncryptedData = encryptedData + tag;
|
|
58
|
-
|
|
59
|
-
// 3. Encrypt AES Key with RSA Public Key
|
|
60
|
-
const encryptedAesKey = this.publicKey.encrypt(aesKey, 'RSA-OAEP', {
|
|
61
|
-
md: forge.md.sha256.create(),
|
|
62
|
-
mgf1: {
|
|
63
|
-
md: forge.md.sha256.create()
|
|
64
|
-
}
|
|
65
|
-
});
|
|
66
|
-
|
|
67
|
-
// 4. Encode to Base64
|
|
68
|
-
const encryptedAesKeyB64 = forge.util.encode64(encryptedAesKey);
|
|
69
|
-
const ivB64 = forge.util.encode64(iv);
|
|
70
|
-
const encryptedDataB64 = forge.util.encode64(finalEncryptedData);
|
|
71
|
-
|
|
72
|
-
return {
|
|
73
|
-
encryptedData: encryptedDataB64,
|
|
74
|
-
aesKey: forge.util.bytesToHex(aesKey), // Return hex string of key
|
|
75
|
-
headers: {
|
|
76
|
-
'X-Encrypted-Key': encryptedAesKeyB64,
|
|
77
|
-
'X-IV': ivB64,
|
|
78
|
-
'Content-Type': 'text/plain'
|
|
79
|
-
}
|
|
80
|
-
};
|
|
81
|
-
} catch (error) {
|
|
82
|
-
console.error('Encryption failed:', error);
|
|
83
|
-
throw error;
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
prepareEncryption(force: boolean = false): { headers: Record<string, string>; aesKey: string } | null {
|
|
88
|
-
if ((this.encryptionLevel === 'none' && !force) || !this.publicKey) {
|
|
89
|
-
return null;
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
try {
|
|
93
|
-
// 1. Generate AES Key (32 bytes)
|
|
94
|
-
const aesKey = forge.random.getBytesSync(32);
|
|
95
|
-
|
|
96
|
-
// 2. Encrypt AES Key with RSA Public Key
|
|
97
|
-
const encryptedAesKey = this.publicKey.encrypt(aesKey, 'RSA-OAEP', {
|
|
98
|
-
md: forge.md.sha256.create(),
|
|
99
|
-
mgf1: {
|
|
100
|
-
md: forge.md.sha256.create()
|
|
101
|
-
}
|
|
102
|
-
});
|
|
103
|
-
|
|
104
|
-
// 3. Encode to Base64
|
|
105
|
-
const encryptedAesKeyB64 = forge.util.encode64(encryptedAesKey);
|
|
106
|
-
|
|
107
|
-
return {
|
|
108
|
-
aesKey: forge.util.bytesToHex(aesKey),
|
|
109
|
-
headers: {
|
|
110
|
-
'X-Encrypted-Key': encryptedAesKeyB64
|
|
111
|
-
}
|
|
112
|
-
};
|
|
113
|
-
} catch (error) {
|
|
114
|
-
console.error('Failed to prepare encryption headers:', error);
|
|
115
|
-
return null;
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
decrypt(encryptedData: { iv: string; data: string }, aesKey: string): any {
|
|
120
|
-
try {
|
|
121
|
-
const iv = forge.util.decode64(encryptedData.iv);
|
|
122
|
-
const dataWithTag = forge.util.decode64(encryptedData.data);
|
|
123
|
-
|
|
124
|
-
// Extract tag (last 16 bytes)
|
|
125
|
-
const tagLength = 16;
|
|
126
|
-
const dataLength = dataWithTag.length - tagLength;
|
|
127
|
-
const ciphertext = dataWithTag.substring(0, dataLength);
|
|
128
|
-
const tag = dataWithTag.substring(dataLength);
|
|
129
|
-
|
|
130
|
-
// Convert Hex key back to bytes
|
|
131
|
-
const keyBytes = forge.util.hexToBytes(aesKey);
|
|
132
|
-
|
|
133
|
-
const decipher = forge.cipher.createDecipher('AES-GCM', keyBytes);
|
|
134
|
-
decipher.start({
|
|
135
|
-
iv: iv,
|
|
136
|
-
tag: forge.util.createBuffer(tag)
|
|
137
|
-
});
|
|
138
|
-
decipher.update(forge.util.createBuffer(ciphertext));
|
|
139
|
-
|
|
140
|
-
const success = decipher.finish();
|
|
141
|
-
|
|
142
|
-
if (success) {
|
|
143
|
-
const decryptedString = decipher.output.toString();
|
|
144
|
-
try {
|
|
145
|
-
return JSON.parse(decryptedString);
|
|
146
|
-
} catch {
|
|
147
|
-
return decryptedString;
|
|
148
|
-
}
|
|
149
|
-
} else {
|
|
150
|
-
throw new Error('Decryption authentication failed');
|
|
151
|
-
}
|
|
152
|
-
} catch (error) {
|
|
153
|
-
console.error('Decryption failed:', error);
|
|
154
|
-
throw error;
|
|
155
|
-
}
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
// Helper to generate raw AES key string for storage/passing
|
|
159
|
-
generateKey(): string {
|
|
160
|
-
return forge.random.getBytesSync(32);
|
|
161
|
-
}
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
export const encryptionManager = new EncryptionManager();
|