feat: multi-instance support with --config parameter
Add support for running multiple nanobot instances with complete isolation: - Add --config parameter to gateway command for custom config file path - Implement set_config_path() in config/loader.py for dynamic config path - Derive data directory from config file location (e.g., ~/.nanobot-xxx/) - Update get_data_path() to use unified data directory from config loader - Ensure cron jobs use instance-specific data directory This enables running multiple isolated nanobot instances by specifying different config files, with each instance maintaining separate: - Configuration files - Workspace (memory, sessions, skills) - Cron jobs - Logs and media Example usage: nanobot gateway --config ~/.nanobot-instance2/config.json --port 18791
This commit is contained in:
@@ -244,15 +244,24 @@ def _make_provider(config: Config):
|
|||||||
@app.command()
|
@app.command()
|
||||||
def gateway(
|
def gateway(
|
||||||
port: int = typer.Option(18790, "--port", "-p", help="Gateway port"),
|
port: int = typer.Option(18790, "--port", "-p", help="Gateway port"),
|
||||||
workspace: str | None = typer.Option(None, "--workspace", "-w", help="Workspace directory"),
|
|
||||||
config: str | None = typer.Option(None, "--config", "-c", help="Config file path"),
|
|
||||||
verbose: bool = typer.Option(False, "--verbose", "-v", help="Verbose output"),
|
verbose: bool = typer.Option(False, "--verbose", "-v", help="Verbose output"),
|
||||||
|
config: str = typer.Option(None, "--config", "-c", help="Path to config file"),
|
||||||
):
|
):
|
||||||
"""Start the nanobot gateway."""
|
"""Start the nanobot gateway."""
|
||||||
|
# Set config path if provided (must be done before any imports that use get_data_dir)
|
||||||
|
if config:
|
||||||
|
from nanobot.config.loader import set_config_path
|
||||||
|
config_path = Path(config).expanduser().resolve()
|
||||||
|
if not config_path.exists():
|
||||||
|
console.print(f"[red]Error: Config file not found: {config_path}[/red]")
|
||||||
|
raise typer.Exit(1)
|
||||||
|
set_config_path(config_path)
|
||||||
|
console.print(f"[dim]Using config: {config_path}[/dim]")
|
||||||
|
|
||||||
from nanobot.agent.loop import AgentLoop
|
from nanobot.agent.loop import AgentLoop
|
||||||
from nanobot.bus.queue import MessageBus
|
from nanobot.bus.queue import MessageBus
|
||||||
from nanobot.channels.manager import ChannelManager
|
from nanobot.channels.manager import ChannelManager
|
||||||
from nanobot.config.loader import load_config
|
from nanobot.config.loader import get_data_dir, load_config
|
||||||
from nanobot.cron.service import CronService
|
from nanobot.cron.service import CronService
|
||||||
from nanobot.cron.types import CronJob
|
from nanobot.cron.types import CronJob
|
||||||
from nanobot.heartbeat.service import HeartbeatService
|
from nanobot.heartbeat.service import HeartbeatService
|
||||||
@@ -262,20 +271,16 @@ def gateway(
|
|||||||
import logging
|
import logging
|
||||||
logging.basicConfig(level=logging.DEBUG)
|
logging.basicConfig(level=logging.DEBUG)
|
||||||
|
|
||||||
config_path = Path(config) if config else None
|
|
||||||
config = load_config(config_path)
|
|
||||||
if workspace:
|
|
||||||
config.agents.defaults.workspace = workspace
|
|
||||||
|
|
||||||
console.print(f"{__logo__} Starting nanobot gateway on port {port}...")
|
console.print(f"{__logo__} Starting nanobot gateway on port {port}...")
|
||||||
|
|
||||||
|
config = load_config()
|
||||||
sync_workspace_templates(config.workspace_path)
|
sync_workspace_templates(config.workspace_path)
|
||||||
bus = MessageBus()
|
bus = MessageBus()
|
||||||
provider = _make_provider(config)
|
provider = _make_provider(config)
|
||||||
session_manager = SessionManager(config.workspace_path)
|
session_manager = SessionManager(config.workspace_path)
|
||||||
|
|
||||||
# Create cron service first (callback set after agent creation)
|
# Create cron service first (callback set after agent creation)
|
||||||
# Use workspace path for per-instance cron store
|
cron_store_path = get_data_dir() / "cron" / "jobs.json"
|
||||||
cron_store_path = config.workspace_path / "cron" / "jobs.json"
|
|
||||||
cron = CronService(cron_store_path)
|
cron = CronService(cron_store_path)
|
||||||
|
|
||||||
# Create agent with cron service
|
# Create agent with cron service
|
||||||
|
|||||||
@@ -6,15 +6,29 @@ from pathlib import Path
|
|||||||
from nanobot.config.schema import Config
|
from nanobot.config.schema import Config
|
||||||
|
|
||||||
|
|
||||||
|
# Global variable to store current config path (for multi-instance support)
|
||||||
|
_current_config_path: Path | None = None
|
||||||
|
|
||||||
|
|
||||||
|
def set_config_path(path: Path) -> None:
|
||||||
|
"""Set the current config path (used to derive data directory)."""
|
||||||
|
global _current_config_path
|
||||||
|
_current_config_path = path
|
||||||
|
|
||||||
|
|
||||||
def get_config_path() -> Path:
|
def get_config_path() -> Path:
|
||||||
"""Get the default configuration file path."""
|
"""Get the configuration file path."""
|
||||||
|
if _current_config_path:
|
||||||
|
return _current_config_path
|
||||||
return Path.home() / ".nanobot" / "config.json"
|
return Path.home() / ".nanobot" / "config.json"
|
||||||
|
|
||||||
|
|
||||||
def get_data_dir() -> Path:
|
def get_data_dir() -> Path:
|
||||||
"""Get the nanobot data directory."""
|
"""Get the nanobot data directory (derived from config path)."""
|
||||||
from nanobot.utils.helpers import get_data_path
|
config_path = get_config_path()
|
||||||
return get_data_path()
|
# If config is ~/.nanobot-xxx/config.json, data dir is ~/.nanobot-xxx/
|
||||||
|
# If config is ~/.nanobot/config.json, data dir is ~/.nanobot/
|
||||||
|
return config_path.parent
|
||||||
|
|
||||||
|
|
||||||
def load_config(config_path: Path | None = None) -> Config:
|
def load_config(config_path: Path | None = None) -> Config:
|
||||||
|
|||||||
@@ -12,8 +12,9 @@ def ensure_dir(path: Path) -> Path:
|
|||||||
|
|
||||||
|
|
||||||
def get_data_path() -> Path:
|
def get_data_path() -> Path:
|
||||||
"""~/.nanobot data directory."""
|
"""Get nanobot data directory (derived from config path)."""
|
||||||
return ensure_dir(Path.home() / ".nanobot")
|
from nanobot.config.loader import get_data_dir
|
||||||
|
return ensure_dir(get_data_dir())
|
||||||
|
|
||||||
|
|
||||||
def get_workspace_path(workspace: str | None = None) -> Path:
|
def get_workspace_path(workspace: str | None = None) -> Path:
|
||||||
|
|||||||
Reference in New Issue
Block a user