htmlgraph 0.9.3__py3-none-any.whl → 0.27.5__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 +173 -17
- htmlgraph/__init__.pyi +123 -0
- htmlgraph/agent_detection.py +127 -0
- htmlgraph/agent_registry.py +45 -30
- htmlgraph/agents.py +160 -107
- htmlgraph/analytics/__init__.py +9 -2
- htmlgraph/analytics/cli.py +190 -51
- htmlgraph/analytics/cost_analyzer.py +391 -0
- htmlgraph/analytics/cost_monitor.py +664 -0
- htmlgraph/analytics/cost_reporter.py +675 -0
- htmlgraph/analytics/cross_session.py +617 -0
- htmlgraph/analytics/dependency.py +192 -100
- htmlgraph/analytics/pattern_learning.py +771 -0
- htmlgraph/analytics/session_graph.py +707 -0
- htmlgraph/analytics/strategic/__init__.py +80 -0
- htmlgraph/analytics/strategic/cost_optimizer.py +611 -0
- htmlgraph/analytics/strategic/pattern_detector.py +876 -0
- htmlgraph/analytics/strategic/preference_manager.py +709 -0
- htmlgraph/analytics/strategic/suggestion_engine.py +747 -0
- htmlgraph/analytics/work_type.py +190 -14
- htmlgraph/analytics_index.py +135 -51
- htmlgraph/api/__init__.py +3 -0
- htmlgraph/api/cost_alerts_websocket.py +416 -0
- htmlgraph/api/main.py +2498 -0
- htmlgraph/api/static/htmx.min.js +1 -0
- htmlgraph/api/static/style-redesign.css +1344 -0
- htmlgraph/api/static/style.css +1079 -0
- htmlgraph/api/templates/dashboard-redesign.html +1366 -0
- htmlgraph/api/templates/dashboard.html +794 -0
- htmlgraph/api/templates/partials/activity-feed-hierarchical.html +326 -0
- htmlgraph/api/templates/partials/activity-feed.html +1100 -0
- htmlgraph/api/templates/partials/agents-redesign.html +317 -0
- htmlgraph/api/templates/partials/agents.html +317 -0
- htmlgraph/api/templates/partials/event-traces.html +373 -0
- htmlgraph/api/templates/partials/features-kanban-redesign.html +509 -0
- htmlgraph/api/templates/partials/features.html +578 -0
- htmlgraph/api/templates/partials/metrics-redesign.html +346 -0
- htmlgraph/api/templates/partials/metrics.html +346 -0
- htmlgraph/api/templates/partials/orchestration-redesign.html +443 -0
- htmlgraph/api/templates/partials/orchestration.html +198 -0
- htmlgraph/api/templates/partials/spawners.html +375 -0
- htmlgraph/api/templates/partials/work-items.html +613 -0
- htmlgraph/api/websocket.py +538 -0
- htmlgraph/archive/__init__.py +24 -0
- htmlgraph/archive/bloom.py +234 -0
- htmlgraph/archive/fts.py +297 -0
- htmlgraph/archive/manager.py +583 -0
- htmlgraph/archive/search.py +244 -0
- htmlgraph/atomic_ops.py +560 -0
- htmlgraph/attribute_index.py +208 -0
- htmlgraph/bounded_paths.py +539 -0
- htmlgraph/builders/__init__.py +14 -0
- htmlgraph/builders/base.py +118 -29
- htmlgraph/builders/bug.py +150 -0
- htmlgraph/builders/chore.py +119 -0
- htmlgraph/builders/epic.py +150 -0
- htmlgraph/builders/feature.py +31 -6
- htmlgraph/builders/insight.py +195 -0
- htmlgraph/builders/metric.py +217 -0
- htmlgraph/builders/pattern.py +202 -0
- htmlgraph/builders/phase.py +162 -0
- htmlgraph/builders/spike.py +52 -19
- htmlgraph/builders/track.py +148 -72
- htmlgraph/cigs/__init__.py +81 -0
- htmlgraph/cigs/autonomy.py +385 -0
- htmlgraph/cigs/cost.py +475 -0
- htmlgraph/cigs/messages_basic.py +472 -0
- htmlgraph/cigs/messaging.py +365 -0
- htmlgraph/cigs/models.py +771 -0
- htmlgraph/cigs/pattern_storage.py +427 -0
- htmlgraph/cigs/patterns.py +503 -0
- htmlgraph/cigs/posttool_analyzer.py +234 -0
- htmlgraph/cigs/reporter.py +818 -0
- htmlgraph/cigs/tracker.py +317 -0
- htmlgraph/cli/.htmlgraph/.session-warning-state.json +6 -0
- htmlgraph/cli/.htmlgraph/agents.json +72 -0
- htmlgraph/cli/.htmlgraph/htmlgraph.db +0 -0
- htmlgraph/cli/__init__.py +42 -0
- htmlgraph/cli/__main__.py +6 -0
- htmlgraph/cli/analytics.py +1424 -0
- htmlgraph/cli/base.py +685 -0
- htmlgraph/cli/constants.py +206 -0
- htmlgraph/cli/core.py +954 -0
- htmlgraph/cli/main.py +147 -0
- htmlgraph/cli/models.py +475 -0
- htmlgraph/cli/templates/__init__.py +1 -0
- htmlgraph/cli/templates/cost_dashboard.py +399 -0
- htmlgraph/cli/work/__init__.py +239 -0
- htmlgraph/cli/work/browse.py +115 -0
- htmlgraph/cli/work/features.py +568 -0
- htmlgraph/cli/work/orchestration.py +676 -0
- htmlgraph/cli/work/report.py +728 -0
- htmlgraph/cli/work/sessions.py +466 -0
- htmlgraph/cli/work/snapshot.py +559 -0
- htmlgraph/cli/work/tracks.py +486 -0
- htmlgraph/cli_commands/__init__.py +1 -0
- htmlgraph/cli_commands/feature.py +195 -0
- htmlgraph/cli_framework.py +115 -0
- htmlgraph/collections/__init__.py +18 -0
- htmlgraph/collections/base.py +415 -98
- htmlgraph/collections/bug.py +53 -0
- htmlgraph/collections/chore.py +53 -0
- htmlgraph/collections/epic.py +53 -0
- htmlgraph/collections/feature.py +12 -26
- htmlgraph/collections/insight.py +100 -0
- htmlgraph/collections/metric.py +92 -0
- htmlgraph/collections/pattern.py +97 -0
- htmlgraph/collections/phase.py +53 -0
- htmlgraph/collections/session.py +194 -0
- htmlgraph/collections/spike.py +56 -16
- htmlgraph/collections/task_delegation.py +241 -0
- htmlgraph/collections/todo.py +511 -0
- htmlgraph/collections/traces.py +487 -0
- htmlgraph/config/cost_models.json +56 -0
- htmlgraph/config.py +190 -0
- htmlgraph/context_analytics.py +344 -0
- htmlgraph/converter.py +216 -28
- htmlgraph/cost_analysis/__init__.py +5 -0
- htmlgraph/cost_analysis/analyzer.py +438 -0
- htmlgraph/dashboard.html +2406 -307
- htmlgraph/dashboard.html.backup +6592 -0
- htmlgraph/dashboard.html.bak +7181 -0
- htmlgraph/dashboard.html.bak2 +7231 -0
- htmlgraph/dashboard.html.bak3 +7232 -0
- htmlgraph/db/__init__.py +38 -0
- htmlgraph/db/queries.py +790 -0
- htmlgraph/db/schema.py +1788 -0
- htmlgraph/decorators.py +317 -0
- htmlgraph/dependency_models.py +19 -2
- htmlgraph/deploy.py +142 -125
- htmlgraph/deployment_models.py +474 -0
- htmlgraph/docs/API_REFERENCE.md +841 -0
- htmlgraph/docs/HTTP_API.md +750 -0
- htmlgraph/docs/INTEGRATION_GUIDE.md +752 -0
- htmlgraph/docs/ORCHESTRATION_PATTERNS.md +717 -0
- htmlgraph/docs/README.md +532 -0
- htmlgraph/docs/__init__.py +77 -0
- htmlgraph/docs/docs_version.py +55 -0
- htmlgraph/docs/metadata.py +93 -0
- htmlgraph/docs/migrations.py +232 -0
- htmlgraph/docs/template_engine.py +143 -0
- htmlgraph/docs/templates/_sections/cli_reference.md.j2 +52 -0
- htmlgraph/docs/templates/_sections/core_concepts.md.j2 +29 -0
- htmlgraph/docs/templates/_sections/sdk_basics.md.j2 +69 -0
- htmlgraph/docs/templates/base_agents.md.j2 +78 -0
- htmlgraph/docs/templates/example_user_override.md.j2 +47 -0
- htmlgraph/docs/version_check.py +163 -0
- htmlgraph/edge_index.py +182 -27
- htmlgraph/error_handler.py +544 -0
- htmlgraph/event_log.py +100 -52
- htmlgraph/event_migration.py +13 -4
- htmlgraph/exceptions.py +49 -0
- htmlgraph/file_watcher.py +101 -28
- htmlgraph/find_api.py +75 -63
- htmlgraph/git_events.py +145 -63
- htmlgraph/graph.py +1122 -106
- 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/__init__.py +45 -0
- htmlgraph/hooks/bootstrap.py +169 -0
- htmlgraph/hooks/cigs_pretool_enforcer.py +354 -0
- htmlgraph/hooks/concurrent_sessions.py +208 -0
- htmlgraph/hooks/context.py +350 -0
- htmlgraph/hooks/drift_handler.py +525 -0
- htmlgraph/hooks/event_tracker.py +1314 -0
- htmlgraph/hooks/git_commands.py +175 -0
- htmlgraph/hooks/hooks-config.example.json +12 -0
- htmlgraph/hooks/installer.py +343 -0
- htmlgraph/hooks/orchestrator.py +674 -0
- htmlgraph/hooks/orchestrator_reflector.py +223 -0
- htmlgraph/hooks/post-checkout.sh +28 -0
- htmlgraph/hooks/post-commit.sh +24 -0
- htmlgraph/hooks/post-merge.sh +26 -0
- htmlgraph/hooks/post_tool_use_failure.py +273 -0
- htmlgraph/hooks/post_tool_use_handler.py +257 -0
- htmlgraph/hooks/posttooluse.py +408 -0
- htmlgraph/hooks/pre-commit.sh +94 -0
- htmlgraph/hooks/pre-push.sh +28 -0
- htmlgraph/hooks/pretooluse.py +819 -0
- htmlgraph/hooks/prompt_analyzer.py +637 -0
- htmlgraph/hooks/session_handler.py +668 -0
- htmlgraph/hooks/session_summary.py +395 -0
- htmlgraph/hooks/state_manager.py +504 -0
- htmlgraph/hooks/subagent_detection.py +202 -0
- htmlgraph/hooks/subagent_stop.py +369 -0
- htmlgraph/hooks/task_enforcer.py +255 -0
- htmlgraph/hooks/task_validator.py +177 -0
- htmlgraph/hooks/validator.py +628 -0
- htmlgraph/ids.py +41 -27
- htmlgraph/index.d.ts +286 -0
- htmlgraph/learning.py +767 -0
- htmlgraph/mcp_server.py +69 -23
- htmlgraph/models.py +1586 -87
- htmlgraph/operations/README.md +62 -0
- htmlgraph/operations/__init__.py +79 -0
- htmlgraph/operations/analytics.py +339 -0
- htmlgraph/operations/bootstrap.py +289 -0
- htmlgraph/operations/events.py +244 -0
- htmlgraph/operations/fastapi_server.py +231 -0
- htmlgraph/operations/hooks.py +350 -0
- htmlgraph/operations/initialization.py +597 -0
- htmlgraph/operations/initialization.py.backup +228 -0
- htmlgraph/operations/server.py +303 -0
- htmlgraph/orchestration/__init__.py +58 -0
- htmlgraph/orchestration/claude_launcher.py +179 -0
- htmlgraph/orchestration/command_builder.py +72 -0
- htmlgraph/orchestration/headless_spawner.py +281 -0
- htmlgraph/orchestration/live_events.py +377 -0
- htmlgraph/orchestration/model_selection.py +327 -0
- htmlgraph/orchestration/plugin_manager.py +140 -0
- htmlgraph/orchestration/prompts.py +137 -0
- htmlgraph/orchestration/spawner_event_tracker.py +383 -0
- htmlgraph/orchestration/spawners/__init__.py +16 -0
- htmlgraph/orchestration/spawners/base.py +194 -0
- htmlgraph/orchestration/spawners/claude.py +173 -0
- htmlgraph/orchestration/spawners/codex.py +435 -0
- htmlgraph/orchestration/spawners/copilot.py +294 -0
- htmlgraph/orchestration/spawners/gemini.py +471 -0
- htmlgraph/orchestration/subprocess_runner.py +36 -0
- htmlgraph/orchestration/task_coordination.py +343 -0
- htmlgraph/orchestration.md +563 -0
- htmlgraph/orchestrator-system-prompt-optimized.txt +863 -0
- htmlgraph/orchestrator.py +669 -0
- htmlgraph/orchestrator_config.py +357 -0
- htmlgraph/orchestrator_mode.py +328 -0
- htmlgraph/orchestrator_validator.py +133 -0
- htmlgraph/parallel.py +646 -0
- htmlgraph/parser.py +160 -35
- htmlgraph/path_query.py +608 -0
- htmlgraph/pattern_matcher.py +636 -0
- htmlgraph/planning.py +147 -52
- htmlgraph/pydantic_models.py +476 -0
- htmlgraph/quality_gates.py +350 -0
- htmlgraph/query_builder.py +109 -72
- htmlgraph/query_composer.py +509 -0
- htmlgraph/reflection.py +443 -0
- htmlgraph/refs.py +344 -0
- htmlgraph/repo_hash.py +512 -0
- htmlgraph/repositories/__init__.py +292 -0
- htmlgraph/repositories/analytics_repository.py +455 -0
- htmlgraph/repositories/analytics_repository_standard.py +628 -0
- htmlgraph/repositories/feature_repository.py +581 -0
- htmlgraph/repositories/feature_repository_htmlfile.py +668 -0
- htmlgraph/repositories/feature_repository_memory.py +607 -0
- htmlgraph/repositories/feature_repository_sqlite.py +858 -0
- htmlgraph/repositories/filter_service.py +620 -0
- htmlgraph/repositories/filter_service_standard.py +445 -0
- htmlgraph/repositories/shared_cache.py +621 -0
- htmlgraph/repositories/shared_cache_memory.py +395 -0
- htmlgraph/repositories/track_repository.py +552 -0
- htmlgraph/repositories/track_repository_htmlfile.py +619 -0
- htmlgraph/repositories/track_repository_memory.py +508 -0
- htmlgraph/repositories/track_repository_sqlite.py +711 -0
- htmlgraph/routing.py +8 -19
- htmlgraph/scripts/deploy.py +1 -2
- htmlgraph/sdk/__init__.py +398 -0
- htmlgraph/sdk/__init__.pyi +14 -0
- htmlgraph/sdk/analytics/__init__.py +19 -0
- htmlgraph/sdk/analytics/engine.py +155 -0
- htmlgraph/sdk/analytics/helpers.py +178 -0
- htmlgraph/sdk/analytics/registry.py +109 -0
- htmlgraph/sdk/base.py +484 -0
- htmlgraph/sdk/constants.py +216 -0
- htmlgraph/sdk/core.pyi +308 -0
- htmlgraph/sdk/discovery.py +120 -0
- htmlgraph/sdk/help/__init__.py +12 -0
- htmlgraph/sdk/help/mixin.py +699 -0
- htmlgraph/sdk/mixins/__init__.py +15 -0
- htmlgraph/sdk/mixins/attribution.py +113 -0
- htmlgraph/sdk/mixins/mixin.py +410 -0
- htmlgraph/sdk/operations/__init__.py +12 -0
- htmlgraph/sdk/operations/mixin.py +427 -0
- htmlgraph/sdk/orchestration/__init__.py +17 -0
- htmlgraph/sdk/orchestration/coordinator.py +203 -0
- htmlgraph/sdk/orchestration/spawner.py +204 -0
- htmlgraph/sdk/planning/__init__.py +19 -0
- htmlgraph/sdk/planning/bottlenecks.py +93 -0
- htmlgraph/sdk/planning/mixin.py +211 -0
- htmlgraph/sdk/planning/parallel.py +186 -0
- htmlgraph/sdk/planning/queue.py +210 -0
- htmlgraph/sdk/planning/recommendations.py +87 -0
- htmlgraph/sdk/planning/smart_planning.py +319 -0
- htmlgraph/sdk/session/__init__.py +19 -0
- htmlgraph/sdk/session/continuity.py +57 -0
- htmlgraph/sdk/session/handoff.py +110 -0
- htmlgraph/sdk/session/info.py +309 -0
- htmlgraph/sdk/session/manager.py +103 -0
- htmlgraph/sdk/strategic/__init__.py +26 -0
- htmlgraph/sdk/strategic/mixin.py +563 -0
- htmlgraph/server.py +685 -180
- htmlgraph/services/__init__.py +10 -0
- htmlgraph/services/claiming.py +199 -0
- htmlgraph/session_hooks.py +300 -0
- htmlgraph/session_manager.py +1392 -175
- htmlgraph/session_registry.py +587 -0
- htmlgraph/session_state.py +436 -0
- htmlgraph/session_warning.py +201 -0
- htmlgraph/sessions/__init__.py +23 -0
- htmlgraph/sessions/handoff.py +756 -0
- htmlgraph/setup.py +34 -17
- htmlgraph/spike_index.py +143 -0
- htmlgraph/sync_docs.py +12 -15
- htmlgraph/system_prompts.py +450 -0
- htmlgraph/templates/AGENTS.md.template +366 -0
- htmlgraph/templates/CLAUDE.md.template +97 -0
- htmlgraph/templates/GEMINI.md.template +87 -0
- htmlgraph/templates/orchestration-view.html +350 -0
- htmlgraph/track_builder.py +146 -15
- htmlgraph/track_manager.py +69 -21
- htmlgraph/transcript.py +890 -0
- htmlgraph/transcript_analytics.py +699 -0
- htmlgraph/types.py +323 -0
- htmlgraph/validation.py +115 -0
- htmlgraph/watch.py +8 -5
- htmlgraph/work_type_utils.py +3 -2
- {htmlgraph-0.9.3.data → htmlgraph-0.27.5.data}/data/htmlgraph/dashboard.html +2406 -307
- htmlgraph-0.27.5.data/data/htmlgraph/templates/AGENTS.md.template +366 -0
- htmlgraph-0.27.5.data/data/htmlgraph/templates/CLAUDE.md.template +97 -0
- htmlgraph-0.27.5.data/data/htmlgraph/templates/GEMINI.md.template +87 -0
- {htmlgraph-0.9.3.dist-info → htmlgraph-0.27.5.dist-info}/METADATA +97 -64
- htmlgraph-0.27.5.dist-info/RECORD +337 -0
- {htmlgraph-0.9.3.dist-info → htmlgraph-0.27.5.dist-info}/entry_points.txt +1 -1
- htmlgraph/cli.py +0 -2688
- htmlgraph/sdk.py +0 -709
- htmlgraph-0.9.3.dist-info/RECORD +0 -61
- {htmlgraph-0.9.3.data → htmlgraph-0.27.5.data}/data/htmlgraph/styles.css +0 -0
- {htmlgraph-0.9.3.dist-info → htmlgraph-0.27.5.dist-info}/WHEEL +0 -0
htmlgraph/routing.py
CHANGED
|
@@ -41,15 +41,12 @@ class AgentCapabilityRegistry:
|
|
|
41
41
|
# Returns: [AgentProfile(agent_id='claude', ...)]
|
|
42
42
|
"""
|
|
43
43
|
|
|
44
|
-
def __init__(self):
|
|
44
|
+
def __init__(self) -> None:
|
|
45
45
|
"""Initialize empty registry."""
|
|
46
46
|
self.agents: dict[str, AgentProfile] = {}
|
|
47
47
|
|
|
48
48
|
def register_agent(
|
|
49
|
-
self,
|
|
50
|
-
agent_id: str,
|
|
51
|
-
capabilities: list[str],
|
|
52
|
-
wip_limit: int = 5
|
|
49
|
+
self, agent_id: str, capabilities: list[str], wip_limit: int = 5
|
|
53
50
|
) -> None:
|
|
54
51
|
"""
|
|
55
52
|
Register an agent with capabilities.
|
|
@@ -63,7 +60,7 @@ class AgentCapabilityRegistry:
|
|
|
63
60
|
agent_id=agent_id,
|
|
64
61
|
capabilities=capabilities,
|
|
65
62
|
wip_limit=wip_limit,
|
|
66
|
-
current_wip=0
|
|
63
|
+
current_wip=0,
|
|
67
64
|
)
|
|
68
65
|
|
|
69
66
|
def unregister_agent(self, agent_id: str) -> bool:
|
|
@@ -158,9 +155,7 @@ class CapabilityMatcher:
|
|
|
158
155
|
|
|
159
156
|
@staticmethod
|
|
160
157
|
def score_agent_task_fit(
|
|
161
|
-
agent_profile: AgentProfile,
|
|
162
|
-
task: Node,
|
|
163
|
-
include_workload: bool = True
|
|
158
|
+
agent_profile: AgentProfile, task: Node, include_workload: bool = True
|
|
164
159
|
) -> float:
|
|
165
160
|
"""
|
|
166
161
|
Calculate fit score for agent-task pair.
|
|
@@ -211,9 +206,7 @@ class CapabilityMatcher:
|
|
|
211
206
|
|
|
212
207
|
@staticmethod
|
|
213
208
|
def find_best_agent(
|
|
214
|
-
agents: list[AgentProfile],
|
|
215
|
-
task: Node,
|
|
216
|
-
min_score: float = 0.0
|
|
209
|
+
agents: list[AgentProfile], task: Node, min_score: float = 0.0
|
|
217
210
|
) -> AgentProfile | None:
|
|
218
211
|
"""
|
|
219
212
|
Find the best agent for a task.
|
|
@@ -242,9 +235,7 @@ class CapabilityMatcher:
|
|
|
242
235
|
|
|
243
236
|
|
|
244
237
|
def route_task_to_agent(
|
|
245
|
-
task: Node,
|
|
246
|
-
registry: AgentCapabilityRegistry,
|
|
247
|
-
allow_unmatched: bool = False
|
|
238
|
+
task: Node, registry: AgentCapabilityRegistry, allow_unmatched: bool = False
|
|
248
239
|
) -> tuple[AgentProfile | None, float]:
|
|
249
240
|
"""
|
|
250
241
|
Route a single task to the best capable agent.
|
|
@@ -276,7 +267,7 @@ def route_task_to_agent(
|
|
|
276
267
|
best_agent = CapabilityMatcher.find_best_agent(
|
|
277
268
|
agents_to_consider,
|
|
278
269
|
task,
|
|
279
|
-
min_score=0.0 if not allow_unmatched else -float("inf")
|
|
270
|
+
min_score=0.0 if not allow_unmatched else -float("inf"),
|
|
280
271
|
)
|
|
281
272
|
|
|
282
273
|
if best_agent:
|
|
@@ -287,9 +278,7 @@ def route_task_to_agent(
|
|
|
287
278
|
|
|
288
279
|
|
|
289
280
|
def route_tasks_to_agents(
|
|
290
|
-
tasks: list[Node],
|
|
291
|
-
registry: AgentCapabilityRegistry,
|
|
292
|
-
allow_unmatched: bool = False
|
|
281
|
+
tasks: list[Node], registry: AgentCapabilityRegistry, allow_unmatched: bool = False
|
|
293
282
|
) -> dict[str, tuple[AgentProfile | None, float]]:
|
|
294
283
|
"""
|
|
295
284
|
Route multiple tasks to best agents.
|
htmlgraph/scripts/deploy.py
CHANGED
|
@@ -18,7 +18,6 @@ import argparse
|
|
|
18
18
|
import subprocess
|
|
19
19
|
import sys
|
|
20
20
|
from pathlib import Path
|
|
21
|
-
from typing import Optional
|
|
22
21
|
|
|
23
22
|
|
|
24
23
|
def get_project_root() -> Path:
|
|
@@ -50,7 +49,7 @@ def run_deploy_script(args: list[str]) -> int:
|
|
|
50
49
|
return 1
|
|
51
50
|
|
|
52
51
|
|
|
53
|
-
def main(argv:
|
|
52
|
+
def main(argv: list[str] | None = None) -> int:
|
|
54
53
|
"""
|
|
55
54
|
Main entry point for htmlgraph-deploy command.
|
|
56
55
|
|
|
@@ -0,0 +1,398 @@
|
|
|
1
|
+
"""
|
|
2
|
+
HtmlGraph SDK - Modular Architecture
|
|
3
|
+
|
|
4
|
+
This package provides a fluent, ergonomic API for AI agents with:
|
|
5
|
+
- Auto-discovery of .htmlgraph directory
|
|
6
|
+
- Method chaining for all operations
|
|
7
|
+
- Context managers for auto-save
|
|
8
|
+
- Batch operations
|
|
9
|
+
- Minimal boilerplate
|
|
10
|
+
|
|
11
|
+
The SDK is composed from specialized mixins:
|
|
12
|
+
- AnalyticsRegistry: Analytics properties (analytics, dep_analytics, context, etc.)
|
|
13
|
+
- SessionManagerMixin: Session lifecycle (start_session, end_session)
|
|
14
|
+
- SessionHandoffMixin: Handoff operations (set_session_handoff, end_session_with_handoff)
|
|
15
|
+
- SessionContinuityMixin: Continuity (continue_from_last)
|
|
16
|
+
- SessionInfoMixin: Session info (get_session_start_info, get_active_work_item)
|
|
17
|
+
- PlanningMixin: Planning methods (find_bottlenecks, recommend_next_work, etc.)
|
|
18
|
+
- OrchestrationMixin: Subagent spawning (spawn_explorer, spawn_coder, orchestrate)
|
|
19
|
+
- OperationsMixin: Server, hooks, events (start_server, install_hooks, etc.)
|
|
20
|
+
- CoreMixin: Database, refs, utilities (db, query, ref, reload, etc.)
|
|
21
|
+
- TaskAttributionMixin: Task attribution (get_task_attribution, get_subagent_work)
|
|
22
|
+
- HelpMixin: Help system (help, __dir__)
|
|
23
|
+
|
|
24
|
+
Public API exports maintain backward compatibility.
|
|
25
|
+
All existing imports continue to work:
|
|
26
|
+
from htmlgraph import SDK # Still works
|
|
27
|
+
from htmlgraph.sdk import SDK # Also works
|
|
28
|
+
"""
|
|
29
|
+
|
|
30
|
+
from __future__ import annotations
|
|
31
|
+
|
|
32
|
+
import os
|
|
33
|
+
from pathlib import Path
|
|
34
|
+
from typing import Any
|
|
35
|
+
|
|
36
|
+
from htmlgraph.agent_detection import detect_agent_name
|
|
37
|
+
from htmlgraph.agents import AgentInterface
|
|
38
|
+
from htmlgraph.collections import (
|
|
39
|
+
BaseCollection,
|
|
40
|
+
BugCollection,
|
|
41
|
+
ChoreCollection,
|
|
42
|
+
EpicCollection,
|
|
43
|
+
FeatureCollection,
|
|
44
|
+
PhaseCollection,
|
|
45
|
+
SpikeCollection,
|
|
46
|
+
TaskDelegationCollection,
|
|
47
|
+
TodoCollection,
|
|
48
|
+
)
|
|
49
|
+
from htmlgraph.collections.insight import InsightCollection
|
|
50
|
+
from htmlgraph.collections.metric import MetricCollection
|
|
51
|
+
from htmlgraph.collections.pattern import PatternCollection
|
|
52
|
+
from htmlgraph.collections.session import SessionCollection
|
|
53
|
+
from htmlgraph.db.schema import HtmlGraphDB
|
|
54
|
+
from htmlgraph.graph import HtmlGraph
|
|
55
|
+
from htmlgraph.sdk.analytics import AnalyticsRegistry
|
|
56
|
+
from htmlgraph.sdk.base import BaseSDK
|
|
57
|
+
from htmlgraph.sdk.constants import SDKSettings
|
|
58
|
+
from htmlgraph.sdk.discovery import (
|
|
59
|
+
auto_discover_agent,
|
|
60
|
+
discover_htmlgraph_dir,
|
|
61
|
+
find_project_root,
|
|
62
|
+
)
|
|
63
|
+
from htmlgraph.sdk.help import HelpMixin
|
|
64
|
+
from htmlgraph.sdk.mixins import CoreMixin, TaskAttributionMixin
|
|
65
|
+
from htmlgraph.sdk.operations import OperationsMixin
|
|
66
|
+
from htmlgraph.sdk.orchestration import OrchestrationMixin
|
|
67
|
+
from htmlgraph.sdk.planning import PlanningMixin
|
|
68
|
+
from htmlgraph.sdk.session import (
|
|
69
|
+
SessionContinuityMixin,
|
|
70
|
+
SessionHandoffMixin,
|
|
71
|
+
SessionInfoMixin,
|
|
72
|
+
SessionManagerMixin,
|
|
73
|
+
)
|
|
74
|
+
from htmlgraph.session_manager import SessionManager
|
|
75
|
+
from htmlgraph.session_warning import check_and_show_warning
|
|
76
|
+
from htmlgraph.system_prompts import SystemPromptManager
|
|
77
|
+
from htmlgraph.track_builder import TrackCollection
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
class SDK(
|
|
81
|
+
AnalyticsRegistry,
|
|
82
|
+
SessionManagerMixin,
|
|
83
|
+
SessionHandoffMixin,
|
|
84
|
+
SessionContinuityMixin,
|
|
85
|
+
SessionInfoMixin,
|
|
86
|
+
PlanningMixin,
|
|
87
|
+
OrchestrationMixin,
|
|
88
|
+
OperationsMixin,
|
|
89
|
+
CoreMixin,
|
|
90
|
+
TaskAttributionMixin,
|
|
91
|
+
HelpMixin,
|
|
92
|
+
):
|
|
93
|
+
"""
|
|
94
|
+
Main SDK interface for AI agents.
|
|
95
|
+
|
|
96
|
+
Auto-discovers .htmlgraph directory and provides fluent API for all collections.
|
|
97
|
+
|
|
98
|
+
Available Collections:
|
|
99
|
+
- features: Feature work items with builder support
|
|
100
|
+
- bugs: Bug reports
|
|
101
|
+
- chores: Maintenance and chore tasks
|
|
102
|
+
- spikes: Investigation and research spikes
|
|
103
|
+
- epics: Large bodies of work
|
|
104
|
+
- phases: Project phases
|
|
105
|
+
- sessions: Agent sessions
|
|
106
|
+
- tracks: Work tracks
|
|
107
|
+
- agents: Agent information
|
|
108
|
+
- todos: Persistent task tracking (mirrors TodoWrite API)
|
|
109
|
+
- patterns: Workflow patterns (optimal/anti-pattern)
|
|
110
|
+
- insights: Session health insights
|
|
111
|
+
- metrics: Aggregated time-series metrics
|
|
112
|
+
|
|
113
|
+
This SDK class is a thin composition layer that inherits from specialized mixins:
|
|
114
|
+
- AnalyticsRegistry: analytics, dep_analytics, context, pattern_learning properties
|
|
115
|
+
- SessionManagerMixin: start_session, end_session, _ensure_session_exists
|
|
116
|
+
- SessionHandoffMixin: set_session_handoff, end_session_with_handoff
|
|
117
|
+
- SessionContinuityMixin: continue_from_last
|
|
118
|
+
- SessionInfoMixin: get_session_start_info, get_active_work_item, track_activity
|
|
119
|
+
- PlanningMixin: find_bottlenecks, recommend_next_work, get_parallel_work, etc.
|
|
120
|
+
- OrchestrationMixin: orchestrator, spawn_explorer, spawn_coder, orchestrate
|
|
121
|
+
- OperationsMixin: start_server, install_hooks, analyze_session, etc.
|
|
122
|
+
- CoreMixin: db, query, ref, reload, summary, my_work, next_task, etc.
|
|
123
|
+
- TaskAttributionMixin: get_task_attribution, get_subagent_work
|
|
124
|
+
- HelpMixin: help, __dir__
|
|
125
|
+
|
|
126
|
+
Example:
|
|
127
|
+
sdk = SDK(agent="claude")
|
|
128
|
+
|
|
129
|
+
# Work with features (has builder support)
|
|
130
|
+
feature = sdk.features.create("User Auth")
|
|
131
|
+
.set_priority("high")
|
|
132
|
+
.add_steps(["Login", "Logout"])
|
|
133
|
+
.save()
|
|
134
|
+
|
|
135
|
+
# Work with bugs
|
|
136
|
+
high_bugs = sdk.bugs.where(status="todo", priority="high")
|
|
137
|
+
with sdk.bugs.edit("bug-001") as bug:
|
|
138
|
+
bug.status = "in-progress"
|
|
139
|
+
|
|
140
|
+
# Strategic analytics
|
|
141
|
+
bottlenecks = sdk.find_bottlenecks(top_n=5)
|
|
142
|
+
recommendations = sdk.recommend_next_work(agent_count=3)
|
|
143
|
+
"""
|
|
144
|
+
|
|
145
|
+
def __init__(
|
|
146
|
+
self,
|
|
147
|
+
directory: Path | str | None = None,
|
|
148
|
+
agent: str | None = None,
|
|
149
|
+
parent_session: str | None = None,
|
|
150
|
+
db_path: str | None = None,
|
|
151
|
+
):
|
|
152
|
+
"""
|
|
153
|
+
Initialize SDK.
|
|
154
|
+
|
|
155
|
+
Args:
|
|
156
|
+
directory: Path to .htmlgraph directory (auto-discovered if not provided)
|
|
157
|
+
agent: REQUIRED - Agent identifier for operations.
|
|
158
|
+
Used to attribute work items (features, spikes, bugs, etc) to the agent.
|
|
159
|
+
Examples: agent='explorer', agent='coder', agent='tester'
|
|
160
|
+
Critical for: Work attribution, result retrieval, orchestrator tracking
|
|
161
|
+
Falls back to: CLAUDE_AGENT_NAME env var, then detect_agent_name()
|
|
162
|
+
Raises ValueError if not provided and cannot be detected
|
|
163
|
+
parent_session: Parent session ID to log activities to (for nested contexts)
|
|
164
|
+
db_path: Path to SQLite database file (optional, defaults to ~/.htmlgraph/htmlgraph.db)
|
|
165
|
+
"""
|
|
166
|
+
if directory is None:
|
|
167
|
+
directory = self._discover_htmlgraph()
|
|
168
|
+
|
|
169
|
+
if agent is None:
|
|
170
|
+
# Try environment variable fallback
|
|
171
|
+
agent = os.getenv("CLAUDE_AGENT_NAME")
|
|
172
|
+
|
|
173
|
+
if agent is None:
|
|
174
|
+
# Try automatic detection
|
|
175
|
+
detected = detect_agent_name()
|
|
176
|
+
if detected and detected != "cli":
|
|
177
|
+
# Only accept detected if it's not the default fallback
|
|
178
|
+
agent = detected
|
|
179
|
+
else:
|
|
180
|
+
# No valid agent found - fail fast with helpful error message
|
|
181
|
+
raise ValueError(
|
|
182
|
+
"Agent identifier is required for work attribution. "
|
|
183
|
+
"Pass agent='name' to SDK() initialization. "
|
|
184
|
+
"Examples: SDK(agent='explorer'), SDK(agent='coder'), SDK(agent='tester')\n"
|
|
185
|
+
"Alternatively, set CLAUDE_AGENT_NAME environment variable.\n"
|
|
186
|
+
"Critical for: Work attribution, result retrieval, orchestrator tracking"
|
|
187
|
+
)
|
|
188
|
+
|
|
189
|
+
self._directory = Path(directory)
|
|
190
|
+
self._agent_id = agent
|
|
191
|
+
self._parent_session = parent_session or os.getenv("HTMLGRAPH_PARENT_SESSION")
|
|
192
|
+
|
|
193
|
+
# Initialize SQLite database (Phase 2)
|
|
194
|
+
self._db = HtmlGraphDB(
|
|
195
|
+
db_path or str(Path.home() / ".htmlgraph" / "htmlgraph.db")
|
|
196
|
+
)
|
|
197
|
+
self._db.connect()
|
|
198
|
+
self._db.create_tables()
|
|
199
|
+
|
|
200
|
+
# Initialize underlying HtmlGraphs first (for backward compatibility and sharing)
|
|
201
|
+
# These are shared with SessionManager to avoid double-loading features
|
|
202
|
+
self._graph = HtmlGraph(self._directory / "features")
|
|
203
|
+
self._bugs_graph = HtmlGraph(self._directory / "bugs")
|
|
204
|
+
|
|
205
|
+
# Initialize SessionManager with shared graph instances to avoid double-loading
|
|
206
|
+
self.session_manager = SessionManager(
|
|
207
|
+
self._directory,
|
|
208
|
+
features_graph=self._graph,
|
|
209
|
+
bugs_graph=self._bugs_graph,
|
|
210
|
+
)
|
|
211
|
+
|
|
212
|
+
# Agent interface (for backward compatibility)
|
|
213
|
+
self._agent_interface = AgentInterface(
|
|
214
|
+
self._directory / "features", agent_id=agent
|
|
215
|
+
)
|
|
216
|
+
|
|
217
|
+
# Collection interfaces - all work item types (all with builder support)
|
|
218
|
+
self.features = FeatureCollection(self)
|
|
219
|
+
self.bugs = BugCollection(self)
|
|
220
|
+
self.chores = ChoreCollection(self)
|
|
221
|
+
self.spikes = SpikeCollection(self)
|
|
222
|
+
self.epics = EpicCollection(self)
|
|
223
|
+
self.phases = PhaseCollection(self)
|
|
224
|
+
|
|
225
|
+
# Non-work collections
|
|
226
|
+
self.sessions: SessionCollection = SessionCollection(self)
|
|
227
|
+
self.tracks: TrackCollection = TrackCollection(
|
|
228
|
+
self
|
|
229
|
+
) # Use specialized collection with builder support
|
|
230
|
+
self.agents: BaseCollection[Any] = BaseCollection(self, "agents", "agent")
|
|
231
|
+
|
|
232
|
+
# Learning collections (Active Learning Persistence)
|
|
233
|
+
self.patterns = PatternCollection(self)
|
|
234
|
+
self.insights = InsightCollection(self)
|
|
235
|
+
self.metrics = MetricCollection(self)
|
|
236
|
+
|
|
237
|
+
# Todo collection (persistent task tracking)
|
|
238
|
+
self.todos = TodoCollection(self)
|
|
239
|
+
|
|
240
|
+
# Task delegation collection (observability for spawned agents)
|
|
241
|
+
self.task_delegations = TaskDelegationCollection(self)
|
|
242
|
+
|
|
243
|
+
# Create learning directories if needed
|
|
244
|
+
(self._directory / "patterns").mkdir(exist_ok=True)
|
|
245
|
+
(self._directory / "insights").mkdir(exist_ok=True)
|
|
246
|
+
(self._directory / "metrics").mkdir(exist_ok=True)
|
|
247
|
+
(self._directory / "todos").mkdir(exist_ok=True)
|
|
248
|
+
(self._directory / "task-delegations").mkdir(exist_ok=True)
|
|
249
|
+
|
|
250
|
+
# Initialize RefManager and set on all collections
|
|
251
|
+
from htmlgraph.refs import RefManager
|
|
252
|
+
|
|
253
|
+
self.refs = RefManager(self._directory)
|
|
254
|
+
|
|
255
|
+
# Set ref manager on all work item collections
|
|
256
|
+
self.features.set_ref_manager(self.refs)
|
|
257
|
+
self.bugs.set_ref_manager(self.refs)
|
|
258
|
+
self.chores.set_ref_manager(self.refs)
|
|
259
|
+
self.spikes.set_ref_manager(self.refs)
|
|
260
|
+
self.epics.set_ref_manager(self.refs)
|
|
261
|
+
self.phases.set_ref_manager(self.refs)
|
|
262
|
+
self.tracks.set_ref_manager(self.refs)
|
|
263
|
+
self.todos.set_ref_manager(self.refs)
|
|
264
|
+
|
|
265
|
+
# Analytics engine (centralized analytics management with lazy loading)
|
|
266
|
+
from htmlgraph.sdk.analytics.helpers import create_analytics_engine
|
|
267
|
+
|
|
268
|
+
self._analytics_engine = create_analytics_engine(
|
|
269
|
+
sdk=self, graph=self._graph, directory=self._directory
|
|
270
|
+
)
|
|
271
|
+
|
|
272
|
+
# Lazy-loaded orchestrator for subagent management
|
|
273
|
+
self._orchestrator: Any = None
|
|
274
|
+
|
|
275
|
+
# System prompt manager (lazy-loaded)
|
|
276
|
+
self._system_prompts: SystemPromptManager | None = None
|
|
277
|
+
|
|
278
|
+
# Session warning system (workaround for Claude Code hook bug #10373)
|
|
279
|
+
# Shows orchestrator instructions on first SDK usage per session
|
|
280
|
+
self._session_warning = check_and_show_warning(
|
|
281
|
+
self._directory,
|
|
282
|
+
agent=self._agent_id,
|
|
283
|
+
session_id=None, # Will be set by session manager if available
|
|
284
|
+
)
|
|
285
|
+
|
|
286
|
+
@staticmethod
|
|
287
|
+
def _discover_htmlgraph() -> Path:
|
|
288
|
+
"""
|
|
289
|
+
Auto-discover .htmlgraph directory.
|
|
290
|
+
|
|
291
|
+
Searches current directory and parents.
|
|
292
|
+
"""
|
|
293
|
+
current = Path.cwd()
|
|
294
|
+
|
|
295
|
+
# Check current directory
|
|
296
|
+
if (current / ".htmlgraph").exists():
|
|
297
|
+
return current / ".htmlgraph"
|
|
298
|
+
|
|
299
|
+
# Check parent directories
|
|
300
|
+
for parent in current.parents:
|
|
301
|
+
if (parent / ".htmlgraph").exists():
|
|
302
|
+
return parent / ".htmlgraph"
|
|
303
|
+
|
|
304
|
+
# Default to current directory
|
|
305
|
+
return current / ".htmlgraph"
|
|
306
|
+
|
|
307
|
+
@property
|
|
308
|
+
def agent(self) -> str | None:
|
|
309
|
+
"""Get current agent ID."""
|
|
310
|
+
return self._agent_id
|
|
311
|
+
|
|
312
|
+
@property
|
|
313
|
+
def system_prompts(self) -> SystemPromptManager:
|
|
314
|
+
"""
|
|
315
|
+
Access system prompt management.
|
|
316
|
+
|
|
317
|
+
Provides methods to:
|
|
318
|
+
- Get active prompt (project override OR plugin default)
|
|
319
|
+
- Create/delete project-level overrides
|
|
320
|
+
- Validate token counts
|
|
321
|
+
- Get prompt statistics
|
|
322
|
+
|
|
323
|
+
Lazy-loaded on first access.
|
|
324
|
+
|
|
325
|
+
Returns:
|
|
326
|
+
SystemPromptManager instance
|
|
327
|
+
|
|
328
|
+
Example:
|
|
329
|
+
>>> sdk = SDK(agent="claude")
|
|
330
|
+
|
|
331
|
+
# Get active prompt
|
|
332
|
+
>>> prompt = sdk.system_prompts.get_active()
|
|
333
|
+
|
|
334
|
+
# Create project override
|
|
335
|
+
>>> sdk.system_prompts.create("## Custom prompt\\n...")
|
|
336
|
+
|
|
337
|
+
# Validate token count
|
|
338
|
+
>>> result = sdk.system_prompts.validate()
|
|
339
|
+
>>> print(result['message'])
|
|
340
|
+
|
|
341
|
+
# Get statistics
|
|
342
|
+
>>> stats = sdk.system_prompts.get_stats()
|
|
343
|
+
>>> print(f"Source: {stats['source']}")
|
|
344
|
+
"""
|
|
345
|
+
if self._system_prompts is None:
|
|
346
|
+
self._system_prompts = SystemPromptManager(self._directory)
|
|
347
|
+
return self._system_prompts
|
|
348
|
+
|
|
349
|
+
def dismiss_session_warning(self) -> bool:
|
|
350
|
+
"""
|
|
351
|
+
Dismiss the session warning after reading it.
|
|
352
|
+
|
|
353
|
+
IMPORTANT: Call this as your FIRST action after seeing the orchestrator
|
|
354
|
+
warning. This confirms you've read the instructions.
|
|
355
|
+
|
|
356
|
+
Returns:
|
|
357
|
+
True if warning was dismissed, False if already dismissed
|
|
358
|
+
|
|
359
|
+
Example:
|
|
360
|
+
sdk = SDK(agent="claude")
|
|
361
|
+
# Warning shown automatically...
|
|
362
|
+
|
|
363
|
+
# First action: dismiss to confirm you read it
|
|
364
|
+
sdk.dismiss_session_warning()
|
|
365
|
+
|
|
366
|
+
# Now proceed with orchestration
|
|
367
|
+
sdk.spawn_coder(feature_id="feat-123", ...)
|
|
368
|
+
"""
|
|
369
|
+
if self._session_warning:
|
|
370
|
+
return self._session_warning.dismiss(
|
|
371
|
+
agent=self._agent_id,
|
|
372
|
+
session_id=None,
|
|
373
|
+
)
|
|
374
|
+
return False
|
|
375
|
+
|
|
376
|
+
def get_warning_status(self) -> dict[str, Any]:
|
|
377
|
+
"""
|
|
378
|
+
Get current session warning status.
|
|
379
|
+
|
|
380
|
+
Returns:
|
|
381
|
+
Dict with dismissed status, timestamp, and show count
|
|
382
|
+
"""
|
|
383
|
+
if self._session_warning:
|
|
384
|
+
return self._session_warning.get_status()
|
|
385
|
+
return {"dismissed": True, "show_count": 0}
|
|
386
|
+
|
|
387
|
+
|
|
388
|
+
__all__ = [
|
|
389
|
+
# Core SDK class
|
|
390
|
+
"SDK",
|
|
391
|
+
"BaseSDK",
|
|
392
|
+
# Discovery utilities
|
|
393
|
+
"find_project_root",
|
|
394
|
+
"discover_htmlgraph_dir",
|
|
395
|
+
"auto_discover_agent",
|
|
396
|
+
# Constants and configuration
|
|
397
|
+
"SDKSettings",
|
|
398
|
+
]
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Type stub for htmlgraph.sdk package.
|
|
3
|
+
|
|
4
|
+
Exports SDK from the core module.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from htmlgraph.sdk.base import BaseSDK as BaseSDK
|
|
8
|
+
from htmlgraph.sdk.constants import SDKSettings as SDKSettings
|
|
9
|
+
from htmlgraph.sdk.core import SDK as SDK
|
|
10
|
+
from htmlgraph.sdk.discovery import auto_discover_agent as auto_discover_agent
|
|
11
|
+
from htmlgraph.sdk.discovery import discover_htmlgraph_dir as discover_htmlgraph_dir
|
|
12
|
+
from htmlgraph.sdk.discovery import find_project_root as find_project_root
|
|
13
|
+
|
|
14
|
+
__all__: list[str]
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Analytics submodule for SDK.
|
|
3
|
+
|
|
4
|
+
Provides lazy-loaded analytics interfaces:
|
|
5
|
+
- Analytics: Work type distribution and session analytics
|
|
6
|
+
- DependencyAnalytics: Graph-based dependency analysis
|
|
7
|
+
- CrossSessionAnalytics: Git commit-based cross-session tracking
|
|
8
|
+
- ContextAnalytics: Context usage tracking
|
|
9
|
+
|
|
10
|
+
Exported for backward compatibility.
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
from htmlgraph.sdk.analytics.engine import AnalyticsEngine
|
|
14
|
+
from htmlgraph.sdk.analytics.registry import AnalyticsRegistry
|
|
15
|
+
|
|
16
|
+
__all__ = [
|
|
17
|
+
"AnalyticsEngine",
|
|
18
|
+
"AnalyticsRegistry",
|
|
19
|
+
]
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Analytics Engine for SDK.
|
|
3
|
+
|
|
4
|
+
Centralized management of all analytics interfaces with lazy loading.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from __future__ import annotations
|
|
8
|
+
|
|
9
|
+
from typing import TYPE_CHECKING, Any
|
|
10
|
+
|
|
11
|
+
if TYPE_CHECKING:
|
|
12
|
+
from htmlgraph.analytics import (
|
|
13
|
+
Analytics,
|
|
14
|
+
CrossSessionAnalytics,
|
|
15
|
+
DependencyAnalytics,
|
|
16
|
+
)
|
|
17
|
+
from htmlgraph.context_analytics import ContextAnalytics
|
|
18
|
+
from htmlgraph.graph import HtmlGraph
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
class AnalyticsEngine:
|
|
22
|
+
"""
|
|
23
|
+
Centralized analytics engine with lazy loading.
|
|
24
|
+
|
|
25
|
+
Manages all analytics interfaces:
|
|
26
|
+
- analytics: Work type distribution and session analytics
|
|
27
|
+
- dep_analytics: Dependency-aware graph analysis
|
|
28
|
+
- cross_session_analytics: Git commit-based tracking
|
|
29
|
+
- context: Context usage tracking
|
|
30
|
+
- pattern_learning: Pattern learning (lazy-loaded)
|
|
31
|
+
|
|
32
|
+
All analytics are lazy-loaded to improve SDK initialization performance.
|
|
33
|
+
|
|
34
|
+
Example:
|
|
35
|
+
>>> from htmlgraph import SDK
|
|
36
|
+
>>> sdk = SDK(agent="claude")
|
|
37
|
+
>>>
|
|
38
|
+
>>> # Analytics are lazy-loaded on first access
|
|
39
|
+
>>> dist = sdk.analytics.work_type_distribution()
|
|
40
|
+
>>> bottlenecks = sdk.dep_analytics.find_bottlenecks()
|
|
41
|
+
>>> usage = sdk.context.get_session_usage("session-123")
|
|
42
|
+
"""
|
|
43
|
+
|
|
44
|
+
def __init__(self, sdk: Any, graph: HtmlGraph, directory: Any):
|
|
45
|
+
"""
|
|
46
|
+
Initialize analytics engine.
|
|
47
|
+
|
|
48
|
+
Args:
|
|
49
|
+
sdk: SDK instance (parent)
|
|
50
|
+
graph: HtmlGraph instance
|
|
51
|
+
directory: .htmlgraph directory path
|
|
52
|
+
"""
|
|
53
|
+
self._sdk = sdk
|
|
54
|
+
self._graph = graph
|
|
55
|
+
self._directory = directory
|
|
56
|
+
|
|
57
|
+
# Lazy-loaded analytics instances
|
|
58
|
+
self._analytics: Analytics | None = None
|
|
59
|
+
self._dep_analytics: DependencyAnalytics | None = None
|
|
60
|
+
self._cross_session_analytics: CrossSessionAnalytics | None = None
|
|
61
|
+
self._context_analytics: ContextAnalytics | None = None
|
|
62
|
+
self._pattern_learning: Any = None
|
|
63
|
+
|
|
64
|
+
@property
|
|
65
|
+
def analytics(self) -> Analytics:
|
|
66
|
+
"""
|
|
67
|
+
Get work type analytics interface (lazy-loaded).
|
|
68
|
+
|
|
69
|
+
Provides:
|
|
70
|
+
- work_type_distribution(): Analyze work type distribution
|
|
71
|
+
- spike_to_feature_ratio(): Calculate spike/feature ratio
|
|
72
|
+
- maintenance_burden(): Calculate maintenance percentage
|
|
73
|
+
- get_sessions_by_work_type(): Filter sessions by work type
|
|
74
|
+
|
|
75
|
+
Returns:
|
|
76
|
+
Analytics instance
|
|
77
|
+
"""
|
|
78
|
+
if self._analytics is None:
|
|
79
|
+
from htmlgraph.analytics import Analytics
|
|
80
|
+
|
|
81
|
+
self._analytics = Analytics(self._sdk)
|
|
82
|
+
return self._analytics
|
|
83
|
+
|
|
84
|
+
@property
|
|
85
|
+
def dep_analytics(self) -> DependencyAnalytics:
|
|
86
|
+
"""
|
|
87
|
+
Get dependency analytics interface (lazy-loaded).
|
|
88
|
+
|
|
89
|
+
Provides:
|
|
90
|
+
- find_bottlenecks(): Identify blocking work
|
|
91
|
+
- find_critical_path(): Find longest dependency chain
|
|
92
|
+
- find_parallelization_opportunities(): Find parallel work
|
|
93
|
+
- recommend_next_tasks(): Prioritize work
|
|
94
|
+
- assess_risk(): Identify high-risk dependencies
|
|
95
|
+
|
|
96
|
+
Returns:
|
|
97
|
+
DependencyAnalytics instance
|
|
98
|
+
"""
|
|
99
|
+
if self._dep_analytics is None:
|
|
100
|
+
from htmlgraph.analytics import DependencyAnalytics
|
|
101
|
+
|
|
102
|
+
self._dep_analytics = DependencyAnalytics(self._graph)
|
|
103
|
+
return self._dep_analytics
|
|
104
|
+
|
|
105
|
+
@property
|
|
106
|
+
def cross_session_analytics(self) -> CrossSessionAnalytics:
|
|
107
|
+
"""
|
|
108
|
+
Get cross-session analytics interface (lazy-loaded).
|
|
109
|
+
|
|
110
|
+
Provides:
|
|
111
|
+
- work_in_commit_range(): Get work between commits
|
|
112
|
+
- sessions_for_feature(): Find sessions for a feature
|
|
113
|
+
- work_by_author(): Analyze work by author
|
|
114
|
+
|
|
115
|
+
Returns:
|
|
116
|
+
CrossSessionAnalytics instance
|
|
117
|
+
"""
|
|
118
|
+
if self._cross_session_analytics is None:
|
|
119
|
+
from htmlgraph.analytics import CrossSessionAnalytics
|
|
120
|
+
|
|
121
|
+
self._cross_session_analytics = CrossSessionAnalytics(self._sdk)
|
|
122
|
+
return self._cross_session_analytics
|
|
123
|
+
|
|
124
|
+
@property
|
|
125
|
+
def context(self) -> ContextAnalytics:
|
|
126
|
+
"""
|
|
127
|
+
Get context analytics interface (lazy-loaded).
|
|
128
|
+
|
|
129
|
+
Provides:
|
|
130
|
+
- get_session_usage(): Get session context usage
|
|
131
|
+
- get_feature_usage(): Get feature context usage
|
|
132
|
+
- get_track_usage(): Get track context usage
|
|
133
|
+
|
|
134
|
+
Returns:
|
|
135
|
+
ContextAnalytics instance
|
|
136
|
+
"""
|
|
137
|
+
if self._context_analytics is None:
|
|
138
|
+
from htmlgraph.context_analytics import ContextAnalytics
|
|
139
|
+
|
|
140
|
+
self._context_analytics = ContextAnalytics(self._sdk)
|
|
141
|
+
return self._context_analytics
|
|
142
|
+
|
|
143
|
+
@property
|
|
144
|
+
def pattern_learning(self) -> Any:
|
|
145
|
+
"""
|
|
146
|
+
Get pattern learning interface (lazy-loaded).
|
|
147
|
+
|
|
148
|
+
Returns:
|
|
149
|
+
PatternLearner instance
|
|
150
|
+
"""
|
|
151
|
+
if self._pattern_learning is None:
|
|
152
|
+
from htmlgraph.analytics.pattern_learning import PatternLearner
|
|
153
|
+
|
|
154
|
+
self._pattern_learning = PatternLearner(self._directory)
|
|
155
|
+
return self._pattern_learning
|