aiecs 1.0.8__py3-none-any.whl → 1.2.0__py3-none-any.whl
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.
Potentially problematic release.
This version of aiecs might be problematic. Click here for more details.
- aiecs/__init__.py +1 -1
- aiecs/aiecs_client.py +159 -1
- aiecs/config/config.py +6 -0
- aiecs/domain/__init__.py +95 -0
- aiecs/domain/community/__init__.py +159 -0
- aiecs/domain/community/agent_adapter.py +516 -0
- aiecs/domain/community/analytics.py +465 -0
- aiecs/domain/community/collaborative_workflow.py +99 -7
- aiecs/domain/community/communication_hub.py +649 -0
- aiecs/domain/community/community_builder.py +322 -0
- aiecs/domain/community/community_integration.py +365 -12
- aiecs/domain/community/community_manager.py +481 -5
- aiecs/domain/community/decision_engine.py +459 -13
- aiecs/domain/community/exceptions.py +238 -0
- aiecs/domain/community/models/__init__.py +36 -0
- aiecs/domain/community/resource_manager.py +1 -1
- aiecs/domain/community/shared_context_manager.py +621 -0
- aiecs/domain/context/__init__.py +24 -0
- aiecs/domain/context/context_engine.py +37 -33
- aiecs/main.py +20 -2
- aiecs/scripts/aid/VERSION_MANAGEMENT.md +97 -0
- aiecs/scripts/aid/__init__.py +15 -0
- aiecs/scripts/aid/version_manager.py +224 -0
- aiecs/scripts/dependance_check/__init__.py +18 -0
- aiecs/scripts/{download_nlp_data.py → dependance_check/download_nlp_data.py} +51 -8
- aiecs/scripts/dependance_patch/__init__.py +8 -0
- aiecs/scripts/dependance_patch/fix_weasel/__init__.py +12 -0
- aiecs/scripts/tools_develop/README.md +340 -0
- aiecs/scripts/tools_develop/__init__.py +16 -0
- aiecs/scripts/tools_develop/check_type_annotations.py +263 -0
- aiecs/scripts/tools_develop/validate_tool_schemas.py +346 -0
- aiecs/tools/__init__.py +53 -34
- aiecs/tools/docs/__init__.py +106 -0
- aiecs/tools/docs/ai_document_orchestrator.py +556 -0
- aiecs/tools/docs/ai_document_writer_orchestrator.py +2222 -0
- aiecs/tools/docs/content_insertion_tool.py +1234 -0
- aiecs/tools/docs/document_creator_tool.py +1179 -0
- aiecs/tools/docs/document_layout_tool.py +1105 -0
- aiecs/tools/docs/document_parser_tool.py +924 -0
- aiecs/tools/docs/document_writer_tool.py +1636 -0
- aiecs/tools/langchain_adapter.py +102 -51
- aiecs/tools/schema_generator.py +265 -0
- aiecs/tools/statistics/__init__.py +82 -0
- aiecs/tools/statistics/ai_data_analysis_orchestrator.py +581 -0
- aiecs/tools/statistics/ai_insight_generator_tool.py +473 -0
- aiecs/tools/statistics/ai_report_orchestrator_tool.py +629 -0
- aiecs/tools/statistics/data_loader_tool.py +518 -0
- aiecs/tools/statistics/data_profiler_tool.py +599 -0
- aiecs/tools/statistics/data_transformer_tool.py +531 -0
- aiecs/tools/statistics/data_visualizer_tool.py +460 -0
- aiecs/tools/statistics/model_trainer_tool.py +470 -0
- aiecs/tools/statistics/statistical_analyzer_tool.py +426 -0
- aiecs/tools/task_tools/chart_tool.py +2 -1
- aiecs/tools/task_tools/image_tool.py +43 -43
- aiecs/tools/task_tools/office_tool.py +48 -36
- aiecs/tools/task_tools/pandas_tool.py +37 -33
- aiecs/tools/task_tools/report_tool.py +67 -56
- aiecs/tools/task_tools/research_tool.py +32 -31
- aiecs/tools/task_tools/scraper_tool.py +53 -46
- aiecs/tools/task_tools/search_tool.py +1123 -0
- aiecs/tools/task_tools/stats_tool.py +20 -15
- {aiecs-1.0.8.dist-info → aiecs-1.2.0.dist-info}/METADATA +5 -1
- aiecs-1.2.0.dist-info/RECORD +135 -0
- aiecs-1.2.0.dist-info/entry_points.txt +10 -0
- aiecs/tools/task_tools/search_api.py +0 -7
- aiecs-1.0.8.dist-info/RECORD +0 -98
- aiecs-1.0.8.dist-info/entry_points.txt +0 -7
- /aiecs/scripts/{DEPENDENCY_SYSTEM_SUMMARY.md → dependance_check/DEPENDENCY_SYSTEM_SUMMARY.md} +0 -0
- /aiecs/scripts/{README_DEPENDENCY_CHECKER.md → dependance_check/README_DEPENDENCY_CHECKER.md} +0 -0
- /aiecs/scripts/{dependency_checker.py → dependance_check/dependency_checker.py} +0 -0
- /aiecs/scripts/{dependency_fixer.py → dependance_check/dependency_fixer.py} +0 -0
- /aiecs/scripts/{quick_dependency_check.py → dependance_check/quick_dependency_check.py} +0 -0
- /aiecs/scripts/{setup_nlp_data.sh → dependance_check/setup_nlp_data.sh} +0 -0
- /aiecs/scripts/{README_WEASEL_PATCH.md → dependance_patch/fix_weasel/README_WEASEL_PATCH.md} +0 -0
- /aiecs/scripts/{fix_weasel_validator.py → dependance_patch/fix_weasel/fix_weasel_validator.py} +0 -0
- /aiecs/scripts/{fix_weasel_validator.sh → dependance_patch/fix_weasel/fix_weasel_validator.sh} +0 -0
- /aiecs/scripts/{patch_weasel_library.sh → dependance_patch/fix_weasel/patch_weasel_library.sh} +0 -0
- /aiecs/scripts/{run_weasel_patch.sh → dependance_patch/fix_weasel/run_weasel_patch.sh} +0 -0
- {aiecs-1.0.8.dist-info → aiecs-1.2.0.dist-info}/WHEEL +0 -0
- {aiecs-1.0.8.dist-info → aiecs-1.2.0.dist-info}/licenses/LICENSE +0 -0
- {aiecs-1.0.8.dist-info → aiecs-1.2.0.dist-info}/top_level.txt +0 -0
|
@@ -117,9 +117,11 @@ class ContextEngine(IStorageBackend, ICheckpointerBackend):
|
|
|
117
117
|
|
|
118
118
|
Args:
|
|
119
119
|
use_existing_redis: Whether to use the existing Redis client from infrastructure
|
|
120
|
+
(已弃用: 现在总是创建独立的 RedisClient 实例以避免事件循环冲突)
|
|
120
121
|
"""
|
|
121
122
|
self.use_existing_redis = use_existing_redis
|
|
122
123
|
self.redis_client: Optional[redis.Redis] = None
|
|
124
|
+
self._redis_client_wrapper: Optional[Any] = None # RedisClient 包装器实例
|
|
123
125
|
|
|
124
126
|
# Fallback to memory storage if Redis not available
|
|
125
127
|
self._memory_sessions: Dict[str, SessionMetrics] = {}
|
|
@@ -149,49 +151,51 @@ class ContextEngine(IStorageBackend, ICheckpointerBackend):
|
|
|
149
151
|
return True
|
|
150
152
|
|
|
151
153
|
try:
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
)
|
|
179
|
-
|
|
180
|
-
# Test connection
|
|
181
|
-
await self.redis_client.ping()
|
|
182
|
-
logger.info("ContextEngine connected to Redis directly")
|
|
183
|
-
return True
|
|
154
|
+
# ✅ 修复方案:在当前事件循环中创建新的 RedisClient 实例
|
|
155
|
+
#
|
|
156
|
+
# 问题根源:
|
|
157
|
+
# - 全局 RedisClient 单例在应用启动的事件循环A中创建
|
|
158
|
+
# - ContextEngine 可能在不同的事件循环B中被初始化(例如在请求处理中)
|
|
159
|
+
# - redis.asyncio 的连接池绑定到创建时的事件循环
|
|
160
|
+
# - 跨事件循环使用会导致 "Task got Future attached to a different loop" 错误
|
|
161
|
+
#
|
|
162
|
+
# 解决方案:
|
|
163
|
+
# - 为每个 ContextEngine 实例创建独立的 RedisClient
|
|
164
|
+
# - 使用 RedisClient 包装器保持架构一致性
|
|
165
|
+
# - 在当前事件循环中初始化,确保事件循环匹配
|
|
166
|
+
|
|
167
|
+
from aiecs.infrastructure.persistence.redis_client import RedisClient
|
|
168
|
+
|
|
169
|
+
# 创建专属的 RedisClient 实例(在当前事件循环中)
|
|
170
|
+
self._redis_client_wrapper = RedisClient()
|
|
171
|
+
await self._redis_client_wrapper.initialize()
|
|
172
|
+
|
|
173
|
+
# 获取底层 redis.Redis 客户端用于现有代码
|
|
174
|
+
self.redis_client = await self._redis_client_wrapper.get_client()
|
|
175
|
+
|
|
176
|
+
# Test connection
|
|
177
|
+
await self.redis_client.ping()
|
|
178
|
+
logger.info("ContextEngine connected to Redis successfully using RedisClient wrapper in current event loop")
|
|
179
|
+
return True
|
|
184
180
|
|
|
185
181
|
except Exception as e:
|
|
186
182
|
logger.error(f"Failed to connect to Redis: {e}")
|
|
187
183
|
logger.warning("Falling back to memory storage")
|
|
188
184
|
self.redis_client = None
|
|
185
|
+
self._redis_client_wrapper = None
|
|
189
186
|
return False
|
|
190
187
|
|
|
191
188
|
async def close(self):
|
|
192
189
|
"""Close Redis connection."""
|
|
193
|
-
if self.
|
|
190
|
+
if hasattr(self, '_redis_client_wrapper') and self._redis_client_wrapper:
|
|
191
|
+
# 使用 RedisClient 包装器的 close 方法
|
|
192
|
+
await self._redis_client_wrapper.close()
|
|
193
|
+
self._redis_client_wrapper = None
|
|
194
|
+
self.redis_client = None
|
|
195
|
+
elif self.redis_client:
|
|
196
|
+
# 兼容性处理:直接关闭 redis 客户端
|
|
194
197
|
await self.redis_client.close()
|
|
198
|
+
self.redis_client = None
|
|
195
199
|
|
|
196
200
|
# ==================== Session Management ====================
|
|
197
201
|
|
aiecs/main.py
CHANGED
|
@@ -23,6 +23,10 @@ from aiecs.ws.socket_server import sio
|
|
|
23
23
|
|
|
24
24
|
# Import infrastructure
|
|
25
25
|
from aiecs.infrastructure.persistence.database_manager import DatabaseManager
|
|
26
|
+
from aiecs.infrastructure.persistence import (
|
|
27
|
+
initialize_context_engine,
|
|
28
|
+
close_context_engine
|
|
29
|
+
)
|
|
26
30
|
from aiecs.infrastructure.messaging.celery_task_manager import CeleryTaskManager
|
|
27
31
|
from aiecs.infrastructure.monitoring.structured_logger import setup_structured_logging
|
|
28
32
|
|
|
@@ -82,6 +86,13 @@ async def lifespan(app: FastAPI):
|
|
|
82
86
|
logger.error(f"Failed to discover tools: {e}")
|
|
83
87
|
raise
|
|
84
88
|
|
|
89
|
+
# Initialize ContextEngine (optional, graceful degradation)
|
|
90
|
+
try:
|
|
91
|
+
await initialize_context_engine()
|
|
92
|
+
logger.info("ContextEngine initialized")
|
|
93
|
+
except Exception as e:
|
|
94
|
+
logger.warning(f"ContextEngine initialization failed (continuing without it): {e}")
|
|
95
|
+
|
|
85
96
|
# Application startup complete
|
|
86
97
|
logger.info("AIECS startup complete")
|
|
87
98
|
|
|
@@ -90,6 +101,13 @@ async def lifespan(app: FastAPI):
|
|
|
90
101
|
# Shutdown
|
|
91
102
|
logger.info("Shutting down AIECS...")
|
|
92
103
|
|
|
104
|
+
# Close ContextEngine
|
|
105
|
+
try:
|
|
106
|
+
await close_context_engine()
|
|
107
|
+
logger.info("ContextEngine closed")
|
|
108
|
+
except Exception as e:
|
|
109
|
+
logger.warning(f"Error closing ContextEngine: {e}")
|
|
110
|
+
|
|
93
111
|
# Close database connection
|
|
94
112
|
if db_manager:
|
|
95
113
|
await db_manager.disconnect()
|
|
@@ -106,7 +124,7 @@ async def lifespan(app: FastAPI):
|
|
|
106
124
|
app = FastAPI(
|
|
107
125
|
title="AIECS - AI Execute Services",
|
|
108
126
|
description="Middleware service for AI-powered task execution and tool orchestration",
|
|
109
|
-
version="1.0
|
|
127
|
+
version="1.2.0",
|
|
110
128
|
lifespan=lifespan
|
|
111
129
|
)
|
|
112
130
|
|
|
@@ -131,7 +149,7 @@ async def health_check():
|
|
|
131
149
|
return {
|
|
132
150
|
"status": "healthy",
|
|
133
151
|
"service": "aiecs",
|
|
134
|
-
"version": "1.0
|
|
152
|
+
"version": "1.2.0"
|
|
135
153
|
}
|
|
136
154
|
|
|
137
155
|
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
# AIECS 版本管理
|
|
2
|
+
|
|
3
|
+
AIECS 提供了一个统一的版本管理工具,可以同时更新项目中所有相关文件的版本号。
|
|
4
|
+
|
|
5
|
+
## 支持的文件
|
|
6
|
+
|
|
7
|
+
版本管理工具会自动更新以下文件中的版本号:
|
|
8
|
+
|
|
9
|
+
1. **`aiecs/__init__.py`** - 更新 `__version__` 变量
|
|
10
|
+
2. **`aiecs/main.py`** - 更新 FastAPI 应用版本和健康检查端点版本
|
|
11
|
+
3. **`pyproject.toml`** - 更新项目版本
|
|
12
|
+
|
|
13
|
+
## 使用方法
|
|
14
|
+
|
|
15
|
+
### 1. 显示当前版本
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
poetry run python -m aiecs.scripts.aid.version_manager --show
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
### 2. 设置特定版本
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
poetry run python -m aiecs.scripts.aid.version_manager --version 1.2.0
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
### 3. 自动递增版本
|
|
28
|
+
|
|
29
|
+
#### 补丁版本 (Patch)
|
|
30
|
+
```bash
|
|
31
|
+
poetry run python -m aiecs.scripts.aid.version_manager --bump patch
|
|
32
|
+
# 1.1.0 -> 1.1.1
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
#### 次版本 (Minor)
|
|
36
|
+
```bash
|
|
37
|
+
poetry run python -m aiecs.scripts.aid.version_manager --bump minor
|
|
38
|
+
# 1.1.0 -> 1.2.0
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
#### 主版本 (Major)
|
|
42
|
+
```bash
|
|
43
|
+
poetry run python -m aiecs.scripts.aid.version_manager --bump major
|
|
44
|
+
# 1.1.0 -> 2.0.0
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
## 版本号格式
|
|
48
|
+
|
|
49
|
+
版本号遵循 [语义化版本控制](https://semver.org/) 规范:
|
|
50
|
+
|
|
51
|
+
- **主版本号 (Major)**: 不兼容的API修改
|
|
52
|
+
- **次版本号 (Minor)**: 向下兼容的功能性新增
|
|
53
|
+
- **补丁版本号 (Patch)**: 向下兼容的问题修正
|
|
54
|
+
|
|
55
|
+
格式:`X.Y.Z` (例如:1.2.3)
|
|
56
|
+
|
|
57
|
+
## 命令行选项
|
|
58
|
+
|
|
59
|
+
- `--version, -v`: 设置特定版本号
|
|
60
|
+
- `--bump, -b`: 自动递增版本 (major/minor/patch)
|
|
61
|
+
- `--show, -s`: 显示当前版本
|
|
62
|
+
- `--help, -h`: 显示帮助信息
|
|
63
|
+
|
|
64
|
+
## 示例
|
|
65
|
+
|
|
66
|
+
```bash
|
|
67
|
+
# 查看当前版本
|
|
68
|
+
poetry run python -m aiecs.scripts.aid.version_manager --show
|
|
69
|
+
|
|
70
|
+
# 发布补丁版本
|
|
71
|
+
poetry run python -m aiecs.scripts.aid.version_manager --bump patch
|
|
72
|
+
|
|
73
|
+
# 发布新功能版本
|
|
74
|
+
poetry run python -m aiecs.scripts.aid.version_manager --bump minor
|
|
75
|
+
|
|
76
|
+
# 发布重大更新版本
|
|
77
|
+
poetry run python -m aiecs.scripts.aid.version_manager --bump major
|
|
78
|
+
|
|
79
|
+
# 手动设置版本
|
|
80
|
+
poetry run python -m aiecs.scripts.aid.version_manager --version 2.1.0
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
## 注意事项
|
|
84
|
+
|
|
85
|
+
1. 版本管理工具会自动验证版本号格式
|
|
86
|
+
2. 所有相关文件会同时更新,确保版本号一致性
|
|
87
|
+
3. 更新前建议先提交当前更改到版本控制系统
|
|
88
|
+
4. 工具会显示详细的更新日志,确认所有文件都已正确更新
|
|
89
|
+
|
|
90
|
+
## 故障排除
|
|
91
|
+
|
|
92
|
+
如果遇到问题,请检查:
|
|
93
|
+
|
|
94
|
+
1. 确保在项目根目录下运行命令
|
|
95
|
+
2. 确保所有目标文件存在且可写
|
|
96
|
+
3. 检查版本号格式是否正确 (X.Y.Z)
|
|
97
|
+
4. 确保没有其他进程正在编辑这些文件
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
"""
|
|
2
|
+
AIECS Development Tools (AID)
|
|
3
|
+
|
|
4
|
+
This module contains development and maintenance tools for the AIECS project.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
# Lazy import to avoid circular import issues
|
|
8
|
+
def get_version_manager_main():
|
|
9
|
+
"""Get the version manager main function"""
|
|
10
|
+
from .version_manager import main
|
|
11
|
+
return main
|
|
12
|
+
|
|
13
|
+
__all__ = [
|
|
14
|
+
'get_version_manager_main',
|
|
15
|
+
]
|
|
@@ -0,0 +1,224 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
AIECS Version Manager
|
|
4
|
+
|
|
5
|
+
A script to manage version numbers across multiple files in the AIECS project.
|
|
6
|
+
Updates version numbers in:
|
|
7
|
+
- aiecs/__init__.py (__version__)
|
|
8
|
+
- aiecs/main.py (FastAPI app version and health check version)
|
|
9
|
+
- pyproject.toml (project version)
|
|
10
|
+
|
|
11
|
+
Usage:
|
|
12
|
+
aiecs-version --version 1.2.0
|
|
13
|
+
aiecs-version --bump patch
|
|
14
|
+
aiecs-version --bump minor
|
|
15
|
+
aiecs-version --bump major
|
|
16
|
+
aiecs-version --show
|
|
17
|
+
"""
|
|
18
|
+
|
|
19
|
+
import argparse
|
|
20
|
+
import re
|
|
21
|
+
import sys
|
|
22
|
+
from pathlib import Path
|
|
23
|
+
from typing import Optional, Tuple
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
class VersionManager:
|
|
27
|
+
"""Manages version numbers across AIECS project files"""
|
|
28
|
+
|
|
29
|
+
def __init__(self, project_root: Optional[Path] = None):
|
|
30
|
+
"""Initialize the version manager with project root path"""
|
|
31
|
+
if project_root is None:
|
|
32
|
+
# Find project root by looking for pyproject.toml
|
|
33
|
+
current = Path(__file__).parent
|
|
34
|
+
while current != current.parent:
|
|
35
|
+
if (current / "pyproject.toml").exists():
|
|
36
|
+
project_root = current
|
|
37
|
+
break
|
|
38
|
+
current = current.parent
|
|
39
|
+
|
|
40
|
+
if project_root is None:
|
|
41
|
+
raise RuntimeError("Could not find project root (pyproject.toml)")
|
|
42
|
+
|
|
43
|
+
self.project_root = project_root
|
|
44
|
+
self.files = {
|
|
45
|
+
'init': project_root / "aiecs" / "__init__.py",
|
|
46
|
+
'main': project_root / "aiecs" / "main.py",
|
|
47
|
+
'pyproject': project_root / "pyproject.toml"
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
def get_current_version(self) -> str:
|
|
51
|
+
"""Get the current version from __init__.py"""
|
|
52
|
+
init_file = self.files['init']
|
|
53
|
+
if not init_file.exists():
|
|
54
|
+
raise FileNotFoundError(f"Could not find {init_file}")
|
|
55
|
+
|
|
56
|
+
content = init_file.read_text(encoding='utf-8')
|
|
57
|
+
match = re.search(r'__version__\s*=\s*["\']([^"\']+)["\']', content)
|
|
58
|
+
if not match:
|
|
59
|
+
raise ValueError("Could not find __version__ in __init__.py")
|
|
60
|
+
|
|
61
|
+
return match.group(1)
|
|
62
|
+
|
|
63
|
+
def parse_version(self, version: str) -> Tuple[int, int, int]:
|
|
64
|
+
"""Parse version string into major, minor, patch components"""
|
|
65
|
+
match = re.match(r'^(\d+)\.(\d+)\.(\d+)$', version)
|
|
66
|
+
if not match:
|
|
67
|
+
raise ValueError(f"Invalid version format: {version}. Expected format: X.Y.Z")
|
|
68
|
+
|
|
69
|
+
return int(match.group(1)), int(match.group(2)), int(match.group(3))
|
|
70
|
+
|
|
71
|
+
def bump_version(self, current_version: str, bump_type: str) -> str:
|
|
72
|
+
"""Bump version based on type (major, minor, patch)"""
|
|
73
|
+
major, minor, patch = self.parse_version(current_version)
|
|
74
|
+
|
|
75
|
+
if bump_type == 'major':
|
|
76
|
+
major += 1
|
|
77
|
+
minor = 0
|
|
78
|
+
patch = 0
|
|
79
|
+
elif bump_type == 'minor':
|
|
80
|
+
minor += 1
|
|
81
|
+
patch = 0
|
|
82
|
+
elif bump_type == 'patch':
|
|
83
|
+
patch += 1
|
|
84
|
+
else:
|
|
85
|
+
raise ValueError(f"Invalid bump type: {bump_type}. Use 'major', 'minor', or 'patch'")
|
|
86
|
+
|
|
87
|
+
return f"{major}.{minor}.{patch}"
|
|
88
|
+
|
|
89
|
+
def update_init_file(self, new_version: str) -> None:
|
|
90
|
+
"""Update version in aiecs/__init__.py"""
|
|
91
|
+
init_file = self.files['init']
|
|
92
|
+
content = init_file.read_text(encoding='utf-8')
|
|
93
|
+
|
|
94
|
+
# Update __version__ line
|
|
95
|
+
content = re.sub(
|
|
96
|
+
r'(__version__\s*=\s*["\'])([^"\']+)(["\'])',
|
|
97
|
+
rf'\g<1>{new_version}\g<3>',
|
|
98
|
+
content
|
|
99
|
+
)
|
|
100
|
+
|
|
101
|
+
init_file.write_text(content, encoding='utf-8')
|
|
102
|
+
print(f"✓ Updated {init_file.relative_to(self.project_root)}: __version__ = \"{new_version}\"")
|
|
103
|
+
|
|
104
|
+
def update_main_file(self, new_version: str) -> None:
|
|
105
|
+
"""Update version in aiecs/main.py"""
|
|
106
|
+
main_file = self.files['main']
|
|
107
|
+
content = main_file.read_text(encoding='utf-8')
|
|
108
|
+
|
|
109
|
+
# Update FastAPI app version
|
|
110
|
+
content = re.sub(
|
|
111
|
+
r'(version=")([^"]+)(")',
|
|
112
|
+
rf'\g<1>{new_version}\g<3>',
|
|
113
|
+
content
|
|
114
|
+
)
|
|
115
|
+
|
|
116
|
+
# Update health check version
|
|
117
|
+
content = re.sub(
|
|
118
|
+
r'("version":\s*")([^"]+)(")',
|
|
119
|
+
rf'\g<1>{new_version}\g<3>',
|
|
120
|
+
content
|
|
121
|
+
)
|
|
122
|
+
|
|
123
|
+
main_file.write_text(content, encoding='utf-8')
|
|
124
|
+
print(f"✓ Updated {main_file.relative_to(self.project_root)}: FastAPI version and health check version")
|
|
125
|
+
|
|
126
|
+
def update_pyproject_file(self, new_version: str) -> None:
|
|
127
|
+
"""Update version in pyproject.toml"""
|
|
128
|
+
pyproject_file = self.files['pyproject']
|
|
129
|
+
content = pyproject_file.read_text(encoding='utf-8')
|
|
130
|
+
|
|
131
|
+
# Update project version (only in [project] section, not in [project.scripts])
|
|
132
|
+
# Use a more specific pattern to avoid updating script entry points
|
|
133
|
+
content = re.sub(
|
|
134
|
+
r'^(\s*version\s*=\s*")([^"]+)(")',
|
|
135
|
+
rf'\g<1>{new_version}\g<3>',
|
|
136
|
+
content,
|
|
137
|
+
flags=re.MULTILINE
|
|
138
|
+
)
|
|
139
|
+
|
|
140
|
+
pyproject_file.write_text(content, encoding='utf-8')
|
|
141
|
+
print(f"✓ Updated {pyproject_file.relative_to(self.project_root)}: project version")
|
|
142
|
+
|
|
143
|
+
def update_version(self, new_version: str) -> None:
|
|
144
|
+
"""Update version in all files"""
|
|
145
|
+
# Validate version format
|
|
146
|
+
self.parse_version(new_version)
|
|
147
|
+
|
|
148
|
+
print(f"Updating version to {new_version}...")
|
|
149
|
+
print()
|
|
150
|
+
|
|
151
|
+
# Update all files
|
|
152
|
+
self.update_init_file(new_version)
|
|
153
|
+
self.update_main_file(new_version)
|
|
154
|
+
self.update_pyproject_file(new_version)
|
|
155
|
+
|
|
156
|
+
print()
|
|
157
|
+
print(f"✓ Successfully updated version to {new_version} in all files!")
|
|
158
|
+
|
|
159
|
+
def show_version(self) -> None:
|
|
160
|
+
"""Show current version"""
|
|
161
|
+
try:
|
|
162
|
+
version = self.get_current_version()
|
|
163
|
+
print(f"Current version: {version}")
|
|
164
|
+
except Exception as e:
|
|
165
|
+
print(f"Error getting current version: {e}", file=sys.stderr)
|
|
166
|
+
sys.exit(1)
|
|
167
|
+
|
|
168
|
+
|
|
169
|
+
def main():
|
|
170
|
+
"""Main entry point for the version manager"""
|
|
171
|
+
parser = argparse.ArgumentParser(
|
|
172
|
+
description="AIECS Version Manager - Update version numbers across project files",
|
|
173
|
+
formatter_class=argparse.RawDescriptionHelpFormatter,
|
|
174
|
+
epilog="""
|
|
175
|
+
Examples:
|
|
176
|
+
aiecs-version --version 1.2.0 # Set specific version
|
|
177
|
+
aiecs-version --bump patch # Bump patch version (1.1.0 -> 1.1.1)
|
|
178
|
+
aiecs-version --bump minor # Bump minor version (1.1.0 -> 1.2.0)
|
|
179
|
+
aiecs-version --bump major # Bump major version (1.1.0 -> 2.0.0)
|
|
180
|
+
aiecs-version --show # Show current version
|
|
181
|
+
"""
|
|
182
|
+
)
|
|
183
|
+
|
|
184
|
+
# Create mutually exclusive group for version options
|
|
185
|
+
version_group = parser.add_mutually_exclusive_group(required=True)
|
|
186
|
+
version_group.add_argument(
|
|
187
|
+
'--version', '-v',
|
|
188
|
+
type=str,
|
|
189
|
+
help='Set specific version (e.g., 1.2.0)'
|
|
190
|
+
)
|
|
191
|
+
version_group.add_argument(
|
|
192
|
+
'--bump', '-b',
|
|
193
|
+
choices=['major', 'minor', 'patch'],
|
|
194
|
+
help='Bump version: major (X.0.0), minor (X.Y.0), or patch (X.Y.Z)'
|
|
195
|
+
)
|
|
196
|
+
version_group.add_argument(
|
|
197
|
+
'--show', '-s',
|
|
198
|
+
action='store_true',
|
|
199
|
+
help='Show current version'
|
|
200
|
+
)
|
|
201
|
+
|
|
202
|
+
args = parser.parse_args()
|
|
203
|
+
|
|
204
|
+
try:
|
|
205
|
+
manager = VersionManager()
|
|
206
|
+
|
|
207
|
+
if args.show:
|
|
208
|
+
manager.show_version()
|
|
209
|
+
elif args.version:
|
|
210
|
+
manager.update_version(args.version)
|
|
211
|
+
elif args.bump:
|
|
212
|
+
current_version = manager.get_current_version()
|
|
213
|
+
new_version = manager.bump_version(current_version, args.bump)
|
|
214
|
+
print(f"Bumping {args.bump} version: {current_version} -> {new_version}")
|
|
215
|
+
print()
|
|
216
|
+
manager.update_version(new_version)
|
|
217
|
+
|
|
218
|
+
except Exception as e:
|
|
219
|
+
print(f"Error: {e}", file=sys.stderr)
|
|
220
|
+
sys.exit(1)
|
|
221
|
+
|
|
222
|
+
|
|
223
|
+
if __name__ == '__main__':
|
|
224
|
+
main()
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"""
|
|
2
|
+
依赖检查和修复工具
|
|
3
|
+
|
|
4
|
+
提供 AIECS 系统依赖的检查、修复和 NLP 数据下载功能。
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from .dependency_checker import main as dependency_checker_main
|
|
8
|
+
from .dependency_fixer import main as dependency_fixer_main
|
|
9
|
+
from .quick_dependency_check import main as quick_dependency_check_main
|
|
10
|
+
from .download_nlp_data import main as download_nlp_data_main
|
|
11
|
+
|
|
12
|
+
__all__ = [
|
|
13
|
+
'dependency_checker_main',
|
|
14
|
+
'dependency_fixer_main',
|
|
15
|
+
'quick_dependency_check_main',
|
|
16
|
+
'download_nlp_data_main',
|
|
17
|
+
]
|
|
18
|
+
|
|
@@ -103,6 +103,7 @@ def download_nltk_data(logger: logging.Logger) -> bool:
|
|
|
103
103
|
packages_to_download = [
|
|
104
104
|
'stopwords',
|
|
105
105
|
'punkt',
|
|
106
|
+
'punkt_tab', # Added for RAKE-NLTK compatibility
|
|
106
107
|
'wordnet',
|
|
107
108
|
'averaged_perceptron_tagger'
|
|
108
109
|
]
|
|
@@ -305,21 +306,21 @@ def verify_installation(logger: logging.Logger) -> bool:
|
|
|
305
306
|
return success
|
|
306
307
|
|
|
307
308
|
|
|
308
|
-
def
|
|
309
|
-
"""
|
|
309
|
+
def download_all_nlp_data():
|
|
310
|
+
"""Download all required NLP data."""
|
|
310
311
|
logger = setup_logging()
|
|
311
312
|
logger.info("Starting AIECS NLP data download process...")
|
|
312
|
-
|
|
313
|
+
|
|
313
314
|
success = True
|
|
314
|
-
|
|
315
|
+
|
|
315
316
|
# Download NLTK data
|
|
316
317
|
if not download_nltk_data(logger):
|
|
317
318
|
success = False
|
|
318
|
-
|
|
319
|
+
|
|
319
320
|
# Download spaCy English model
|
|
320
321
|
if not download_spacy_model('en_core_web_sm', logger):
|
|
321
322
|
success = False
|
|
322
|
-
|
|
323
|
+
|
|
323
324
|
# Download spaCy Chinese model (optional)
|
|
324
325
|
if not download_spacy_model('zh_core_web_sm', logger):
|
|
325
326
|
logger.warning("Chinese model download failed, but this is optional")
|
|
@@ -329,10 +330,10 @@ def main():
|
|
|
329
330
|
if not download_spacy_pkuseg_model(logger):
|
|
330
331
|
logger.warning("spaCy PKUSeg model download failed, but this is optional")
|
|
331
332
|
# Don't mark as failure for PKUSeg model
|
|
332
|
-
|
|
333
|
+
|
|
333
334
|
# Check RAKE-NLTK (optional)
|
|
334
335
|
download_rake_nltk_data(logger)
|
|
335
|
-
|
|
336
|
+
|
|
336
337
|
# Verify installation
|
|
337
338
|
if success and verify_installation(logger):
|
|
338
339
|
logger.info("✅ All NLP data downloaded and verified successfully!")
|
|
@@ -344,5 +345,47 @@ def main():
|
|
|
344
345
|
return 1
|
|
345
346
|
|
|
346
347
|
|
|
348
|
+
def main():
|
|
349
|
+
"""Main entry point with argument parsing."""
|
|
350
|
+
import argparse
|
|
351
|
+
|
|
352
|
+
parser = argparse.ArgumentParser(
|
|
353
|
+
description='Download NLP data for AIECS tools',
|
|
354
|
+
formatter_class=argparse.RawDescriptionHelpFormatter,
|
|
355
|
+
epilog="""
|
|
356
|
+
Examples:
|
|
357
|
+
# Show this help message
|
|
358
|
+
aiecs-download-nlp-data --help
|
|
359
|
+
|
|
360
|
+
# Download all NLP data
|
|
361
|
+
aiecs-download-nlp-data --download
|
|
362
|
+
aiecs-download-nlp-data -d
|
|
363
|
+
|
|
364
|
+
NLP Data Includes:
|
|
365
|
+
- NLTK packages: stopwords, punkt, wordnet, averaged_perceptron_tagger
|
|
366
|
+
- spaCy models: en_core_web_sm (English), zh_core_web_sm (Chinese, optional)
|
|
367
|
+
- spaCy PKUSeg model (Chinese segmentation, optional)
|
|
368
|
+
- RAKE-NLTK data (keyword extraction, optional)
|
|
369
|
+
"""
|
|
370
|
+
)
|
|
371
|
+
|
|
372
|
+
parser.add_argument(
|
|
373
|
+
'-d', '--download',
|
|
374
|
+
action='store_true',
|
|
375
|
+
help='Download all NLP data packages'
|
|
376
|
+
)
|
|
377
|
+
|
|
378
|
+
args = parser.parse_args()
|
|
379
|
+
|
|
380
|
+
# If no arguments provided, show help
|
|
381
|
+
if not args.download:
|
|
382
|
+
parser.print_help()
|
|
383
|
+
print("\n⚠️ No action specified. Use --download or -d to download NLP data.")
|
|
384
|
+
return 0
|
|
385
|
+
|
|
386
|
+
# Execute download
|
|
387
|
+
return download_all_nlp_data()
|
|
388
|
+
|
|
389
|
+
|
|
347
390
|
if __name__ == "__main__":
|
|
348
391
|
sys.exit(main())
|