- 将 A_Memorix 从旧 submodule / 插件形态迁入主线源码,主体落到 src/A_memorix - 调整主程序接入方式,使 A_Memorix 作为源码内长期记忆子系统运行 - 回收父项目插件体系中针对 A_Memorix 的特判,减少对 plugin 通用层的侵入 - 将长期记忆配置、运行时、自检、导入、调优等能力收口到 memory 路由与主线服务层 - 重做长期记忆控制台与图谱页面,按 MaiBot 现有 dashboard 风格接入 - 补充实体关系图与证据视图双视图能力,支持查看节点、关系、段落及其证据链路 - 新增长期记忆配置编辑器与 memory-api,支持主线内配置管理 - 补齐删除管理能力:删除预览、混合删除、来源批量删除、删除操作恢复 - 优化删除预览与删除操作详情的前端展示,支持分页、检索,并以实体名/关系内容/段落摘要替代单纯 hash 展示 - 修复图谱与控制台相关前端问题,包括证据视图切换、查询触发时机、删除弹层空值保护等 - 新增或更新 A_Memorix 相关测试、WebUI 路由测试、前端 vitest 测试与辅助验证脚本 - 移除旧 plugins/A_memorix、.gitmodules 及相关历史维护文档
137 lines
3.7 KiB
TypeScript
137 lines
3.7 KiB
TypeScript
import { useEffect, useState } from 'react'
|
|
import CodeMirror from '@uiw/react-codemirror'
|
|
import { css } from '@codemirror/lang-css'
|
|
import { json, jsonParseLinter } from '@codemirror/lang-json'
|
|
import { linter } from '@codemirror/lint'
|
|
import { python } from '@codemirror/lang-python'
|
|
import { oneDark } from '@codemirror/theme-one-dark'
|
|
import { EditorView } from '@codemirror/view'
|
|
import { StreamLanguage } from '@codemirror/language'
|
|
import { toml as tomlMode } from '@codemirror/legacy-modes/mode/toml'
|
|
|
|
import { useTheme } from '@/components/use-theme'
|
|
|
|
export type Language = 'python' | 'json' | 'toml' | 'css' | 'text'
|
|
|
|
interface CodeEditorProps {
|
|
value: string
|
|
|
|
onChange?: (value: string) => void
|
|
language?: Language
|
|
readOnly?: boolean
|
|
height?: string
|
|
minHeight?: string
|
|
maxHeight?: string
|
|
placeholder?: string
|
|
theme?: 'light' | 'dark'
|
|
className?: string
|
|
}
|
|
|
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
const languageExtensions: Record<Language, any[]> = {
|
|
python: [python()],
|
|
json: [json(), linter(jsonParseLinter())],
|
|
toml: [StreamLanguage.define(tomlMode)],
|
|
css: [css()],
|
|
text: [],
|
|
}
|
|
|
|
export function CodeEditor({
|
|
value,
|
|
onChange,
|
|
language = 'text',
|
|
readOnly = false,
|
|
height = '400px',
|
|
minHeight,
|
|
maxHeight,
|
|
placeholder,
|
|
theme,
|
|
className = '',
|
|
}: CodeEditorProps) {
|
|
const [mounted, setMounted] = useState(false)
|
|
const { resolvedTheme } = useTheme()
|
|
|
|
useEffect(() => {
|
|
setMounted(true)
|
|
}, [])
|
|
|
|
if (!mounted) {
|
|
return (
|
|
<div
|
|
className={`rounded-md border bg-muted animate-pulse ${className}`}
|
|
style={{ height, minHeight, maxHeight }}
|
|
/>
|
|
)
|
|
}
|
|
|
|
const extensions = [
|
|
...(languageExtensions[language] || []),
|
|
EditorView.lineWrapping,
|
|
// 应用 JetBrains Mono 字体
|
|
EditorView.theme({
|
|
'&': {
|
|
fontFamily: '"JetBrains Mono", "Fira Code", "Consolas", "Monaco", monospace',
|
|
},
|
|
'.cm-content': {
|
|
fontFamily: '"JetBrains Mono", "Fira Code", "Consolas", "Monaco", monospace',
|
|
},
|
|
'.cm-gutters': {
|
|
fontFamily: '"JetBrains Mono", "Fira Code", "Consolas", "Monaco", monospace',
|
|
},
|
|
'.cm-scroller': {
|
|
fontFamily: '"JetBrains Mono", "Fira Code", "Consolas", "Monaco", monospace',
|
|
},
|
|
}),
|
|
]
|
|
|
|
if (readOnly) {
|
|
extensions.push(EditorView.editable.of(false))
|
|
}
|
|
|
|
// 如果外部传了 theme prop 则使用,否则从 context 自动获取
|
|
const effectiveTheme = theme ?? resolvedTheme
|
|
|
|
return (
|
|
<div className={`rounded-md overflow-hidden border custom-scrollbar ${className}`}>
|
|
<CodeMirror
|
|
value={value}
|
|
height={height}
|
|
minHeight={minHeight}
|
|
maxHeight={maxHeight}
|
|
theme={effectiveTheme === 'dark' ? oneDark : undefined}
|
|
extensions={extensions}
|
|
onChange={onChange}
|
|
placeholder={placeholder}
|
|
basicSetup={{
|
|
lineNumbers: true,
|
|
highlightActiveLineGutter: true,
|
|
highlightSpecialChars: true,
|
|
history: true,
|
|
foldGutter: true,
|
|
drawSelection: true,
|
|
dropCursor: true,
|
|
allowMultipleSelections: true,
|
|
indentOnInput: true,
|
|
syntaxHighlighting: true,
|
|
bracketMatching: true,
|
|
closeBrackets: true,
|
|
autocompletion: true,
|
|
rectangularSelection: true,
|
|
crosshairCursor: true,
|
|
highlightActiveLine: true,
|
|
highlightSelectionMatches: true,
|
|
closeBracketsKeymap: true,
|
|
defaultKeymap: true,
|
|
searchKeymap: true,
|
|
historyKeymap: true,
|
|
foldKeymap: true,
|
|
completionKeymap: true,
|
|
lintKeymap: true,
|
|
}}
|
|
/>
|
|
</div>
|
|
)
|
|
}
|
|
|
|
export default CodeEditor
|