cortexctl 0.1.0.dev20260811135705__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
cortex_cli/config.py ADDED
@@ -0,0 +1,88 @@
1
+ from __future__ import annotations
2
+
3
+ import json
4
+ import os
5
+ import tempfile
6
+ from dataclasses import dataclass
7
+ from pathlib import Path
8
+ from typing import Any
9
+
10
+ DEFAULT_API_URL = "http://127.0.0.1:8000/api/v1"
11
+
12
+
13
+ @dataclass
14
+ class CliState:
15
+ api_url: str = DEFAULT_API_URL
16
+ access_token: str | None = None
17
+ refresh_token: str | None = None
18
+ default_workspace_id: str | None = None
19
+
20
+
21
+ class StateStore:
22
+ def __init__(self, path: Path | None = None) -> None:
23
+ self.path = path or default_state_path()
24
+
25
+ def load(self) -> CliState:
26
+ if not self.path.exists():
27
+ return CliState(api_url=default_api_url())
28
+
29
+ data = json.loads(self.path.read_text(encoding="utf-8"))
30
+ return CliState(
31
+ api_url=str(data.get("api_url") or default_api_url()),
32
+ access_token=data.get("access_token"),
33
+ refresh_token=data.get("refresh_token"),
34
+ default_workspace_id=data.get("default_workspace_id"),
35
+ )
36
+
37
+ def save(self, state: CliState) -> None:
38
+ self.path.parent.mkdir(parents=True, exist_ok=True)
39
+ payload: dict[str, Any] = {
40
+ "api_url": state.api_url,
41
+ "access_token": state.access_token,
42
+ "refresh_token": state.refresh_token,
43
+ "default_workspace_id": state.default_workspace_id,
44
+ }
45
+ fd = -1
46
+ tmp_path: Path | None = None
47
+ try:
48
+ fd, tmp_name = tempfile.mkstemp(
49
+ prefix=f".{self.path.name}.",
50
+ dir=self.path.parent,
51
+ )
52
+ tmp_path = Path(tmp_name)
53
+ os.fchmod(fd, 0o600)
54
+ with os.fdopen(fd, "w", encoding="utf-8") as handle:
55
+ fd = -1
56
+ json.dump(payload, handle, indent=2, sort_keys=True)
57
+ handle.write("\n")
58
+ os.replace(tmp_path, self.path)
59
+ tmp_path = None
60
+ finally:
61
+ if fd != -1:
62
+ os.close(fd)
63
+ if tmp_path is not None:
64
+ tmp_path.unlink(missing_ok=True)
65
+ self.path.chmod(0o600)
66
+
67
+ def clear_token(self) -> CliState:
68
+ state = self.load()
69
+ state.access_token = None
70
+ state.refresh_token = None
71
+ self.save(state)
72
+ return state
73
+
74
+
75
+ def default_api_url() -> str:
76
+ return os.environ.get("CORTEX_API_URL", DEFAULT_API_URL).rstrip("/")
77
+
78
+
79
+ def default_state_path() -> Path:
80
+ configured = os.environ.get("CORTEX_CLI_STATE")
81
+ if configured:
82
+ return Path(configured).expanduser()
83
+
84
+ config_home = os.environ.get("XDG_CONFIG_HOME")
85
+ if config_home:
86
+ return Path(config_home).expanduser() / "cortex" / "state.json"
87
+
88
+ return Path.home() / ".config" / "cortex" / "state.json"