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
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import logging
|
|
4
|
+
|
|
5
|
+
logger = logging.getLogger(__name__)
|
|
6
|
+
|
|
7
|
+
"""
|
|
8
|
+
SessionCollection - Session state and management interface.
|
|
9
|
+
|
|
10
|
+
Provides methods to:
|
|
11
|
+
- Get current session state automatically
|
|
12
|
+
- Set up environment variables automatically
|
|
13
|
+
- Track session metadata
|
|
14
|
+
- Detect post-compact sessions
|
|
15
|
+
|
|
16
|
+
Integration with SessionStart hook:
|
|
17
|
+
sdk = SDK()
|
|
18
|
+
state = sdk.sessions.get_current_state()
|
|
19
|
+
sdk.sessions.setup_environment_variables(state)
|
|
20
|
+
"""
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
from typing import TYPE_CHECKING
|
|
24
|
+
|
|
25
|
+
from htmlgraph.collections.base import BaseCollection
|
|
26
|
+
from htmlgraph.session_state import SessionState, SessionStateManager
|
|
27
|
+
|
|
28
|
+
if TYPE_CHECKING:
|
|
29
|
+
from htmlgraph.sdk import SDK
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
class SessionCollection(BaseCollection):
|
|
33
|
+
"""
|
|
34
|
+
Collection interface for session state management.
|
|
35
|
+
|
|
36
|
+
Extends BaseCollection with session-specific state management operations.
|
|
37
|
+
|
|
38
|
+
Provides:
|
|
39
|
+
- Automatic session state detection (post-compact, delegation status)
|
|
40
|
+
- Environment variable setup (CLAUDE_SESSION_ID, CLAUDE_DELEGATION_ENABLED, etc.)
|
|
41
|
+
- Session metadata recording and retrieval
|
|
42
|
+
- Compact detection
|
|
43
|
+
|
|
44
|
+
Example:
|
|
45
|
+
>>> sdk = SDK(agent="claude")
|
|
46
|
+
>>> state = sdk.sessions.get_current_state()
|
|
47
|
+
>>> sdk.sessions.setup_environment_variables(state)
|
|
48
|
+
# All environment variables automatically set
|
|
49
|
+
"""
|
|
50
|
+
|
|
51
|
+
_collection_name = "sessions"
|
|
52
|
+
_node_type = "session"
|
|
53
|
+
|
|
54
|
+
def __init__(self, sdk: SDK):
|
|
55
|
+
"""
|
|
56
|
+
Initialize SessionCollection.
|
|
57
|
+
|
|
58
|
+
Args:
|
|
59
|
+
sdk: Parent SDK instance
|
|
60
|
+
"""
|
|
61
|
+
super().__init__(sdk, "sessions", "session")
|
|
62
|
+
self._state_manager = SessionStateManager(sdk._directory)
|
|
63
|
+
|
|
64
|
+
def get_current_state(self) -> SessionState:
|
|
65
|
+
"""
|
|
66
|
+
Get current session state with automatic detection.
|
|
67
|
+
|
|
68
|
+
Automatically detects:
|
|
69
|
+
- Current session ID
|
|
70
|
+
- Session source (startup, resume, compact, clear)
|
|
71
|
+
- Post-compact status
|
|
72
|
+
- Delegation enable/disable
|
|
73
|
+
- Session validity
|
|
74
|
+
|
|
75
|
+
Returns:
|
|
76
|
+
SessionState dict with:
|
|
77
|
+
- session_id: Current session identifier
|
|
78
|
+
- session_source: "startup", "resume", "compact", "clear"
|
|
79
|
+
- is_post_compact: True if this is post-compact session
|
|
80
|
+
- previous_session_id: Previous session ID if available
|
|
81
|
+
- delegation_enabled: Should delegation be active
|
|
82
|
+
- prompt_injected: Was orchestrator prompt injected
|
|
83
|
+
- session_valid: Is session valid for tracking
|
|
84
|
+
- timestamp: Current UTC timestamp
|
|
85
|
+
- compact_metadata: Compact detection details
|
|
86
|
+
|
|
87
|
+
Example:
|
|
88
|
+
>>> sdk = SDK()
|
|
89
|
+
>>> state = sdk.sessions.get_current_state()
|
|
90
|
+
>>> logger.info(f"Session: {state['session_id']}")
|
|
91
|
+
>>> logger.info(f"Post-compact: {state['is_post_compact']}")
|
|
92
|
+
>>> logger.info(f"Delegation enabled: {state['delegation_enabled']}")
|
|
93
|
+
"""
|
|
94
|
+
return self._state_manager.get_current_state()
|
|
95
|
+
|
|
96
|
+
def setup_environment_variables(
|
|
97
|
+
self,
|
|
98
|
+
session_state: SessionState | None = None,
|
|
99
|
+
auto_detect_compact: bool = True,
|
|
100
|
+
) -> dict[str, str]:
|
|
101
|
+
"""
|
|
102
|
+
Automatically set up environment variables for session state.
|
|
103
|
+
|
|
104
|
+
Sets up environment variables that persist across context boundaries:
|
|
105
|
+
- CLAUDE_SESSION_ID: Current session identifier
|
|
106
|
+
- CLAUDE_SESSION_SOURCE: "startup|resume|compact|clear"
|
|
107
|
+
- CLAUDE_SESSION_COMPACTED: "true|false"
|
|
108
|
+
- CLAUDE_DELEGATION_ENABLED: "true|false"
|
|
109
|
+
- CLAUDE_PREVIOUS_SESSION_ID: Previous session ID
|
|
110
|
+
- CLAUDE_ORCHESTRATOR_ACTIVE: "true|false"
|
|
111
|
+
- CLAUDE_PROMPT_PERSISTENCE_VERSION: "1.0"
|
|
112
|
+
|
|
113
|
+
Args:
|
|
114
|
+
session_state: Session state dict (auto-detected if not provided)
|
|
115
|
+
auto_detect_compact: Whether to auto-detect post-compact state
|
|
116
|
+
|
|
117
|
+
Returns:
|
|
118
|
+
Dict of environment variables that were set
|
|
119
|
+
|
|
120
|
+
Example:
|
|
121
|
+
>>> sdk = SDK()
|
|
122
|
+
>>> state = sdk.sessions.get_current_state()
|
|
123
|
+
>>> env_vars = sdk.sessions.setup_environment_variables(state)
|
|
124
|
+
>>> logger.info(f"CLAUDE_SESSION_ID: {env_vars['CLAUDE_SESSION_ID']}")
|
|
125
|
+
>>> logger.info(f"CLAUDE_DELEGATION_ENABLED: {env_vars['CLAUDE_DELEGATION_ENABLED']}")
|
|
126
|
+
"""
|
|
127
|
+
return self._state_manager.setup_environment_variables(
|
|
128
|
+
session_state=session_state, auto_detect_compact=auto_detect_compact
|
|
129
|
+
)
|
|
130
|
+
|
|
131
|
+
def record_state(
|
|
132
|
+
self,
|
|
133
|
+
session_id: str,
|
|
134
|
+
source: str,
|
|
135
|
+
is_post_compact: bool,
|
|
136
|
+
delegation_enabled: bool,
|
|
137
|
+
environment_vars: dict[str, str] | None = None,
|
|
138
|
+
) -> None:
|
|
139
|
+
"""
|
|
140
|
+
Store session state metadata for future reference.
|
|
141
|
+
|
|
142
|
+
Args:
|
|
143
|
+
session_id: Current session ID
|
|
144
|
+
source: Session source ("startup", "resume", "compact", "clear")
|
|
145
|
+
is_post_compact: Whether this is post-compact
|
|
146
|
+
delegation_enabled: Whether delegation is enabled
|
|
147
|
+
environment_vars: Environment variables that were set
|
|
148
|
+
|
|
149
|
+
Example:
|
|
150
|
+
>>> sdk = SDK()
|
|
151
|
+
>>> sdk.sessions.record_state(
|
|
152
|
+
... session_id="sess-123",
|
|
153
|
+
... source="compact",
|
|
154
|
+
... is_post_compact=True,
|
|
155
|
+
... delegation_enabled=True
|
|
156
|
+
... )
|
|
157
|
+
"""
|
|
158
|
+
self._state_manager.record_state(
|
|
159
|
+
session_id=session_id,
|
|
160
|
+
source=source,
|
|
161
|
+
is_post_compact=is_post_compact,
|
|
162
|
+
delegation_enabled=delegation_enabled,
|
|
163
|
+
environment_vars=environment_vars,
|
|
164
|
+
)
|
|
165
|
+
|
|
166
|
+
def detect_compact_automatically(self) -> bool:
|
|
167
|
+
"""
|
|
168
|
+
Auto-detect if this is post-compact by comparing session IDs.
|
|
169
|
+
|
|
170
|
+
Returns:
|
|
171
|
+
True if this is a post-compact session
|
|
172
|
+
|
|
173
|
+
Example:
|
|
174
|
+
>>> sdk = SDK()
|
|
175
|
+
>>> if sdk.sessions.detect_compact_automatically():
|
|
176
|
+
... logger.info("This is a post-compact session")
|
|
177
|
+
"""
|
|
178
|
+
return self._state_manager.detect_compact_automatically()
|
|
179
|
+
|
|
180
|
+
def get_state_manager(self) -> SessionStateManager:
|
|
181
|
+
"""
|
|
182
|
+
Get the underlying SessionStateManager.
|
|
183
|
+
|
|
184
|
+
Use this for advanced session state operations.
|
|
185
|
+
|
|
186
|
+
Returns:
|
|
187
|
+
SessionStateManager instance
|
|
188
|
+
|
|
189
|
+
Example:
|
|
190
|
+
>>> sdk = SDK()
|
|
191
|
+
>>> manager = sdk.sessions.get_state_manager()
|
|
192
|
+
>>> state = manager.get_current_state()
|
|
193
|
+
"""
|
|
194
|
+
return self._state_manager
|
htmlgraph/collections/spike.py
CHANGED
|
@@ -1,20 +1,26 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import logging
|
|
4
|
+
|
|
5
|
+
logger = logging.getLogger(__name__)
|
|
6
|
+
|
|
1
7
|
"""
|
|
2
8
|
Spike collection for managing investigation and research spikes.
|
|
3
9
|
|
|
4
10
|
Extends BaseCollection with spike-specific builder support.
|
|
5
11
|
"""
|
|
6
12
|
|
|
7
|
-
|
|
13
|
+
|
|
14
|
+
from datetime import datetime
|
|
8
15
|
from typing import TYPE_CHECKING
|
|
9
16
|
|
|
10
17
|
if TYPE_CHECKING:
|
|
11
18
|
from htmlgraph.sdk import SDK
|
|
12
|
-
from htmlgraph.builders import SpikeBuilder
|
|
13
19
|
|
|
14
20
|
from htmlgraph.collections.base import BaseCollection
|
|
15
21
|
|
|
16
22
|
|
|
17
|
-
class SpikeCollection(BaseCollection[
|
|
23
|
+
class SpikeCollection(BaseCollection["SpikeCollection"]):
|
|
18
24
|
"""
|
|
19
25
|
Collection interface for spikes with builder support.
|
|
20
26
|
|
|
@@ -37,7 +43,7 @@ class SpikeCollection(BaseCollection['SpikeCollection']):
|
|
|
37
43
|
_collection_name = "spikes"
|
|
38
44
|
_node_type = "spike"
|
|
39
45
|
|
|
40
|
-
def __init__(self, sdk:
|
|
46
|
+
def __init__(self, sdk: SDK):
|
|
41
47
|
"""
|
|
42
48
|
Initialize spike collection.
|
|
43
49
|
|
|
@@ -47,23 +53,57 @@ class SpikeCollection(BaseCollection['SpikeCollection']):
|
|
|
47
53
|
super().__init__(sdk, "spikes", "spike")
|
|
48
54
|
self._sdk = sdk
|
|
49
55
|
|
|
50
|
-
|
|
56
|
+
# Set builder class for create() method
|
|
57
|
+
from htmlgraph.builders import SpikeBuilder
|
|
58
|
+
|
|
59
|
+
self._builder_class = SpikeBuilder
|
|
60
|
+
|
|
61
|
+
def get_latest(self, agent: str | None = None, limit: int = 1) -> list:
|
|
51
62
|
"""
|
|
52
|
-
|
|
63
|
+
Get the most recent spike(s), optionally filtered by agent.
|
|
64
|
+
|
|
65
|
+
Useful for retrieving subagent findings after delegation.
|
|
53
66
|
|
|
54
67
|
Args:
|
|
55
|
-
|
|
56
|
-
|
|
68
|
+
agent: Filter by agent_assigned (optional)
|
|
69
|
+
limit: Maximum number of spikes to return (default: 1)
|
|
57
70
|
|
|
58
71
|
Returns:
|
|
59
|
-
|
|
72
|
+
List of most recent Spike nodes (newest first)
|
|
60
73
|
|
|
61
74
|
Example:
|
|
62
|
-
>>>
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
... .
|
|
75
|
+
>>> # Get latest spike from explorer subagent
|
|
76
|
+
>>> sdk = SDK(agent="orchestrator")
|
|
77
|
+
>>> findings = sdk.spikes.get_latest(agent="explorer")
|
|
78
|
+
>>> if findings:
|
|
79
|
+
... print(findings[0].findings)
|
|
80
|
+
>>>
|
|
81
|
+
>>> # Get latest 5 spikes from any agent
|
|
82
|
+
>>> recent = sdk.spikes.get_latest(limit=5)
|
|
67
83
|
"""
|
|
68
|
-
from
|
|
69
|
-
|
|
84
|
+
from datetime import timezone
|
|
85
|
+
|
|
86
|
+
# Get all spikes
|
|
87
|
+
all_spikes = self.all()
|
|
88
|
+
|
|
89
|
+
# Filter by agent if specified
|
|
90
|
+
# Check both agent_assigned and model_name fields
|
|
91
|
+
if agent:
|
|
92
|
+
all_spikes = [
|
|
93
|
+
s
|
|
94
|
+
for s in all_spikes
|
|
95
|
+
if (s.agent_assigned and agent.lower() in s.agent_assigned.lower())
|
|
96
|
+
or (s.model_name and agent.lower() in s.model_name.lower())
|
|
97
|
+
]
|
|
98
|
+
|
|
99
|
+
# Normalize to UTC for comparison
|
|
100
|
+
def to_comparable(dt: datetime) -> datetime:
|
|
101
|
+
if dt.tzinfo is None:
|
|
102
|
+
return dt.replace(tzinfo=timezone.utc)
|
|
103
|
+
return dt
|
|
104
|
+
|
|
105
|
+
# Sort by created timestamp (newest first)
|
|
106
|
+
all_spikes.sort(key=lambda s: to_comparable(s.created), reverse=True)
|
|
107
|
+
|
|
108
|
+
# Return limited results
|
|
109
|
+
return all_spikes[:limit]
|
|
@@ -0,0 +1,241 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import logging
|
|
4
|
+
|
|
5
|
+
logger = logging.getLogger(__name__)
|
|
6
|
+
|
|
7
|
+
"""
|
|
8
|
+
Task delegation collection for tracking spawned agent work.
|
|
9
|
+
|
|
10
|
+
Captures observability data for Task() calls:
|
|
11
|
+
- Which agent was spawned (gemini-spawner, codex-spawner, copilot-spawner, haiku)
|
|
12
|
+
- What task was assigned
|
|
13
|
+
- How long it took
|
|
14
|
+
- What was the output/result
|
|
15
|
+
- Cost (tokens used)
|
|
16
|
+
- Success/failure status
|
|
17
|
+
|
|
18
|
+
This data proves multi-agent orchestration works and enables dashboard attribution.
|
|
19
|
+
"""
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
from datetime import datetime
|
|
23
|
+
from typing import TYPE_CHECKING, Any
|
|
24
|
+
|
|
25
|
+
if TYPE_CHECKING:
|
|
26
|
+
from htmlgraph.sdk import SDK
|
|
27
|
+
|
|
28
|
+
from htmlgraph.collections.base import BaseCollection
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
class TaskDelegationCollection(BaseCollection["TaskDelegationCollection"]):
|
|
32
|
+
"""
|
|
33
|
+
Collection interface for task delegations.
|
|
34
|
+
|
|
35
|
+
Tracks all spawned agent work with metrics:
|
|
36
|
+
- Agent type (gemini-spawner, codex-spawner, copilot-spawner, haiku)
|
|
37
|
+
- Task description
|
|
38
|
+
- Start and end timestamps
|
|
39
|
+
- Duration in seconds
|
|
40
|
+
- Tokens used
|
|
41
|
+
- Cost in USD
|
|
42
|
+
- Status (success/failure)
|
|
43
|
+
- Result summary
|
|
44
|
+
|
|
45
|
+
Example:
|
|
46
|
+
>>> sdk = SDK(agent="orchestrator")
|
|
47
|
+
>>> delegations = sdk.task_delegations.where(agent_type="codex-spawner")
|
|
48
|
+
>>> for d in delegations:
|
|
49
|
+
... logger.info(f"{d.agent_type}: {d.task_description} ({d.duration_seconds}s)")
|
|
50
|
+
>>>
|
|
51
|
+
>>> # Get all delegations for a specific agent
|
|
52
|
+
>>> gemini_work = sdk.task_delegations.where(agent_type="gemini-spawner")
|
|
53
|
+
>>>
|
|
54
|
+
>>> # Calculate total cost
|
|
55
|
+
>>> total_cost = sum(float(d.cost_usd or 0) for d in sdk.task_delegations.all())
|
|
56
|
+
"""
|
|
57
|
+
|
|
58
|
+
_collection_name = "task-delegations"
|
|
59
|
+
_node_type = "task-delegation"
|
|
60
|
+
|
|
61
|
+
def __init__(self, sdk: SDK):
|
|
62
|
+
"""
|
|
63
|
+
Initialize task delegation collection.
|
|
64
|
+
|
|
65
|
+
Args:
|
|
66
|
+
sdk: Parent SDK instance
|
|
67
|
+
"""
|
|
68
|
+
super().__init__(sdk, "task-delegations", "task-delegation")
|
|
69
|
+
self._sdk = sdk
|
|
70
|
+
|
|
71
|
+
def create_delegation(
|
|
72
|
+
self,
|
|
73
|
+
agent_type: str,
|
|
74
|
+
task_description: str,
|
|
75
|
+
timestamp_start: datetime | None = None,
|
|
76
|
+
tokens_used: int = 0,
|
|
77
|
+
cost_usd: float = 0.0,
|
|
78
|
+
status: str = "pending",
|
|
79
|
+
result_summary: str = "",
|
|
80
|
+
) -> Any:
|
|
81
|
+
"""
|
|
82
|
+
Record a task delegation.
|
|
83
|
+
|
|
84
|
+
Args:
|
|
85
|
+
agent_type: Type of spawned agent (gemini-spawner, codex-spawner, copilot-spawner, haiku)
|
|
86
|
+
task_description: Human-readable task description
|
|
87
|
+
timestamp_start: When delegation started (defaults to now)
|
|
88
|
+
tokens_used: Number of tokens used by the agent
|
|
89
|
+
cost_usd: Cost in USD for this delegation
|
|
90
|
+
status: success/failure/pending
|
|
91
|
+
result_summary: Brief summary of the result
|
|
92
|
+
|
|
93
|
+
Returns:
|
|
94
|
+
Created task delegation node
|
|
95
|
+
"""
|
|
96
|
+
if timestamp_start is None:
|
|
97
|
+
timestamp_start = datetime.utcnow()
|
|
98
|
+
|
|
99
|
+
# Create delegation record via base collection
|
|
100
|
+
return self.create(
|
|
101
|
+
title=f"{agent_type}: {task_description[:50]}...",
|
|
102
|
+
).set_metadata(
|
|
103
|
+
{
|
|
104
|
+
"agent_type": agent_type,
|
|
105
|
+
"task_description": task_description,
|
|
106
|
+
"timestamp_start": timestamp_start.isoformat(),
|
|
107
|
+
"tokens_used": tokens_used,
|
|
108
|
+
"cost_usd": cost_usd,
|
|
109
|
+
"status": status,
|
|
110
|
+
"result_summary": result_summary,
|
|
111
|
+
}
|
|
112
|
+
)
|
|
113
|
+
|
|
114
|
+
def update_delegation(
|
|
115
|
+
self,
|
|
116
|
+
delegation_id: str,
|
|
117
|
+
timestamp_end: datetime | None = None,
|
|
118
|
+
tokens_used: int | None = None,
|
|
119
|
+
cost_usd: float | None = None,
|
|
120
|
+
status: str | None = None,
|
|
121
|
+
result_summary: str | None = None,
|
|
122
|
+
) -> Any:
|
|
123
|
+
"""
|
|
124
|
+
Update a delegation record with completion info.
|
|
125
|
+
|
|
126
|
+
Args:
|
|
127
|
+
delegation_id: ID of the delegation to update
|
|
128
|
+
timestamp_end: When delegation completed
|
|
129
|
+
tokens_used: Updated token count
|
|
130
|
+
cost_usd: Updated cost
|
|
131
|
+
status: Updated status
|
|
132
|
+
result_summary: Updated result summary
|
|
133
|
+
|
|
134
|
+
Returns:
|
|
135
|
+
Updated delegation node
|
|
136
|
+
"""
|
|
137
|
+
if timestamp_end is None:
|
|
138
|
+
timestamp_end = datetime.utcnow()
|
|
139
|
+
|
|
140
|
+
with self.edit(delegation_id) as delegation:
|
|
141
|
+
if timestamp_end:
|
|
142
|
+
delegation.timestamp_end = timestamp_end.isoformat() # type: ignore[attr-defined]
|
|
143
|
+
|
|
144
|
+
# Calculate duration if we have start time
|
|
145
|
+
if hasattr(delegation, "timestamp_start") and timestamp_end:
|
|
146
|
+
start = datetime.fromisoformat(str(delegation.timestamp_start))
|
|
147
|
+
duration = (timestamp_end - start).total_seconds()
|
|
148
|
+
delegation.duration_seconds = int(duration) # type: ignore[attr-defined]
|
|
149
|
+
|
|
150
|
+
if tokens_used is not None:
|
|
151
|
+
delegation.tokens_used = tokens_used # type: ignore[attr-defined]
|
|
152
|
+
if cost_usd is not None:
|
|
153
|
+
delegation.cost_usd = cost_usd # type: ignore[attr-defined]
|
|
154
|
+
if status is not None:
|
|
155
|
+
delegation.status = status # type: ignore[assignment]
|
|
156
|
+
if result_summary is not None:
|
|
157
|
+
delegation.result_summary = result_summary # type: ignore[attr-defined]
|
|
158
|
+
|
|
159
|
+
return delegation
|
|
160
|
+
|
|
161
|
+
def get_by_agent_type(self, agent_type: str) -> list:
|
|
162
|
+
"""
|
|
163
|
+
Get all delegations for a specific agent type.
|
|
164
|
+
|
|
165
|
+
Args:
|
|
166
|
+
agent_type: Type of agent (gemini-spawner, codex-spawner, etc.)
|
|
167
|
+
|
|
168
|
+
Returns:
|
|
169
|
+
List of delegations for that agent type
|
|
170
|
+
"""
|
|
171
|
+
return self.where(agent_type=agent_type)
|
|
172
|
+
|
|
173
|
+
def get_by_status(self, status: str) -> list:
|
|
174
|
+
"""
|
|
175
|
+
Get all delegations with a specific status.
|
|
176
|
+
|
|
177
|
+
Args:
|
|
178
|
+
status: Status to filter by (success/failure/pending)
|
|
179
|
+
|
|
180
|
+
Returns:
|
|
181
|
+
List of delegations with that status
|
|
182
|
+
"""
|
|
183
|
+
return self.where(status=status)
|
|
184
|
+
|
|
185
|
+
def get_stats(self) -> dict:
|
|
186
|
+
"""
|
|
187
|
+
Get aggregated statistics about delegations.
|
|
188
|
+
|
|
189
|
+
Returns:
|
|
190
|
+
Dictionary with:
|
|
191
|
+
- total_delegations: Count of all delegations
|
|
192
|
+
- by_agent_type: Count per agent type
|
|
193
|
+
- by_status: Count per status
|
|
194
|
+
- total_tokens: Sum of all tokens used
|
|
195
|
+
- total_cost: Sum of all costs in USD
|
|
196
|
+
- average_duration: Average duration in seconds
|
|
197
|
+
"""
|
|
198
|
+
all_delegations = self.all()
|
|
199
|
+
|
|
200
|
+
if not all_delegations:
|
|
201
|
+
return {
|
|
202
|
+
"total_delegations": 0,
|
|
203
|
+
"by_agent_type": {},
|
|
204
|
+
"by_status": {},
|
|
205
|
+
"total_tokens": 0,
|
|
206
|
+
"total_cost": 0.0,
|
|
207
|
+
"average_duration": 0.0,
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
# Count by agent type
|
|
211
|
+
by_agent_type: dict[str, int] = {}
|
|
212
|
+
for d in all_delegations:
|
|
213
|
+
agent = getattr(d, "agent_type", "unknown")
|
|
214
|
+
by_agent_type[agent] = by_agent_type.get(agent, 0) + 1
|
|
215
|
+
|
|
216
|
+
# Count by status
|
|
217
|
+
by_status: dict[str, int] = {}
|
|
218
|
+
for d in all_delegations:
|
|
219
|
+
status = getattr(d, "status", "unknown")
|
|
220
|
+
by_status[status] = by_status.get(status, 0) + 1
|
|
221
|
+
|
|
222
|
+
# Sum tokens and cost
|
|
223
|
+
total_tokens = sum(getattr(d, "tokens_used", 0) for d in all_delegations)
|
|
224
|
+
total_cost = sum(float(getattr(d, "cost_usd", 0) or 0) for d in all_delegations)
|
|
225
|
+
|
|
226
|
+
# Average duration
|
|
227
|
+
durations = [
|
|
228
|
+
getattr(d, "duration_seconds", 0)
|
|
229
|
+
for d in all_delegations
|
|
230
|
+
if hasattr(d, "duration_seconds")
|
|
231
|
+
]
|
|
232
|
+
average_duration = sum(durations) / len(durations) if durations else 0.0
|
|
233
|
+
|
|
234
|
+
return {
|
|
235
|
+
"total_delegations": len(all_delegations),
|
|
236
|
+
"by_agent_type": by_agent_type,
|
|
237
|
+
"by_status": by_status,
|
|
238
|
+
"total_tokens": total_tokens,
|
|
239
|
+
"total_cost": round(total_cost, 4),
|
|
240
|
+
"average_duration": round(average_duration, 2),
|
|
241
|
+
}
|