htmlgraph 0.25.0__py3-none-any.whl → 0.26.2__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.
- htmlgraph/.htmlgraph/.session-warning-state.json +6 -0
- htmlgraph/.htmlgraph/agents.json +72 -0
- htmlgraph/.htmlgraph/htmlgraph.db +0 -0
- htmlgraph/__init__.py +1 -1
- htmlgraph/api/main.py +252 -47
- htmlgraph/api/templates/dashboard.html +11 -0
- htmlgraph/api/templates/partials/activity-feed.html +517 -8
- htmlgraph/cli.py +1 -1
- htmlgraph/config.py +173 -96
- htmlgraph/dashboard.html +632 -7237
- htmlgraph/db/schema.py +258 -9
- htmlgraph/hooks/.htmlgraph/.session-warning-state.json +6 -0
- htmlgraph/hooks/.htmlgraph/agents.json +72 -0
- htmlgraph/hooks/.htmlgraph/index.sqlite +0 -0
- htmlgraph/hooks/cigs_pretool_enforcer.py +2 -2
- htmlgraph/hooks/concurrent_sessions.py +208 -0
- htmlgraph/hooks/context.py +88 -10
- htmlgraph/hooks/drift_handler.py +24 -20
- htmlgraph/hooks/event_tracker.py +264 -189
- htmlgraph/hooks/orchestrator.py +6 -4
- htmlgraph/hooks/orchestrator_reflector.py +4 -4
- htmlgraph/hooks/pretooluse.py +63 -36
- htmlgraph/hooks/prompt_analyzer.py +14 -25
- htmlgraph/hooks/session_handler.py +123 -69
- htmlgraph/hooks/state_manager.py +7 -4
- htmlgraph/hooks/subagent_stop.py +3 -2
- htmlgraph/hooks/validator.py +15 -11
- htmlgraph/operations/fastapi_server.py +2 -2
- htmlgraph/orchestration/headless_spawner.py +489 -16
- htmlgraph/orchestration/live_events.py +377 -0
- htmlgraph/server.py +100 -203
- htmlgraph-0.26.2.data/data/htmlgraph/dashboard.html +812 -0
- {htmlgraph-0.25.0.dist-info → htmlgraph-0.26.2.dist-info}/METADATA +1 -1
- {htmlgraph-0.25.0.dist-info → htmlgraph-0.26.2.dist-info}/RECORD +40 -32
- htmlgraph-0.25.0.data/data/htmlgraph/dashboard.html +0 -7417
- {htmlgraph-0.25.0.data → htmlgraph-0.26.2.data}/data/htmlgraph/styles.css +0 -0
- {htmlgraph-0.25.0.data → htmlgraph-0.26.2.data}/data/htmlgraph/templates/AGENTS.md.template +0 -0
- {htmlgraph-0.25.0.data → htmlgraph-0.26.2.data}/data/htmlgraph/templates/CLAUDE.md.template +0 -0
- {htmlgraph-0.25.0.data → htmlgraph-0.26.2.data}/data/htmlgraph/templates/GEMINI.md.template +0 -0
- {htmlgraph-0.25.0.dist-info → htmlgraph-0.26.2.dist-info}/WHEEL +0 -0
- {htmlgraph-0.25.0.dist-info → htmlgraph-0.26.2.dist-info}/entry_points.txt +0 -0
htmlgraph/config.py
CHANGED
|
@@ -3,111 +3,188 @@ HtmlGraph Configuration Management.
|
|
|
3
3
|
|
|
4
4
|
This module provides centralized configuration management using Pydantic Settings,
|
|
5
5
|
allowing configuration from environment variables, .env files, and CLI arguments.
|
|
6
|
+
|
|
7
|
+
IMPORTANT: Database path functions (get_database_path, get_analytics_cache_path)
|
|
8
|
+
are lightweight and have NO dependencies. They can be imported anywhere.
|
|
6
9
|
"""
|
|
7
10
|
|
|
11
|
+
import os
|
|
8
12
|
from pathlib import Path
|
|
9
13
|
from typing import Any
|
|
10
14
|
|
|
11
|
-
|
|
15
|
+
# =============================================================================
|
|
16
|
+
# LIGHTWEIGHT DATABASE PATH FUNCTIONS (NO DEPENDENCIES)
|
|
17
|
+
# These MUST come before any heavy imports so spawners can use them
|
|
18
|
+
# =============================================================================
|
|
12
19
|
|
|
20
|
+
# Database filenames (SINGLE SOURCE OF TRUTH)
|
|
21
|
+
DATABASE_FILENAME = "htmlgraph.db" # Unified event database
|
|
22
|
+
ANALYTICS_CACHE_FILENAME = "index.sqlite" # Analytics cache (rebuildable)
|
|
13
23
|
|
|
14
|
-
class HtmlGraphConfig(BaseSettings):
|
|
15
|
-
"""Global HtmlGraph configuration using Pydantic Settings.
|
|
16
24
|
|
|
17
|
-
|
|
18
|
-
1. Environment variables (prefix: HTMLGRAPH_)
|
|
19
|
-
2. .env file
|
|
20
|
-
3. Direct instantiation with parameters
|
|
21
|
-
4. CLI argument overrides
|
|
25
|
+
def get_database_path(project_root: Path | str | None = None) -> Path:
|
|
22
26
|
"""
|
|
27
|
+
Get the unified database path for event tracking.
|
|
28
|
+
|
|
29
|
+
This is the SINGLE source of truth for database location.
|
|
30
|
+
All hooks, agents, and spawners MUST use this function.
|
|
31
|
+
|
|
32
|
+
Args:
|
|
33
|
+
project_root: Optional project root path. If None, uses HTMLGRAPH_PROJECT_ROOT
|
|
34
|
+
env var or current working directory.
|
|
35
|
+
|
|
36
|
+
Returns:
|
|
37
|
+
Path to htmlgraph.db (the unified event database)
|
|
38
|
+
"""
|
|
39
|
+
if project_root is None:
|
|
40
|
+
project_root = Path(os.environ.get("HTMLGRAPH_PROJECT_ROOT", os.getcwd()))
|
|
41
|
+
else:
|
|
42
|
+
project_root = Path(project_root)
|
|
43
|
+
|
|
44
|
+
return project_root / ".htmlgraph" / DATABASE_FILENAME
|
|
23
45
|
|
|
24
|
-
# Core paths
|
|
25
|
-
graph_dir: Path = Path.home() / ".htmlgraph"
|
|
26
|
-
|
|
27
|
-
# Feature tracking
|
|
28
|
-
features_dir: Path | None = None
|
|
29
|
-
sessions_dir: Path | None = None
|
|
30
|
-
spikes_dir: Path | None = None
|
|
31
|
-
tracks_dir: Path | None = None
|
|
32
|
-
archives_dir: Path | None = None
|
|
33
|
-
|
|
34
|
-
# CLI behavior
|
|
35
|
-
debug: bool = False
|
|
36
|
-
verbose: bool = False
|
|
37
|
-
auto_sync: bool = True
|
|
38
|
-
color_output: bool = True
|
|
39
|
-
|
|
40
|
-
# Session management
|
|
41
|
-
max_sessions: int = 100
|
|
42
|
-
session_retention_days: int = 30
|
|
43
|
-
auto_archive_sessions: bool = True
|
|
44
|
-
|
|
45
|
-
# Performance
|
|
46
|
-
max_query_results: int = 1000
|
|
47
|
-
cache_enabled: bool = True
|
|
48
|
-
cache_ttl_seconds: int = 3600
|
|
49
|
-
|
|
50
|
-
# Logging
|
|
51
|
-
log_level: str = "INFO"
|
|
52
|
-
log_file: Path | None = None
|
|
53
|
-
|
|
54
|
-
model_config = {
|
|
55
|
-
"env_prefix": "HTMLGRAPH_",
|
|
56
|
-
"env_file": ".env",
|
|
57
|
-
"case_sensitive": False,
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
def __init__(self, **data: Any) -> None:
|
|
61
|
-
"""Initialize config and compute derived paths."""
|
|
62
|
-
super().__init__(**data)
|
|
63
|
-
# Compute derived paths if not explicitly set
|
|
64
|
-
if self.features_dir is None:
|
|
65
|
-
self.features_dir = self.graph_dir / "features"
|
|
66
|
-
if self.sessions_dir is None:
|
|
67
|
-
self.sessions_dir = self.graph_dir / "sessions"
|
|
68
|
-
if self.spikes_dir is None:
|
|
69
|
-
self.spikes_dir = self.graph_dir / "spikes"
|
|
70
|
-
if self.tracks_dir is None:
|
|
71
|
-
self.tracks_dir = self.graph_dir / "tracks"
|
|
72
|
-
if self.archives_dir is None:
|
|
73
|
-
self.archives_dir = self.graph_dir / "archives"
|
|
74
|
-
|
|
75
|
-
def ensure_directories(self) -> None:
|
|
76
|
-
"""Create all configured directories if they don't exist."""
|
|
77
|
-
for directory in [
|
|
78
|
-
self.graph_dir,
|
|
79
|
-
self.features_dir,
|
|
80
|
-
self.sessions_dir,
|
|
81
|
-
self.spikes_dir,
|
|
82
|
-
self.tracks_dir,
|
|
83
|
-
self.archives_dir,
|
|
84
|
-
]:
|
|
85
|
-
if directory:
|
|
86
|
-
directory.mkdir(parents=True, exist_ok=True)
|
|
87
|
-
|
|
88
|
-
def get_config_dict(self) -> dict[str, Any]:
|
|
89
|
-
"""Get configuration as dictionary."""
|
|
90
|
-
return {
|
|
91
|
-
"graph_dir": str(self.graph_dir),
|
|
92
|
-
"features_dir": str(self.features_dir),
|
|
93
|
-
"sessions_dir": str(self.sessions_dir),
|
|
94
|
-
"spikes_dir": str(self.spikes_dir),
|
|
95
|
-
"tracks_dir": str(self.tracks_dir),
|
|
96
|
-
"archives_dir": str(self.archives_dir),
|
|
97
|
-
"debug": self.debug,
|
|
98
|
-
"verbose": self.verbose,
|
|
99
|
-
"auto_sync": self.auto_sync,
|
|
100
|
-
"color_output": self.color_output,
|
|
101
|
-
"max_sessions": self.max_sessions,
|
|
102
|
-
"session_retention_days": self.session_retention_days,
|
|
103
|
-
"auto_archive_sessions": self.auto_archive_sessions,
|
|
104
|
-
"max_query_results": self.max_query_results,
|
|
105
|
-
"cache_enabled": self.cache_enabled,
|
|
106
|
-
"cache_ttl_seconds": self.cache_ttl_seconds,
|
|
107
|
-
"log_level": self.log_level,
|
|
108
|
-
"log_file": str(self.log_file) if self.log_file else None,
|
|
109
|
-
}
|
|
110
46
|
|
|
47
|
+
def get_analytics_cache_path(project_root: Path | str | None = None) -> Path:
|
|
48
|
+
"""
|
|
49
|
+
Get the analytics cache database path.
|
|
50
|
+
|
|
51
|
+
This is for read-only analytics queries (rebuildable from events).
|
|
52
|
+
NOT for event tracking - use get_database_path() for that.
|
|
53
|
+
|
|
54
|
+
Args:
|
|
55
|
+
project_root: Optional project root path. If None, uses HTMLGRAPH_PROJECT_ROOT
|
|
56
|
+
env var or current working directory.
|
|
57
|
+
|
|
58
|
+
Returns:
|
|
59
|
+
Path to index.sqlite (analytics cache, gitignored)
|
|
60
|
+
"""
|
|
61
|
+
if project_root is None:
|
|
62
|
+
project_root = Path(os.environ.get("HTMLGRAPH_PROJECT_ROOT", os.getcwd()))
|
|
63
|
+
else:
|
|
64
|
+
project_root = Path(project_root)
|
|
65
|
+
|
|
66
|
+
return project_root / ".htmlgraph" / ANALYTICS_CACHE_FILENAME
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
# =============================================================================
|
|
70
|
+
# PYDANTIC CONFIGURATION (Heavy imports below - spawners don't need this)
|
|
71
|
+
# =============================================================================
|
|
72
|
+
|
|
73
|
+
try:
|
|
74
|
+
from pydantic_settings import BaseSettings
|
|
75
|
+
|
|
76
|
+
_PYDANTIC_AVAILABLE = True
|
|
77
|
+
except ImportError:
|
|
78
|
+
_PYDANTIC_AVAILABLE = False
|
|
79
|
+
BaseSettings = object # type: ignore
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
if _PYDANTIC_AVAILABLE:
|
|
83
|
+
|
|
84
|
+
class HtmlGraphConfig(BaseSettings):
|
|
85
|
+
"""Global HtmlGraph configuration using Pydantic Settings.
|
|
86
|
+
|
|
87
|
+
Configuration can be provided via:
|
|
88
|
+
1. Environment variables (prefix: HTMLGRAPH_)
|
|
89
|
+
2. .env file
|
|
90
|
+
3. Direct instantiation with parameters
|
|
91
|
+
4. CLI argument overrides
|
|
92
|
+
"""
|
|
93
|
+
|
|
94
|
+
# Core paths
|
|
95
|
+
graph_dir: Path = Path.home() / ".htmlgraph"
|
|
96
|
+
|
|
97
|
+
# Database paths (SINGLE SOURCE OF TRUTH)
|
|
98
|
+
# All hooks, agents, and spawners MUST use these via get_database_path()
|
|
99
|
+
database_filename: str = "htmlgraph.db" # Unified event database
|
|
100
|
+
analytics_cache_filename: str = "index.sqlite" # Analytics cache (rebuildable)
|
|
101
|
+
|
|
102
|
+
# Feature tracking
|
|
103
|
+
features_dir: Path | None = None
|
|
104
|
+
sessions_dir: Path | None = None
|
|
105
|
+
spikes_dir: Path | None = None
|
|
106
|
+
tracks_dir: Path | None = None
|
|
107
|
+
archives_dir: Path | None = None
|
|
108
|
+
|
|
109
|
+
# CLI behavior
|
|
110
|
+
debug: bool = False
|
|
111
|
+
verbose: bool = False
|
|
112
|
+
auto_sync: bool = True
|
|
113
|
+
color_output: bool = True
|
|
114
|
+
|
|
115
|
+
# Session management
|
|
116
|
+
max_sessions: int = 100
|
|
117
|
+
session_retention_days: int = 30
|
|
118
|
+
auto_archive_sessions: bool = True
|
|
119
|
+
|
|
120
|
+
# Performance
|
|
121
|
+
max_query_results: int = 1000
|
|
122
|
+
cache_enabled: bool = True
|
|
123
|
+
cache_ttl_seconds: int = 3600
|
|
124
|
+
|
|
125
|
+
# Logging
|
|
126
|
+
log_level: str = "INFO"
|
|
127
|
+
log_file: Path | None = None
|
|
128
|
+
|
|
129
|
+
model_config = {
|
|
130
|
+
"env_prefix": "HTMLGRAPH_",
|
|
131
|
+
"env_file": ".env",
|
|
132
|
+
"case_sensitive": False,
|
|
133
|
+
}
|
|
111
134
|
|
|
112
|
-
|
|
113
|
-
config
|
|
135
|
+
def __init__(self, **data: Any) -> None:
|
|
136
|
+
"""Initialize config and compute derived paths."""
|
|
137
|
+
super().__init__(**data)
|
|
138
|
+
# Compute derived paths if not explicitly set
|
|
139
|
+
if self.features_dir is None:
|
|
140
|
+
self.features_dir = self.graph_dir / "features"
|
|
141
|
+
if self.sessions_dir is None:
|
|
142
|
+
self.sessions_dir = self.graph_dir / "sessions"
|
|
143
|
+
if self.spikes_dir is None:
|
|
144
|
+
self.spikes_dir = self.graph_dir / "spikes"
|
|
145
|
+
if self.tracks_dir is None:
|
|
146
|
+
self.tracks_dir = self.graph_dir / "tracks"
|
|
147
|
+
if self.archives_dir is None:
|
|
148
|
+
self.archives_dir = self.graph_dir / "archives"
|
|
149
|
+
|
|
150
|
+
def ensure_directories(self) -> None:
|
|
151
|
+
"""Create all configured directories if they don't exist."""
|
|
152
|
+
for directory in [
|
|
153
|
+
self.graph_dir,
|
|
154
|
+
self.features_dir,
|
|
155
|
+
self.sessions_dir,
|
|
156
|
+
self.spikes_dir,
|
|
157
|
+
self.tracks_dir,
|
|
158
|
+
self.archives_dir,
|
|
159
|
+
]:
|
|
160
|
+
if directory:
|
|
161
|
+
directory.mkdir(parents=True, exist_ok=True)
|
|
162
|
+
|
|
163
|
+
def get_config_dict(self) -> dict[str, Any]:
|
|
164
|
+
"""Get configuration as dictionary."""
|
|
165
|
+
return {
|
|
166
|
+
"graph_dir": str(self.graph_dir),
|
|
167
|
+
"features_dir": str(self.features_dir),
|
|
168
|
+
"sessions_dir": str(self.sessions_dir),
|
|
169
|
+
"spikes_dir": str(self.spikes_dir),
|
|
170
|
+
"tracks_dir": str(self.tracks_dir),
|
|
171
|
+
"archives_dir": str(self.archives_dir),
|
|
172
|
+
"debug": self.debug,
|
|
173
|
+
"verbose": self.verbose,
|
|
174
|
+
"auto_sync": self.auto_sync,
|
|
175
|
+
"color_output": self.color_output,
|
|
176
|
+
"max_sessions": self.max_sessions,
|
|
177
|
+
"session_retention_days": self.session_retention_days,
|
|
178
|
+
"auto_archive_sessions": self.auto_archive_sessions,
|
|
179
|
+
"max_query_results": self.max_query_results,
|
|
180
|
+
"cache_enabled": self.cache_enabled,
|
|
181
|
+
"cache_ttl_seconds": self.cache_ttl_seconds,
|
|
182
|
+
"log_level": self.log_level,
|
|
183
|
+
"log_file": str(self.log_file) if self.log_file else None,
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
# Global configuration instance
|
|
187
|
+
config: HtmlGraphConfig = HtmlGraphConfig()
|
|
188
|
+
else:
|
|
189
|
+
# Pydantic not available - config object won't work but database functions will
|
|
190
|
+
config = None # type: ignore
|