93 lines
3.2 KiB
Python
93 lines
3.2 KiB
Python
import json
|
|
import re
|
|
import unittest
|
|
from pathlib import Path
|
|
|
|
PROJECT_ROOT = Path(__file__).resolve().parents[3]
|
|
BACKEND_ROOT = PROJECT_ROOT / 'shierfeng-fastapi-backend'
|
|
FRONTEND_ROOT = PROJECT_ROOT / 'shierfeng-fastapi-frontend'
|
|
|
|
AI_DEPENDENCIES = {
|
|
'agno',
|
|
'anthropic',
|
|
'cerebras-cloud-sdk',
|
|
'cohere',
|
|
'google-genai',
|
|
'groq',
|
|
'litellm',
|
|
'llama-api-client',
|
|
'mistralai',
|
|
'ollama',
|
|
'openai',
|
|
'portkey-ai',
|
|
}
|
|
AI_FRONTEND_DEPENDENCIES = {
|
|
'katex',
|
|
'markstream-vue',
|
|
'mermaid',
|
|
'shiki',
|
|
'stream-markdown',
|
|
'stream-monaco',
|
|
'uuid',
|
|
'vite-plugin-monaco-editor-esm',
|
|
}
|
|
|
|
|
|
def _parse_requirement_names(requirements_path: Path) -> set[str]:
|
|
names = set()
|
|
for raw_line in requirements_path.read_text(encoding='utf-8').splitlines():
|
|
line = raw_line.partition('#')[0].strip()
|
|
if not line or line == '.':
|
|
continue
|
|
match = re.match(r'[A-Za-z0-9_.-]+', line)
|
|
if match:
|
|
names.add(match.group(0).lower().replace('_', '-'))
|
|
return names
|
|
|
|
|
|
class AiRemovalContractTest(unittest.TestCase):
|
|
def test_ai_source_files_are_removed(self) -> None:
|
|
remaining_files = []
|
|
module_ai = BACKEND_ROOT / 'module_ai'
|
|
if module_ai.exists():
|
|
remaining_files.extend(module_ai.rglob('*.py'))
|
|
|
|
explicit_files = (
|
|
BACKEND_ROOT / 'utils/ai_util.py',
|
|
BACKEND_ROOT / 'utils/crypto_util.py',
|
|
FRONTEND_ROOT / 'src/api/ai/chat.js',
|
|
FRONTEND_ROOT / 'src/api/ai/model.js',
|
|
FRONTEND_ROOT / 'src/views/ai/chat/components/AiMessage.vue',
|
|
FRONTEND_ROOT / 'src/views/ai/chat/index.vue',
|
|
FRONTEND_ROOT / 'src/views/ai/model/index.vue',
|
|
FRONTEND_ROOT / 'src/assets/icons/svg/ai-chat.svg',
|
|
FRONTEND_ROOT / 'src/assets/icons/svg/ai-manage.svg',
|
|
FRONTEND_ROOT / 'src/assets/icons/svg/ai-model.svg',
|
|
)
|
|
remaining_files.extend(path for path in explicit_files if path.exists())
|
|
|
|
self.assertEqual([], sorted(str(path.relative_to(PROJECT_ROOT)) for path in remaining_files))
|
|
|
|
def test_ai_dependencies_are_removed(self) -> None:
|
|
backend_dependencies = set()
|
|
for filename in ('requirements.txt',):
|
|
backend_dependencies.update(_parse_requirement_names(BACKEND_ROOT / filename))
|
|
self.assertEqual([], sorted(AI_DEPENDENCIES & backend_dependencies))
|
|
|
|
package_json = json.loads((FRONTEND_ROOT / 'package.json').read_text(encoding='utf-8'))
|
|
frontend_dependencies = set(package_json.get('dependencies', {}))
|
|
frontend_dependencies.update(package_json.get('devDependencies', {}))
|
|
self.assertEqual([], sorted(AI_FRONTEND_DEPENDENCIES & frontend_dependencies))
|
|
|
|
def test_initialization_sql_has_no_ai_or_external_menu(self) -> None:
|
|
forbidden_terms = ('ai_models', 'ai_chat_config', 'ai_provider_type', '施尔丰仓库')
|
|
violations = []
|
|
for filename in ('shierfeng-fastapi.sql',):
|
|
sql = (BACKEND_ROOT / 'sql' / filename).read_text(encoding='utf-8').lower()
|
|
violations.extend(f'{filename}: {term}' for term in forbidden_terms if term.lower() in sql)
|
|
self.assertEqual([], violations)
|
|
|
|
|
|
if __name__ == '__main__':
|
|
unittest.main()
|