File size: 2,878 Bytes
4d393e8
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
f44c935
 
4d393e8
f44c935
4d393e8
 
 
f44c935
4d393e8
 
 
 
 
f44c935
 
 
 
 
4d393e8
 
f44c935
4d393e8
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
"""
Configuration manager for DiffWeave CLI.

Handles local `.diffweave/` workspace context similar to `.git/`.
"""
from __future__ import annotations

import json
import os
from pathlib import Path
from typing import Any, Optional

from diffweave.mcp.errors import WorkspaceNotConfiguredError

CONFIG_DIR_NAME = ".diffweave"
CONFIG_FILE_NAME = "config.json"


def find_diffweave_root(start_dir: Optional[Path] = None) -> Optional[Path]:
    """Search current directory and ancestors for a .diffweave directory."""
    current = (start_dir or Path.cwd()).resolve()
    while True:
        if (current / CONFIG_DIR_NAME).is_dir():
            return current
        if current.parent == current:
            break
        current = current.parent
    return None


def get_config_path(start_dir: Optional[Path] = None) -> Path:
    """Return path to config.json, using discovered root or cwd."""
    root = find_diffweave_root(start_dir) or Path.cwd()
    return root / CONFIG_DIR_NAME / CONFIG_FILE_NAME


def load_config(start_dir: Optional[Path] = None) -> dict[str, Any]:
    """Load the local .diffweave configuration."""
    config_path = get_config_path(start_dir)
    if not config_path.exists():
        return {}
    try:
        with open(config_path, "r", encoding="utf-8") as f:
            return json.load(f)
    except Exception:
        return {}


def save_config(data: dict[str, Any], target_dir: Optional[Path] = None) -> Path:
    """Save configuration to .diffweave/config.json."""
    root = target_dir or Path.cwd()
    cfg_dir = root / CONFIG_DIR_NAME
    cfg_dir.mkdir(parents=True, exist_ok=True)
    config_path = cfg_dir / CONFIG_FILE_NAME
    with open(config_path, "w", encoding="utf-8") as f:
        json.dump(data, f, indent=2)
    return config_path


def get_active_workspace(
    override_id: Optional[str] = None, start_dir: Optional[Path] = None
) -> str:
    """
    Resolve the active workspace ID:
    1. CLI flag override (--workspace)
    2. Local directory .diffweave/config.json (like .git, takes precedence over ambient env)
    3. Environment variable DIFFWEAVE_WORKSPACE_ID / DOCWEAVE_WORKSPACE_ID
    """
    # 1. Direct CLI flag override
    if override_id and override_id.strip():
        return override_id.strip()

    # 2. Local initialized workspace context (.diffweave/config.json)
    config = load_config(start_dir)
    ws_id = config.get("workspace_id")
    if ws_id and str(ws_id).strip():
        return str(ws_id).strip()

    # 3. Ambient environment variable override
    env_ws = os.environ.get("DIFFWEAVE_WORKSPACE_ID") or os.environ.get("DOCWEAVE_WORKSPACE_ID")
    if env_ws and env_ws.strip():
        return env_ws.strip()

    raise WorkspaceNotConfiguredError(
        "No active workspace found. Run 'dw init' to bind this directory to a workspace, "
        "or pass '--workspace <name_or_uuid>'."
    )