refactor: 将 A_Memorix 重构为主线长期记忆子系统并重建管理界面
- 将 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 及相关历史维护文档
This commit is contained in:
80
dashboard/src/routes/__tests__/plugin-config.test.tsx
Normal file
80
dashboard/src/routes/__tests__/plugin-config.test.tsx
Normal file
@@ -0,0 +1,80 @@
|
||||
import { render, screen } from '@testing-library/react'
|
||||
import { beforeEach, describe, expect, it, vi } from 'vitest'
|
||||
import type { ReactNode } from 'react'
|
||||
|
||||
import { PluginConfigPage } from '../plugin-config'
|
||||
import * as pluginApi from '@/lib/plugin-api'
|
||||
|
||||
const toastMock = vi.fn()
|
||||
|
||||
vi.mock('@/hooks/use-toast', () => ({
|
||||
useToast: () => ({ toast: toastMock }),
|
||||
}))
|
||||
|
||||
vi.mock('@/lib/restart-context', () => ({
|
||||
RestartProvider: ({ children }: { children: ReactNode }) => <>{children}</>,
|
||||
useRestart: () => ({
|
||||
showRestartPrompt: false,
|
||||
markRestartRequired: vi.fn(),
|
||||
clearRestartRequired: vi.fn(),
|
||||
}),
|
||||
}))
|
||||
|
||||
vi.mock('@/components/restart-overlay', () => ({
|
||||
RestartOverlay: () => null,
|
||||
}))
|
||||
|
||||
vi.mock('@/components', () => ({
|
||||
CodeEditor: ({ value }: { value: string }) => <pre>{value}</pre>,
|
||||
ListFieldEditor: () => <div>list-field-editor</div>,
|
||||
}))
|
||||
|
||||
vi.mock('@/lib/plugin-api', () => ({
|
||||
getInstalledPlugins: vi.fn(),
|
||||
getPluginConfigSchema: vi.fn(),
|
||||
getPluginConfig: vi.fn(),
|
||||
getPluginConfigRaw: vi.fn(),
|
||||
updatePluginConfig: vi.fn(),
|
||||
updatePluginConfigRaw: vi.fn(),
|
||||
resetPluginConfig: vi.fn(),
|
||||
togglePlugin: vi.fn(),
|
||||
}))
|
||||
|
||||
describe('PluginConfigPage', () => {
|
||||
beforeEach(() => {
|
||||
toastMock.mockReset()
|
||||
vi.mocked(pluginApi.getInstalledPlugins).mockResolvedValue({
|
||||
success: true,
|
||||
data: [
|
||||
{
|
||||
id: 'test.emoji',
|
||||
path: '/plugins/test_emoji',
|
||||
manifest: {
|
||||
manifest_version: 2,
|
||||
name: 'Emoji Plugin',
|
||||
version: '1.0.0',
|
||||
description: 'emoji tools',
|
||||
author: { name: 'tester' },
|
||||
license: 'MIT',
|
||||
host_application: { min_version: '1.0.0' },
|
||||
},
|
||||
},
|
||||
],
|
||||
})
|
||||
vi.mocked(pluginApi.getPluginConfigSchema).mockResolvedValue({} as never)
|
||||
vi.mocked(pluginApi.getPluginConfig).mockResolvedValue({} as never)
|
||||
vi.mocked(pluginApi.getPluginConfigRaw).mockResolvedValue({} as never)
|
||||
vi.mocked(pluginApi.updatePluginConfig).mockResolvedValue({} as never)
|
||||
vi.mocked(pluginApi.updatePluginConfigRaw).mockResolvedValue({} as never)
|
||||
vi.mocked(pluginApi.resetPluginConfig).mockResolvedValue({} as never)
|
||||
vi.mocked(pluginApi.togglePlugin).mockResolvedValue({} as never)
|
||||
})
|
||||
|
||||
it('shows real plugins and no longer surfaces A_Memorix in plugin config list', async () => {
|
||||
render(<PluginConfigPage />)
|
||||
|
||||
expect(await screen.findByText('Emoji Plugin')).toBeInTheDocument()
|
||||
expect(screen.getByText('点击插件查看和编辑配置')).toBeInTheDocument()
|
||||
expect(screen.queryByText(/A_Memorix/i)).not.toBeInTheDocument()
|
||||
})
|
||||
})
|
||||
Reference in New Issue
Block a user