diff --git a/occm_core/config_paths.py b/occm_core/config_paths.py index dc5bf68..0f36734 100644 --- a/occm_core/config_paths.py +++ b/occm_core/config_paths.py @@ -17,6 +17,9 @@ class ConfigPaths: 支持 .json 和 .jsonc 扩展名,支持自定义路径 """ + # 自定义路径持久化文件 + _CUSTOM_PATHS_FILE = ".occm_custom_paths.json" + # 自定义路径存储(None 表示使用默认路径) _custom_opencode_path: Optional[Path] = None _custom_ohmyopencode_path: Optional[Path] = None @@ -111,6 +114,7 @@ def get_opencode_config(cls) -> Path: def set_opencode_config(cls, path: Optional[Path]) -> None: """设置自定义 OpenCode 配置路径""" cls._custom_opencode_path = path + cls._persist_custom_paths() @classmethod def get_ohmyopencode_config(cls) -> Path: @@ -123,6 +127,50 @@ def get_ohmyopencode_config(cls) -> Path: def set_ohmyopencode_config(cls, path: Optional[Path]) -> None: """设置自定义 Oh My OpenCode 配置路径""" cls._custom_ohmyopencode_path = path + cls._persist_custom_paths() + + @classmethod + def _get_settings_path(cls) -> Path: + """持久化文件路径""" + return cls.get_config_base_dir() / cls._CUSTOM_PATHS_FILE + + @classmethod + def _persist_custom_paths(cls) -> None: + """将自定义路径持久化到磁盘""" + import json + data = {} + if cls._custom_opencode_path is not None: + data["custom_opencode_path"] = str(cls._custom_opencode_path) + if cls._custom_ohmyopencode_path is not None: + data["custom_ohmyopencode_path"] = str(cls._custom_ohmyopencode_path) + if cls._custom_backup_path is not None: + data["custom_backup_dir"] = str(cls._custom_backup_path) + settings_path = cls._get_settings_path() + try: + settings_path.parent.mkdir(parents=True, exist_ok=True) + with open(settings_path, "w", encoding="utf-8") as f: + json.dump(data, f, indent=2) + except Exception as e: + print(f"[OCCM] Failed to persist custom paths: {e}") + + @classmethod + def _load_custom_paths(cls) -> None: + """从磁盘恢复自定义路径""" + import json + settings_path = cls._get_settings_path() + if not settings_path.exists(): + return + try: + with open(settings_path, "r", encoding="utf-8") as f: + data = json.load(f) + if data.get("custom_opencode_path"): + cls._custom_opencode_path = Path(data["custom_opencode_path"]) + if data.get("custom_ohmyopencode_path"): + cls._custom_ohmyopencode_path = Path(data["custom_ohmyopencode_path"]) + if data.get("custom_backup_dir"): + cls._custom_backup_dir = Path(data["custom_backup_dir"]) + except Exception as e: + print(f"[OCCM] Failed to load custom paths: {e}") @classmethod def is_custom_path(cls, config_type: str) -> bool: @@ -144,6 +192,7 @@ def reset_to_default(cls, config_type: str) -> None: cls._custom_ohmyopencode_path = None elif config_type == "backup": cls._custom_backup_path = None + cls._persist_custom_paths() @classmethod def get_claude_settings(cls) -> Path: @@ -168,6 +217,7 @@ def get_backup_dir(cls) -> Path: def set_backup_dir(cls, path: Optional[Path]) -> None: """设置自定义备份目录""" cls._custom_backup_path = path + cls._persist_custom_paths() @classmethod def get_import_path(cls, source_type: str) -> Optional[Path]: diff --git a/opencode_config_manager_fluent.py b/opencode_config_manager_fluent.py index 7874bfe..d84c84c 100644 --- a/opencode_config_manager_fluent.py +++ b/opencode_config_manager_fluent.py @@ -3768,6 +3768,9 @@ class ConfigPaths: 支持 .json 和 .jsonc 扩展名,支持自定义路径 """ + # 自定义路径持久化文件 + _CUSTOM_PATHS_FILE = ".occm_custom_paths.json" + # 自定义路径存储(None 表示使用默认路径) _custom_opencode_path: Optional[Path] = None _custom_ohmyopencode_path: Optional[Path] = None @@ -3863,6 +3866,7 @@ def get_opencode_config(cls) -> Path: def set_opencode_config(cls, path: Optional[Path]) -> None: """设置自定义 OpenCode 配置路径""" cls._custom_opencode_path = path + cls._persist_custom_paths() @classmethod def get_ohmyopencode_config(cls) -> Path: @@ -3875,6 +3879,50 @@ def get_ohmyopencode_config(cls) -> Path: def set_ohmyopencode_config(cls, path: Optional[Path]) -> None: """设置自定义 Oh My OpenCode 配置路径""" cls._custom_ohmyopencode_path = path + cls._persist_custom_paths() + + @classmethod + def _get_settings_path(cls) -> Path: + """持久化文件路径""" + return cls.get_config_base_dir() / cls._CUSTOM_PATHS_FILE + + @classmethod + def _persist_custom_paths(cls) -> None: + """将自定义路径持久化到磁盘""" + import json + data = {} + if cls._custom_opencode_path is not None: + data["custom_opencode_path"] = str(cls._custom_opencode_path) + if cls._custom_ohmyopencode_path is not None: + data["custom_ohmyopencode_path"] = str(cls._custom_ohmyopencode_path) + if cls._custom_backup_path is not None: + data["custom_backup_dir"] = str(cls._custom_backup_path) + settings_path = cls._get_settings_path() + try: + settings_path.parent.mkdir(parents=True, exist_ok=True) + with open(settings_path, "w", encoding="utf-8") as f: + json.dump(data, f, indent=2) + except Exception as e: + print(f"[OCCM] Failed to persist custom paths: {e}") + + @classmethod + def _load_custom_paths(cls) -> None: + """从磁盘恢复自定义路径""" + import json + settings_path = cls._get_settings_path() + if not settings_path.exists(): + return + try: + with open(settings_path, "r", encoding="utf-8") as f: + data = json.load(f) + if data.get("custom_opencode_path"): + cls._custom_opencode_path = Path(data["custom_opencode_path"]) + if data.get("custom_ohmyopencode_path"): + cls._custom_ohmyopencode_path = Path(data["custom_ohmyopencode_path"]) + if data.get("custom_backup_dir"): + cls._custom_backup_dir = Path(data["custom_backup_dir"]) + except Exception as e: + print(f"[OCCM] Failed to load custom paths: {e}") @classmethod def is_custom_path(cls, config_type: str) -> bool: @@ -3896,6 +3944,7 @@ def reset_to_default(cls, config_type: str) -> None: cls._custom_ohmyopencode_path = None elif config_type == "backup": cls._custom_backup_path = None + cls._persist_custom_paths() @classmethod def get_claude_settings(cls) -> Path: @@ -3920,6 +3969,7 @@ def get_backup_dir(cls) -> Path: def set_backup_dir(cls, path: Optional[Path]) -> None: """设置自定义备份目录""" cls._custom_backup_path = path + cls._persist_custom_paths() @classmethod def get_import_path(cls, source_type: str) -> Optional[Path]: @@ -15616,6 +15666,9 @@ def __init__(self): # 检测配置文件冲突(同时存在 .json 和 .jsonc) self._check_config_conflicts() + # 恢复上次保存的自定义路径 + ConfigPaths._load_custom_paths() + # 加载配置 self.opencode_config = ConfigManager.load_json( ConfigPaths.get_opencode_config() @@ -23634,18 +23687,18 @@ def _on_toggle_ohmy_enable(self): plugins = [] if self._ohmy_enabled: - # 禁用:从plugins中移除oh-my-opencode + # 禁用:从plugins中移除oh-my-opencode/oh-my-openagent new_plugins = [] for plugin in plugins: if isinstance(plugin, str): - # 去掉连字符后比较 + # 去掉连字符后比较(兼容新旧包名) plugin_normalized = plugin.lower().replace("-", "") - if "ohmyopencode" not in plugin_normalized: + if "ohmyopencode" not in plugin_normalized and "ohmyopenagent" not in plugin_normalized: new_plugins.append(plugin) elif isinstance(plugin, dict): plugin_name = plugin.get("name", "") or plugin.get("package", "") plugin_normalized = plugin_name.lower().replace("-", "") - if "ohmyopencode" not in plugin_normalized: + if "ohmyopencode" not in plugin_normalized and "ohmyopenagent" not in plugin_normalized: new_plugins.append(plugin) else: new_plugins.append(plugin) @@ -23654,7 +23707,7 @@ def _on_toggle_ohmy_enable(self): self.show_success("成功", "Oh My OpenCode 已禁用") elif self._ohmy_installed: # 已安装但未启用:添加到plugins - plugins.append("oh-my-opencode") + plugins.append("oh-my-openagent") config[field_name] = plugins self.main_window.save_opencode_config() self.show_success("成功", "Oh My OpenCode 已启用") @@ -23662,7 +23715,7 @@ def _on_toggle_ohmy_enable(self): # 未安装:提示安装 self.show_warning( "提示", - "请先通过npm安装oh-my-opencode插件:\nnpm install -g oh-my-opencode", + "请先通过npm安装oh-my-openagent插件:\nbun oh-my-opencode install", ) # 刷新状态 @@ -23829,8 +23882,8 @@ def _load_ohmy_data(self): config_path = ConfigPaths.get_ohmyopencode_config() ohmy_installed = config_path.exists() # 配置文件存在 = 已安装 - # 检测启用状态:plugins数组中是否有oh-my-opencode - # 注意:需要同时检测 "oh-my-opencode" 和 "ohmyopencode" 两种写法 + # 检测启用状态:plugins数组中是否有oh-my-opencode/oh-my-openagent + # 注意:兼容新旧包名 "oh-my-opencode" 和 "oh-my-openagent" # 注意:字段名可能是 "plugins"(复数)或 "plugin"(单数) ohmy_enabled = False config = self.main_window.opencode_config or {} @@ -23840,13 +23893,13 @@ def _load_ohmy_data(self): if isinstance(plugin, str): # 去掉连字符后比较,兼容两种写法 plugin_normalized = plugin.lower().replace("-", "") - if "ohmyopencode" in plugin_normalized: + if "ohmyopencode" in plugin_normalized or "ohmyopenagent" in plugin_normalized: ohmy_enabled = True break elif isinstance(plugin, dict): plugin_name = plugin.get("name", "") or plugin.get("package", "") plugin_normalized = plugin_name.lower().replace("-", "") - if "ohmyopencode" in plugin_normalized: + if "ohmyopencode" in plugin_normalized or "ohmyopenagent" in plugin_normalized: ohmy_enabled = True break