mirror of
https://github.com/rookiestar28/ComfyUI-OpenClaw.git
synced 2026-08-14 08:52:45 +00:00
156 lines
4.6 KiB
Python
156 lines
4.6 KiB
Python
"""
|
|
State Directory Service (R11).
|
|
Provides portable, safe state directory paths for logs, caches, and persistence.
|
|
"""
|
|
|
|
import logging
|
|
import os
|
|
import sys
|
|
from typing import Optional
|
|
|
|
logger = logging.getLogger("ComfyUI-OpenClaw.services.state_dir")
|
|
|
|
# Environment variables to override state directory
|
|
STATE_DIR_ENV = "OPENCLAW_STATE_DIR"
|
|
LEGACY_STATE_DIR_ENV = "MOLTBOT_STATE_DIR"
|
|
|
|
# Default subdirectory names under user data
|
|
STATE_DIR_NAME = "comfyui-openclaw"
|
|
LEGACY_STATE_DIR_NAME = "comfyui-moltbot"
|
|
|
|
|
|
def _get_user_data_dir(subdir: Optional[str] = None) -> str:
|
|
"""
|
|
Get the platform-appropriate user data directory.
|
|
|
|
Returns:
|
|
Path to user-writable application data directory.
|
|
"""
|
|
subdir = subdir or STATE_DIR_NAME
|
|
if sys.platform == "win32":
|
|
# Windows: %LOCALAPPDATA%\{subdir}
|
|
base = os.environ.get("LOCALAPPDATA", os.path.expanduser("~"))
|
|
return os.path.join(base, subdir)
|
|
elif sys.platform == "darwin":
|
|
# macOS: ~/Library/Application Support/{subdir}
|
|
return os.path.join(
|
|
os.path.expanduser("~"), "Library", "Application Support", subdir
|
|
)
|
|
else:
|
|
# Linux/Unix: ~/.local/share/{subdir} (XDG_DATA_HOME)
|
|
base = os.environ.get(
|
|
"XDG_DATA_HOME", os.path.join(os.path.expanduser("~"), ".local", "share")
|
|
)
|
|
return os.path.join(base, subdir)
|
|
|
|
|
|
def _resolve_state_dir_path() -> str:
|
|
"""Resolve the canonical state-dir path without creating it."""
|
|
env_dir = os.environ.get(STATE_DIR_ENV) or os.environ.get(LEGACY_STATE_DIR_ENV)
|
|
if env_dir:
|
|
return os.path.abspath(env_dir)
|
|
|
|
new_dir = _get_user_data_dir(STATE_DIR_NAME)
|
|
legacy_dir = _get_user_data_dir(LEGACY_STATE_DIR_NAME)
|
|
return (
|
|
legacy_dir
|
|
if (os.path.exists(legacy_dir) and not os.path.exists(new_dir))
|
|
else new_dir
|
|
)
|
|
|
|
|
|
def peek_state_dir() -> str:
|
|
"""Return the canonical state-dir path without creating directories."""
|
|
return _resolve_state_dir_path()
|
|
|
|
|
|
def get_state_dir() -> str:
|
|
"""
|
|
Get the canonical state directory for all writable data.
|
|
|
|
Priority:
|
|
1. OPENCLAW_STATE_DIR environment variable (explicit override)
|
|
2. (legacy) MOLTBOT_STATE_DIR environment variable (explicit override)
|
|
2. Platform-appropriate user data directory
|
|
|
|
The directory is created if it doesn't exist.
|
|
|
|
Returns:
|
|
Absolute path to state directory.
|
|
"""
|
|
state_dir = _resolve_state_dir_path()
|
|
|
|
# Ensure directory exists with appropriate permissions
|
|
if not os.path.exists(state_dir):
|
|
try:
|
|
os.makedirs(state_dir, mode=0o700, exist_ok=True)
|
|
logger.info(f"Created state directory: {state_dir}")
|
|
except OSError as e:
|
|
logger.error(f"Failed to create state directory: {e}")
|
|
# Fallback to temp directory
|
|
import tempfile
|
|
|
|
state_dir = os.path.join(tempfile.gettempdir(), STATE_DIR_NAME)
|
|
os.makedirs(state_dir, mode=0o700, exist_ok=True)
|
|
logger.warning(f"Using fallback state directory: {state_dir}")
|
|
|
|
return state_dir
|
|
|
|
|
|
def peek_log_path() -> str:
|
|
"""Return the canonical log-file path without creating directories."""
|
|
state_dir = peek_state_dir()
|
|
new_path = os.path.join(state_dir, "openclaw.log")
|
|
legacy_path = os.path.join(state_dir, "moltbot.log")
|
|
return (
|
|
legacy_path
|
|
if (os.path.exists(legacy_path) and not os.path.exists(new_path))
|
|
else new_path
|
|
)
|
|
|
|
|
|
def get_log_path() -> str:
|
|
"""Get the path for the log file."""
|
|
state_dir = get_state_dir()
|
|
new_path = os.path.join(state_dir, "openclaw.log")
|
|
legacy_path = os.path.join(state_dir, "moltbot.log")
|
|
return (
|
|
legacy_path
|
|
if (os.path.exists(legacy_path) and not os.path.exists(new_path))
|
|
else new_path
|
|
)
|
|
|
|
|
|
def get_cache_dir() -> str:
|
|
"""Get the path for cache files."""
|
|
cache_dir = os.path.join(get_state_dir(), "cache")
|
|
os.makedirs(cache_dir, mode=0o700, exist_ok=True)
|
|
return cache_dir
|
|
|
|
|
|
def get_db_path() -> str:
|
|
"""Get the path for the persistence database (future use)."""
|
|
state_dir = get_state_dir()
|
|
new_path = os.path.join(state_dir, "openclaw.db")
|
|
legacy_path = os.path.join(state_dir, "moltbot.db")
|
|
return (
|
|
legacy_path
|
|
if (os.path.exists(legacy_path) and not os.path.exists(new_path))
|
|
else new_path
|
|
)
|
|
|
|
|
|
# Module-level convenience for backwards compatibility
|
|
STATE_DIR = None
|
|
|
|
|
|
def ensure_state_dir() -> str:
|
|
"""
|
|
Ensure state directory exists and return its path.
|
|
Caches the result for performance.
|
|
"""
|
|
global STATE_DIR
|
|
if STATE_DIR is None:
|
|
STATE_DIR = get_state_dir()
|
|
return STATE_DIR
|