feat: 增强编码能力 - 新增代码编辑器、代码搜索、Git集成

- 新增 plugins/code_editor.py: 精准代码编辑(搜索替换、批量编辑、diff对比)
- 新增 plugins/code_search.py: 代码搜索与理解(跨文件搜索、符号提取、依赖分析)
- 新增 plugins/git_tools.py: Git 版本控制(status/diff/log/commit/branch)
- 新增 core/ 模块: 配置管理、引擎管理、对话处理、显示输出、代码沙箱
- 修复 requirements.txt: 使用正确的 pip 包名(Pillow、opencv-python 等)
- 更新 unified_tool_manager.py: 兼容 Plugin 和 Liugin 两种类名
- 更新系统提示词: 增强编程工作流指导

本次更新由 mimo 自动化执行,与开发者无关。
This commit is contained in:
Xiaoli Dev committed 2026-04-25 10:55:27 +08:00
commit e22652fbbb
53 files changed
+20067

No files matched your search

+198
View File
@@ -0,0 +1,198 @@
"""
Ollama图像识别插件
支持多种图像识别引擎的切换
"""
import os
import sys
from colorama import Fore, Style
# 添加项目根目录到sys.path
current_dir = os.path.dirname(os.path.abspath(__file__))
project_root = os.path.dirname(current_dir)
sys.path.insert(0, project_root)
from image_engine import get_engine_manager
class Liugin:
"""图像识别插件 - 支持多引擎切换"""
def __init__(self):
self.usage = """图像识别插件使用方法:
/image <操作> <参数>
操作命令:
- analyze <图片路径> - 详细分析图片
- ocr <图片路径> - 快速OCR文字识别
- quick <图片路径> - 快速图片描述
- describe <图片路径> - 完整描述图片
- model [模型名] - 查看/切换模型
- models - 列出可用的视觉模型
- engine [引擎名] - 查看/切换识别引擎
- engines - 列出所有识别引擎
示例:
- image analyze C:\\photo.png
- image ocr C:\\screenshot.png
- image model llava:13b
- image engine openai
JSON调用示例:
{"action": "use_tool", "tool": "image", "args": "analyze c:\\\\test.png"}
"""
self.cli = None
self.engine_manager = None
# 支持的图片格式
self.supported_formats = ['png', 'jpg', 'jpeg', 'gif', 'webp', 'bmp']
def set_cli(self, cli):
"""设置CLI实例引用"""
self.cli = cli
# 注册插件命令
self.cli.register_liugin_command('image', self.command_handler)
self.cli.register_liugin_command('img', self.command_handler)
def command_handler(self, args):
"""处理命令"""
parts = args.strip().split(maxsplit=1)
if len(parts) < 1:
return self._get_help()
operation = parts[0].lower()
remaining_args = parts[1] if len(parts) > 1 else ""
return self.handle(f"{operation} {remaining_args}")
def get_tool_info(self):
return {
"name": "image",
"description": "图像识别工具,支持多引擎切换,使用本地或云端模型进行图像分析",
"keywords": ["图像", "图片", "image", "analyze", "分析", "视觉", "识别", "OCR"],
"usage": """image 工具使用说明:
- analyze <图片路径> - 详细分析
- ocr <图片路径> - OCR文字识别
- quick <图片路径> - 快速描述
- engine <引擎名> - 切换引擎
- engines - 列出所有引擎
支持格式:PNG, JPG, JPEG, GIF, WEBP, BMP"""
}
def handle(self, args):
"""处理请求"""
# 延迟初始化引擎管理器
if self.engine_manager is None:
self.engine_manager = get_engine_manager()
try:
parts = args.strip().split(maxsplit=1)
if len(parts) < 1:
return self._get_help()
operation = parts[0].lower()
image_path = parts[1].strip() if len(parts) > 1 else ""
# 引擎管理命令
if operation == "engines":
return self.engine_manager.list_engines()
elif operation == "engine":
if image_path:
success, msg = self.engine_manager.switch_engine(image_path)
return msg
return f"当前引擎: {self.engine_manager.get_current_engine_name()}"
elif operation == "models":
engine = self.engine_manager.get_engine()
if engine and hasattr(engine, 'get_model_list'):
return engine.get_model_list()
return "当前引擎不支持模型列表"
elif operation == "model":
engine = self.engine_manager.get_engine()
if not image_path:
if engine and hasattr(engine, 'model'):
return f"当前模型: {engine.model}"
return "当前引擎不支持模型切换"
if engine and hasattr(engine, 'set_model'):
success, msg = engine.set_model(image_path)
return msg
return "当前引擎不支持模型切换"
# 图像分析命令
elif operation in ["analyze", "ocr", "quick", "describe"]:
if not image_path:
return f"错误:请提供图片路径。用法: {operation} <图片路径>"
return self._analyze_image(image_path, operation)
else:
# 兼容旧用法,直接当作图片路径处理
return self._analyze_image(operation, "analyze")
except Exception as e:
return f"错误: {str(e)}"
def _get_help(self):
"""获取帮助信息"""
current = self.engine_manager.get_current_engine_name() if self.engine_manager else "未初始化"
return f"""图像识别插件命令:
- analyze <图片路径> 详细分析图片
- ocr <图片路径> OCR文字识别
- quick <图片路径> 快速描述
- describe <图片路径> 完整描述
- model [模型名] 查看/切换模型
- models 列出视觉模型
- engine [引擎名] 查看/切换引擎
- engines 列出所有引擎
当前引擎: {current}"""
def _analyze_image(self, image_path, mode="analyze"):
"""使用引擎分析图片"""
# 检查文件
if not os.path.exists(image_path):
return f"文件不存在: {image_path}"
ext = os.path.splitext(image_path)[1].lower().lstrip('.')
if ext not in self.supported_formats:
return f"不支持的图片格式: {ext}。支持: {', '.join(self.supported_formats)}"
# 检查引擎
engine = self.engine_manager.get_engine()
if not engine:
return "没有可用的图像引擎"
file_size = os.path.getsize(image_path)
engine_name = self.engine_manager.get_current_engine_name()
# 获取模型名(如果支持)
model_info = ""
if hasattr(engine, 'model'):
model_info = f" | 模型: {engine.model}"
# 文件大小警告
size_warning = ""
if file_size > 1024 * 1024: # 大于1MB
size_warning = f" {Fore.YELLOW}(较大图片,处理可能需要较长时间){Style.RESET_ALL}"
print(f"{Fore.CYAN}📷 图像识别: {os.path.basename(image_path)}{Style.RESET_ALL}{size_warning}")
print(f"{Fore.YELLOW}📦 大小: {file_size/1024:.1f}KB | 引擎: {engine_name}{model_info}{Style.RESET_ALL}")
print(f"{Fore.YELLOW}⏳ 正在识别,请耐心等待...{Style.RESET_ALL}")
try:
# 使用引擎分析
full_response = ""
for chunk in self.engine_manager.analyze(image_path, mode, stream=True):
if chunk:
print(chunk, end='', flush=True)
full_response += chunk
print() # 换行
print(f"{Fore.GREEN}✓ 识别完成{Style.RESET_ALL}")
return full_response if full_response else "识别结果为空"
except Exception as e:
error_msg = str(e)
print(f"{Fore.RED}✗ {error_msg}{Style.RESET_ALL}")
return f"识别失败: {error_msg}"