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,427 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Operations mixin for SDK - server, hooks, events, analytics operations.
|
|
3
|
+
|
|
4
|
+
Provides infrastructure operations for running HtmlGraph.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from __future__ import annotations
|
|
8
|
+
|
|
9
|
+
from typing import TYPE_CHECKING, Any
|
|
10
|
+
|
|
11
|
+
if TYPE_CHECKING:
|
|
12
|
+
from pathlib import Path
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class OperationsMixin:
|
|
16
|
+
"""
|
|
17
|
+
Mixin providing operations capabilities to SDK.
|
|
18
|
+
|
|
19
|
+
Adds methods for server, hooks, events, and analytics operations.
|
|
20
|
+
Requires SDK instance with _directory attribute.
|
|
21
|
+
"""
|
|
22
|
+
|
|
23
|
+
_directory: Path
|
|
24
|
+
|
|
25
|
+
# =========================================================================
|
|
26
|
+
# Server Operations
|
|
27
|
+
# =========================================================================
|
|
28
|
+
|
|
29
|
+
def start_server(
|
|
30
|
+
self,
|
|
31
|
+
port: int = 8080,
|
|
32
|
+
host: str = "localhost",
|
|
33
|
+
watch: bool = True,
|
|
34
|
+
auto_port: bool = False,
|
|
35
|
+
) -> Any:
|
|
36
|
+
"""
|
|
37
|
+
Start HtmlGraph server for browsing graph via web UI.
|
|
38
|
+
|
|
39
|
+
Args:
|
|
40
|
+
port: Port to listen on (default: 8080)
|
|
41
|
+
host: Host to bind to (default: "localhost")
|
|
42
|
+
watch: Enable file watching for auto-reload (default: True)
|
|
43
|
+
auto_port: Automatically find available port if specified port is in use (default: False)
|
|
44
|
+
|
|
45
|
+
Returns:
|
|
46
|
+
ServerStartResult with handle, warnings, and config used
|
|
47
|
+
|
|
48
|
+
Raises:
|
|
49
|
+
PortInUseError: If port is in use and auto_port=False
|
|
50
|
+
ServerStartError: If server fails to start
|
|
51
|
+
|
|
52
|
+
Example:
|
|
53
|
+
>>> sdk = SDK(agent="claude")
|
|
54
|
+
>>> result = sdk.start_server(port=8080, watch=True)
|
|
55
|
+
>>> logger.info(f"Server running at {result.handle.url}")
|
|
56
|
+
>>> # Open browser to http://localhost:8080
|
|
57
|
+
>>>
|
|
58
|
+
>>> # Stop server when done
|
|
59
|
+
>>> sdk.stop_server(result.handle)
|
|
60
|
+
|
|
61
|
+
See also:
|
|
62
|
+
stop_server: Stop running server
|
|
63
|
+
get_server_status: Check if server is running
|
|
64
|
+
"""
|
|
65
|
+
from htmlgraph.operations import server
|
|
66
|
+
|
|
67
|
+
return server.start_server(
|
|
68
|
+
port=port,
|
|
69
|
+
graph_dir=self._directory,
|
|
70
|
+
static_dir=self._directory.parent, # Project root for index.html
|
|
71
|
+
host=host,
|
|
72
|
+
watch=watch,
|
|
73
|
+
auto_port=auto_port,
|
|
74
|
+
)
|
|
75
|
+
|
|
76
|
+
def stop_server(self, handle: Any) -> None:
|
|
77
|
+
"""
|
|
78
|
+
Stop a running HtmlGraph server.
|
|
79
|
+
|
|
80
|
+
Args:
|
|
81
|
+
handle: ServerHandle returned from start_server()
|
|
82
|
+
|
|
83
|
+
Raises:
|
|
84
|
+
ServerStartError: If shutdown fails
|
|
85
|
+
|
|
86
|
+
Example:
|
|
87
|
+
>>> sdk = SDK(agent="claude")
|
|
88
|
+
>>> result = sdk.start_server()
|
|
89
|
+
>>> # Work with server...
|
|
90
|
+
>>> sdk.stop_server(result.handle)
|
|
91
|
+
"""
|
|
92
|
+
from htmlgraph.operations import server
|
|
93
|
+
|
|
94
|
+
server.stop_server(handle)
|
|
95
|
+
|
|
96
|
+
def get_server_status(self, handle: Any | None = None) -> Any:
|
|
97
|
+
"""
|
|
98
|
+
Check server status.
|
|
99
|
+
|
|
100
|
+
Args:
|
|
101
|
+
handle: Optional ServerHandle to check
|
|
102
|
+
|
|
103
|
+
Returns:
|
|
104
|
+
ServerStatus indicating whether server is running
|
|
105
|
+
|
|
106
|
+
Example:
|
|
107
|
+
>>> sdk = SDK(agent="claude")
|
|
108
|
+
>>> result = sdk.start_server()
|
|
109
|
+
>>> status = sdk.get_server_status(result.handle)
|
|
110
|
+
>>> logger.info(f"Running: {status.running}")
|
|
111
|
+
"""
|
|
112
|
+
from htmlgraph.operations import server
|
|
113
|
+
|
|
114
|
+
return server.get_server_status(handle)
|
|
115
|
+
|
|
116
|
+
# =========================================================================
|
|
117
|
+
# Hook Operations
|
|
118
|
+
# =========================================================================
|
|
119
|
+
|
|
120
|
+
def install_hooks(self, use_copy: bool = False) -> Any:
|
|
121
|
+
"""
|
|
122
|
+
Install Git hooks for automatic tracking.
|
|
123
|
+
|
|
124
|
+
Installs hooks that automatically track sessions, activities, and features
|
|
125
|
+
as you work.
|
|
126
|
+
|
|
127
|
+
Args:
|
|
128
|
+
use_copy: Force copy instead of symlink (default: False)
|
|
129
|
+
|
|
130
|
+
Returns:
|
|
131
|
+
HookInstallResult with installation details
|
|
132
|
+
|
|
133
|
+
Raises:
|
|
134
|
+
HookInstallError: If installation fails
|
|
135
|
+
HookConfigError: If configuration is invalid
|
|
136
|
+
|
|
137
|
+
Example:
|
|
138
|
+
>>> sdk = SDK(agent="claude")
|
|
139
|
+
>>> result = sdk.install_hooks()
|
|
140
|
+
>>> logger.info(f"Installed: {result.installed}")
|
|
141
|
+
>>> logger.info(f"Skipped: {result.skipped}")
|
|
142
|
+
>>> if result.warnings:
|
|
143
|
+
... logger.info(f"Warnings: {result.warnings}")
|
|
144
|
+
|
|
145
|
+
See also:
|
|
146
|
+
list_hooks: List installed hooks
|
|
147
|
+
validate_hook_config: Validate hook configuration
|
|
148
|
+
"""
|
|
149
|
+
from htmlgraph.operations import hooks
|
|
150
|
+
|
|
151
|
+
return hooks.install_hooks(
|
|
152
|
+
project_dir=self._directory.parent,
|
|
153
|
+
use_copy=use_copy,
|
|
154
|
+
)
|
|
155
|
+
|
|
156
|
+
def list_hooks(self) -> Any:
|
|
157
|
+
"""
|
|
158
|
+
List Git hooks status (enabled/disabled/missing).
|
|
159
|
+
|
|
160
|
+
Returns:
|
|
161
|
+
HookListResult with enabled, disabled, and missing hooks
|
|
162
|
+
|
|
163
|
+
Example:
|
|
164
|
+
>>> sdk = SDK(agent="claude")
|
|
165
|
+
>>> result = sdk.list_hooks()
|
|
166
|
+
>>> logger.info(f"Enabled: {result.enabled}")
|
|
167
|
+
>>> logger.info(f"Disabled: {result.disabled}")
|
|
168
|
+
>>> logger.info(f"Missing: {result.missing}")
|
|
169
|
+
"""
|
|
170
|
+
from htmlgraph.operations import hooks
|
|
171
|
+
|
|
172
|
+
return hooks.list_hooks(project_dir=self._directory.parent)
|
|
173
|
+
|
|
174
|
+
def validate_hook_config(self) -> Any:
|
|
175
|
+
"""
|
|
176
|
+
Validate hook configuration.
|
|
177
|
+
|
|
178
|
+
Returns:
|
|
179
|
+
HookValidationResult with validation status
|
|
180
|
+
|
|
181
|
+
Example:
|
|
182
|
+
>>> sdk = SDK(agent="claude")
|
|
183
|
+
>>> result = sdk.validate_hook_config()
|
|
184
|
+
>>> if not result.valid:
|
|
185
|
+
... logger.info(f"Errors: {result.errors}")
|
|
186
|
+
>>> if result.warnings:
|
|
187
|
+
... logger.info(f"Warnings: {result.warnings}")
|
|
188
|
+
"""
|
|
189
|
+
from htmlgraph.operations import hooks
|
|
190
|
+
|
|
191
|
+
return hooks.validate_hook_config(project_dir=self._directory.parent)
|
|
192
|
+
|
|
193
|
+
# =========================================================================
|
|
194
|
+
# Event Operations
|
|
195
|
+
# =========================================================================
|
|
196
|
+
|
|
197
|
+
def export_sessions(self, overwrite: bool = False) -> Any:
|
|
198
|
+
"""
|
|
199
|
+
Export legacy session HTML logs to JSONL events.
|
|
200
|
+
|
|
201
|
+
Converts HTML session files to JSONL format for efficient querying.
|
|
202
|
+
|
|
203
|
+
Args:
|
|
204
|
+
overwrite: Whether to overwrite existing JSONL files (default: False)
|
|
205
|
+
|
|
206
|
+
Returns:
|
|
207
|
+
EventExportResult with counts of written, skipped, failed files
|
|
208
|
+
|
|
209
|
+
Raises:
|
|
210
|
+
EventOperationError: If export fails
|
|
211
|
+
|
|
212
|
+
Example:
|
|
213
|
+
>>> sdk = SDK(agent="claude")
|
|
214
|
+
>>> result = sdk.export_sessions()
|
|
215
|
+
>>> logger.info(f"Exported {result.written} sessions")
|
|
216
|
+
>>> logger.info(f"Skipped {result.skipped} (already exist)")
|
|
217
|
+
>>> if result.failed > 0:
|
|
218
|
+
... logger.info(f"Failed {result.failed} sessions")
|
|
219
|
+
|
|
220
|
+
See also:
|
|
221
|
+
rebuild_event_index: Rebuild SQLite index from JSONL
|
|
222
|
+
query_events: Query exported events
|
|
223
|
+
"""
|
|
224
|
+
from htmlgraph.operations import events
|
|
225
|
+
|
|
226
|
+
return events.export_sessions(
|
|
227
|
+
graph_dir=self._directory,
|
|
228
|
+
overwrite=overwrite,
|
|
229
|
+
)
|
|
230
|
+
|
|
231
|
+
def rebuild_event_index(self) -> Any:
|
|
232
|
+
"""
|
|
233
|
+
Rebuild SQLite analytics index from JSONL events.
|
|
234
|
+
|
|
235
|
+
Creates an optimized SQLite index for fast analytics queries.
|
|
236
|
+
|
|
237
|
+
Returns:
|
|
238
|
+
EventRebuildResult with db_path and counts of inserted/skipped events
|
|
239
|
+
|
|
240
|
+
Raises:
|
|
241
|
+
EventOperationError: If rebuild fails
|
|
242
|
+
|
|
243
|
+
Example:
|
|
244
|
+
>>> sdk = SDK(agent="claude")
|
|
245
|
+
>>> result = sdk.rebuild_event_index()
|
|
246
|
+
>>> logger.info(f"Rebuilt index: {result.db_path}")
|
|
247
|
+
>>> logger.info(f"Inserted {result.inserted} events")
|
|
248
|
+
>>> logger.info(f"Skipped {result.skipped} (duplicates)")
|
|
249
|
+
|
|
250
|
+
See also:
|
|
251
|
+
export_sessions: Export HTML sessions to JSONL first
|
|
252
|
+
"""
|
|
253
|
+
from htmlgraph.operations import events
|
|
254
|
+
|
|
255
|
+
return events.rebuild_index(graph_dir=self._directory)
|
|
256
|
+
|
|
257
|
+
def query_events(
|
|
258
|
+
self,
|
|
259
|
+
session_id: str | None = None,
|
|
260
|
+
tool: str | None = None,
|
|
261
|
+
feature_id: str | None = None,
|
|
262
|
+
since: str | None = None,
|
|
263
|
+
limit: int | None = None,
|
|
264
|
+
) -> Any:
|
|
265
|
+
"""
|
|
266
|
+
Query events from JSONL logs with optional filters.
|
|
267
|
+
|
|
268
|
+
Args:
|
|
269
|
+
session_id: Filter by session ID (None = all sessions)
|
|
270
|
+
tool: Filter by tool name (e.g., 'Bash', 'Edit')
|
|
271
|
+
feature_id: Filter by attributed feature ID
|
|
272
|
+
since: Only events after this timestamp (ISO string)
|
|
273
|
+
limit: Maximum number of events to return
|
|
274
|
+
|
|
275
|
+
Returns:
|
|
276
|
+
EventQueryResult with matching events and total count
|
|
277
|
+
|
|
278
|
+
Raises:
|
|
279
|
+
EventOperationError: If query fails
|
|
280
|
+
|
|
281
|
+
Example:
|
|
282
|
+
>>> sdk = SDK(agent="claude")
|
|
283
|
+
>>> # Get all events for a session
|
|
284
|
+
>>> result = sdk.query_events(session_id="sess-123")
|
|
285
|
+
>>> logger.info(f"Found {result.total} events")
|
|
286
|
+
>>>
|
|
287
|
+
>>> # Get recent Bash events
|
|
288
|
+
>>> result = sdk.query_events(
|
|
289
|
+
... tool="Bash",
|
|
290
|
+
... since="2025-01-01T00:00:00Z",
|
|
291
|
+
... limit=10
|
|
292
|
+
... )
|
|
293
|
+
>>> for event in result.events:
|
|
294
|
+
... logger.info(f"{event['timestamp']}: {event['summary']}")
|
|
295
|
+
|
|
296
|
+
See also:
|
|
297
|
+
export_sessions: Export sessions to JSONL first
|
|
298
|
+
get_event_stats: Get event statistics
|
|
299
|
+
"""
|
|
300
|
+
from htmlgraph.operations import events
|
|
301
|
+
|
|
302
|
+
return events.query_events(
|
|
303
|
+
graph_dir=self._directory,
|
|
304
|
+
session_id=session_id,
|
|
305
|
+
tool=tool,
|
|
306
|
+
feature_id=feature_id,
|
|
307
|
+
since=since,
|
|
308
|
+
limit=limit,
|
|
309
|
+
)
|
|
310
|
+
|
|
311
|
+
def get_event_stats(self) -> Any:
|
|
312
|
+
"""
|
|
313
|
+
Get statistics about events in the system.
|
|
314
|
+
|
|
315
|
+
Returns:
|
|
316
|
+
EventStats with counts of total events, sessions, and files
|
|
317
|
+
|
|
318
|
+
Example:
|
|
319
|
+
>>> sdk = SDK(agent="claude")
|
|
320
|
+
>>> stats = sdk.get_event_stats()
|
|
321
|
+
>>> logger.info(f"Total events: {stats.total_events}")
|
|
322
|
+
>>> logger.info(f"Sessions: {stats.session_count}")
|
|
323
|
+
>>> logger.info(f"JSONL files: {stats.file_count}")
|
|
324
|
+
"""
|
|
325
|
+
from htmlgraph.operations import events
|
|
326
|
+
|
|
327
|
+
return events.get_event_stats(graph_dir=self._directory)
|
|
328
|
+
|
|
329
|
+
# =========================================================================
|
|
330
|
+
# Analytics Operations
|
|
331
|
+
# =========================================================================
|
|
332
|
+
|
|
333
|
+
def analyze_session(self, session_id: str) -> Any:
|
|
334
|
+
"""
|
|
335
|
+
Compute detailed analytics for a single session.
|
|
336
|
+
|
|
337
|
+
Analyzes work distribution, spike-to-feature ratio, maintenance burden,
|
|
338
|
+
transition metrics, and more.
|
|
339
|
+
|
|
340
|
+
Args:
|
|
341
|
+
session_id: ID of the session to analyze
|
|
342
|
+
|
|
343
|
+
Returns:
|
|
344
|
+
AnalyticsSessionResult with session metrics and warnings
|
|
345
|
+
|
|
346
|
+
Raises:
|
|
347
|
+
AnalyticsOperationError: If session cannot be analyzed
|
|
348
|
+
|
|
349
|
+
Example:
|
|
350
|
+
>>> sdk = SDK(agent="claude")
|
|
351
|
+
>>> result = sdk.analyze_session("sess-123")
|
|
352
|
+
>>> logger.info(f"Primary work type: {result.metrics['primary_work_type']}")
|
|
353
|
+
>>> logger.info(f"Total events: {result.metrics['total_events']}")
|
|
354
|
+
>>> logger.info(f"Work distribution: {result.metrics['work_distribution']}")
|
|
355
|
+
>>> if result.warnings:
|
|
356
|
+
... logger.info(f"Warnings: {result.warnings}")
|
|
357
|
+
|
|
358
|
+
See also:
|
|
359
|
+
analyze_project: Analyze entire project
|
|
360
|
+
"""
|
|
361
|
+
from htmlgraph.operations import analytics
|
|
362
|
+
|
|
363
|
+
return analytics.analyze_session(
|
|
364
|
+
graph_dir=self._directory,
|
|
365
|
+
session_id=session_id,
|
|
366
|
+
)
|
|
367
|
+
|
|
368
|
+
def analyze_project(self) -> Any:
|
|
369
|
+
"""
|
|
370
|
+
Compute project-wide analytics.
|
|
371
|
+
|
|
372
|
+
Analyzes all sessions, work distribution, spike-to-feature ratios,
|
|
373
|
+
maintenance burden, and session types across the entire project.
|
|
374
|
+
|
|
375
|
+
Returns:
|
|
376
|
+
AnalyticsProjectResult with project metrics and warnings
|
|
377
|
+
|
|
378
|
+
Raises:
|
|
379
|
+
AnalyticsOperationError: If project cannot be analyzed
|
|
380
|
+
|
|
381
|
+
Example:
|
|
382
|
+
>>> sdk = SDK(agent="claude")
|
|
383
|
+
>>> result = sdk.analyze_project()
|
|
384
|
+
>>> logger.info(f"Total sessions: {result.metrics['total_sessions']}")
|
|
385
|
+
>>> logger.info(f"Work distribution: {result.metrics['work_distribution']}")
|
|
386
|
+
>>> logger.info(f"Spike-to-feature ratio: {result.metrics['spike_to_feature_ratio']}")
|
|
387
|
+
>>> logger.info(f"Session types: {result.metrics['session_types']}")
|
|
388
|
+
>>> for session in result.metrics['recent_sessions']:
|
|
389
|
+
... logger.info(f" {session['session_id']}: {session['primary_work_type']}")
|
|
390
|
+
|
|
391
|
+
See also:
|
|
392
|
+
analyze_session: Analyze a single session
|
|
393
|
+
get_work_recommendations: Get work recommendations
|
|
394
|
+
"""
|
|
395
|
+
from htmlgraph.operations import analytics
|
|
396
|
+
|
|
397
|
+
return analytics.analyze_project(graph_dir=self._directory)
|
|
398
|
+
|
|
399
|
+
def get_work_recommendations(self) -> Any:
|
|
400
|
+
"""
|
|
401
|
+
Get smart work recommendations based on project state.
|
|
402
|
+
|
|
403
|
+
Uses dependency analytics to recommend next tasks based on priority,
|
|
404
|
+
dependencies, and impact.
|
|
405
|
+
|
|
406
|
+
Returns:
|
|
407
|
+
RecommendationsResult with recommendations, reasoning, and warnings
|
|
408
|
+
|
|
409
|
+
Raises:
|
|
410
|
+
AnalyticsOperationError: If recommendations cannot be generated
|
|
411
|
+
|
|
412
|
+
Example:
|
|
413
|
+
>>> sdk = SDK(agent="claude")
|
|
414
|
+
>>> result = sdk.get_work_recommendations()
|
|
415
|
+
>>> for rec in result.recommendations:
|
|
416
|
+
... logger.info(f"{rec['title']} (score: {rec['score']})")
|
|
417
|
+
... logger.info(f" Reasons: {rec['reasons']}")
|
|
418
|
+
... logger.info(f" Unlocks: {rec['unlocks']}")
|
|
419
|
+
>>> logger.info(f"Reasoning: {result.reasoning}")
|
|
420
|
+
|
|
421
|
+
See also:
|
|
422
|
+
recommend_next_work: Legacy method (backward compatibility)
|
|
423
|
+
get_work_queue: Get prioritized work queue
|
|
424
|
+
"""
|
|
425
|
+
from htmlgraph.operations import analytics
|
|
426
|
+
|
|
427
|
+
return analytics.get_recommendations(graph_dir=self._directory)
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Orchestration module for spawning and coordinating subagents.
|
|
3
|
+
|
|
4
|
+
Provides:
|
|
5
|
+
- OrchestrationMixin: Mixin for SDK with orchestration capabilities
|
|
6
|
+
- Spawner utilities for creating explorer/coder agents
|
|
7
|
+
- Coordinator for managing multi-agent workflows
|
|
8
|
+
|
|
9
|
+
Public API:
|
|
10
|
+
from htmlgraph.sdk.orchestration import OrchestrationMixin
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
from htmlgraph.sdk.orchestration.coordinator import OrchestrationMixin
|
|
14
|
+
|
|
15
|
+
__all__ = [
|
|
16
|
+
"OrchestrationMixin",
|
|
17
|
+
]
|
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Orchestration coordinator - manages subagent spawning and workflows.
|
|
3
|
+
|
|
4
|
+
Provides OrchestrationMixin with:
|
|
5
|
+
- orchestrator property (lazy-loaded SubagentOrchestrator)
|
|
6
|
+
- spawn_explorer() - Spawn explorer subagent for codebase discovery
|
|
7
|
+
- spawn_coder() - Spawn coder subagent for implementation
|
|
8
|
+
- orchestrate() - Full exploration + implementation workflow
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
from __future__ import annotations
|
|
12
|
+
|
|
13
|
+
from typing import TYPE_CHECKING, Any
|
|
14
|
+
|
|
15
|
+
if TYPE_CHECKING:
|
|
16
|
+
from htmlgraph.sdk import SDK as SDK_TYPE
|
|
17
|
+
else:
|
|
18
|
+
SDK_TYPE = "SDK" # type: ignore[misc,assignment]
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
class OrchestrationMixin:
|
|
22
|
+
"""
|
|
23
|
+
Mixin providing orchestration capabilities to SDK.
|
|
24
|
+
|
|
25
|
+
Adds methods for spawning and coordinating subagents.
|
|
26
|
+
Requires SDK instance with _orchestrator attribute.
|
|
27
|
+
"""
|
|
28
|
+
|
|
29
|
+
_orchestrator: Any
|
|
30
|
+
_directory: Any
|
|
31
|
+
|
|
32
|
+
def __init__(self) -> None:
|
|
33
|
+
"""Initialize orchestration state."""
|
|
34
|
+
self._orchestrator = None
|
|
35
|
+
|
|
36
|
+
@property
|
|
37
|
+
def orchestrator(self) -> Any:
|
|
38
|
+
"""
|
|
39
|
+
Get the subagent orchestrator for spawning explorer/coder agents.
|
|
40
|
+
|
|
41
|
+
Lazy-loaded on first access.
|
|
42
|
+
|
|
43
|
+
Returns:
|
|
44
|
+
SubagentOrchestrator instance
|
|
45
|
+
|
|
46
|
+
Example:
|
|
47
|
+
>>> sdk = SDK(agent="claude")
|
|
48
|
+
>>> explorer = sdk.orchestrator.spawn_explorer(
|
|
49
|
+
... task="Find all API endpoints",
|
|
50
|
+
... scope="src/"
|
|
51
|
+
... )
|
|
52
|
+
"""
|
|
53
|
+
if self._orchestrator is None:
|
|
54
|
+
from htmlgraph.orchestrator import SubagentOrchestrator
|
|
55
|
+
|
|
56
|
+
self._orchestrator = SubagentOrchestrator(self) # type: ignore[arg-type,assignment]
|
|
57
|
+
return self._orchestrator
|
|
58
|
+
|
|
59
|
+
def spawn_explorer(
|
|
60
|
+
self,
|
|
61
|
+
task: str,
|
|
62
|
+
scope: str | None = None,
|
|
63
|
+
patterns: list[str] | None = None,
|
|
64
|
+
questions: list[str] | None = None,
|
|
65
|
+
) -> dict[str, Any]:
|
|
66
|
+
"""
|
|
67
|
+
Spawn an explorer subagent for codebase discovery.
|
|
68
|
+
|
|
69
|
+
Explorer agents are optimized for finding files, searching patterns,
|
|
70
|
+
and mapping code without modifying anything.
|
|
71
|
+
|
|
72
|
+
Args:
|
|
73
|
+
task: What to explore/discover
|
|
74
|
+
scope: Directory scope (e.g., "src/")
|
|
75
|
+
patterns: Glob patterns to focus on
|
|
76
|
+
questions: Specific questions to answer
|
|
77
|
+
|
|
78
|
+
Returns:
|
|
79
|
+
Dict with prompt ready for Task tool
|
|
80
|
+
|
|
81
|
+
Note:
|
|
82
|
+
Returns dict with 'prompt', 'description', 'subagent_type' keys.
|
|
83
|
+
Returns empty dict if spawning fails.
|
|
84
|
+
|
|
85
|
+
Example:
|
|
86
|
+
>>> prompt = sdk.spawn_explorer(
|
|
87
|
+
... task="Find all database models",
|
|
88
|
+
... scope="src/models/",
|
|
89
|
+
... questions=["What ORM is used?"]
|
|
90
|
+
... )
|
|
91
|
+
>>> # Execute with Task tool
|
|
92
|
+
>>> Task(prompt=prompt["prompt"], description=prompt["description"])
|
|
93
|
+
|
|
94
|
+
See also:
|
|
95
|
+
spawn_coder: Spawn implementation agent with feature context
|
|
96
|
+
orchestrate: Full exploration + implementation workflow
|
|
97
|
+
"""
|
|
98
|
+
subagent_prompt = self.orchestrator.spawn_explorer(
|
|
99
|
+
task=task,
|
|
100
|
+
scope=scope,
|
|
101
|
+
patterns=patterns,
|
|
102
|
+
questions=questions,
|
|
103
|
+
)
|
|
104
|
+
result: dict[str, Any] = subagent_prompt.to_task_kwargs()
|
|
105
|
+
return result
|
|
106
|
+
|
|
107
|
+
def spawn_coder(
|
|
108
|
+
self,
|
|
109
|
+
feature_id: str,
|
|
110
|
+
context: str | None = None,
|
|
111
|
+
files_to_modify: list[str] | None = None,
|
|
112
|
+
test_command: str | None = None,
|
|
113
|
+
) -> dict[str, Any]:
|
|
114
|
+
"""
|
|
115
|
+
Spawn a coder subagent for implementing changes.
|
|
116
|
+
|
|
117
|
+
Coder agents are optimized for reading, modifying, and testing code.
|
|
118
|
+
|
|
119
|
+
Args:
|
|
120
|
+
feature_id: Feature being implemented
|
|
121
|
+
context: Results from explorer (string summary)
|
|
122
|
+
files_to_modify: Specific files to change
|
|
123
|
+
test_command: Command to verify changes
|
|
124
|
+
|
|
125
|
+
Returns:
|
|
126
|
+
Dict with prompt ready for Task tool
|
|
127
|
+
|
|
128
|
+
Note:
|
|
129
|
+
Returns dict with 'prompt', 'description', 'subagent_type' keys.
|
|
130
|
+
Requires valid feature_id. Returns empty dict if feature not found.
|
|
131
|
+
|
|
132
|
+
Example:
|
|
133
|
+
>>> prompt = sdk.spawn_coder(
|
|
134
|
+
... feature_id="feat-add-auth",
|
|
135
|
+
... context=explorer_results,
|
|
136
|
+
... test_command="uv run pytest tests/auth/"
|
|
137
|
+
... )
|
|
138
|
+
>>> Task(prompt=prompt["prompt"], description=prompt["description"])
|
|
139
|
+
|
|
140
|
+
See also:
|
|
141
|
+
spawn_explorer: Explore codebase before implementation
|
|
142
|
+
orchestrate: Full exploration + implementation workflow
|
|
143
|
+
"""
|
|
144
|
+
subagent_prompt = self.orchestrator.spawn_coder(
|
|
145
|
+
feature_id=feature_id,
|
|
146
|
+
context=context,
|
|
147
|
+
files_to_modify=files_to_modify,
|
|
148
|
+
test_command=test_command,
|
|
149
|
+
)
|
|
150
|
+
result: dict[str, Any] = subagent_prompt.to_task_kwargs()
|
|
151
|
+
return result
|
|
152
|
+
|
|
153
|
+
def orchestrate(
|
|
154
|
+
self,
|
|
155
|
+
feature_id: str,
|
|
156
|
+
exploration_scope: str | None = None,
|
|
157
|
+
test_command: str | None = None,
|
|
158
|
+
) -> dict[str, Any]:
|
|
159
|
+
"""
|
|
160
|
+
Orchestrate full feature implementation with explorer and coder.
|
|
161
|
+
|
|
162
|
+
Generates prompts for a two-phase workflow:
|
|
163
|
+
1. Explorer discovers relevant code and patterns
|
|
164
|
+
2. Coder implements the feature based on explorer findings
|
|
165
|
+
|
|
166
|
+
Args:
|
|
167
|
+
feature_id: Feature to implement
|
|
168
|
+
exploration_scope: Directory to explore
|
|
169
|
+
test_command: Test command for verification
|
|
170
|
+
|
|
171
|
+
Returns:
|
|
172
|
+
Dict with explorer and coder prompts
|
|
173
|
+
|
|
174
|
+
Example:
|
|
175
|
+
>>> prompts = sdk.orchestrate(
|
|
176
|
+
... "feat-add-caching",
|
|
177
|
+
... exploration_scope="src/cache/",
|
|
178
|
+
... test_command="uv run pytest tests/cache/"
|
|
179
|
+
... )
|
|
180
|
+
>>> # Phase 1: Run explorer
|
|
181
|
+
>>> Task(prompt=prompts["explorer"]["prompt"], ...)
|
|
182
|
+
>>> # Phase 2: Run coder with explorer results
|
|
183
|
+
>>> Task(prompt=prompts["coder"]["prompt"], ...)
|
|
184
|
+
|
|
185
|
+
See also:
|
|
186
|
+
spawn_explorer: Just the exploration phase
|
|
187
|
+
spawn_coder: Just the implementation phase
|
|
188
|
+
"""
|
|
189
|
+
prompts = self.orchestrator.orchestrate_feature(
|
|
190
|
+
feature_id=feature_id,
|
|
191
|
+
exploration_scope=exploration_scope,
|
|
192
|
+
test_command=test_command,
|
|
193
|
+
)
|
|
194
|
+
return {
|
|
195
|
+
"explorer": prompts["explorer"].to_task_kwargs(),
|
|
196
|
+
"coder": prompts["coder"].to_task_kwargs(),
|
|
197
|
+
"workflow": [
|
|
198
|
+
"1. Execute explorer Task and collect results",
|
|
199
|
+
"2. Parse explorer results for files and patterns",
|
|
200
|
+
"3. Execute coder Task with explorer context",
|
|
201
|
+
"4. Verify coder results and update feature status",
|
|
202
|
+
],
|
|
203
|
+
}
|