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,350 @@
|
|
|
1
|
+
<!-- Orchestration View Component
|
|
2
|
+
Displays agent delegation chains and coordination topology.
|
|
3
|
+
Fetches from /api/orchestration endpoint.
|
|
4
|
+
-->
|
|
5
|
+
|
|
6
|
+
<div id="orchestration-view" class="orchestration-container">
|
|
7
|
+
<div class="orchestration-header">
|
|
8
|
+
<h2>Agent Orchestration</h2>
|
|
9
|
+
<p class="subtitle">Delegation chains and agent coordination</p>
|
|
10
|
+
</div>
|
|
11
|
+
|
|
12
|
+
<div class="orchestration-metrics">
|
|
13
|
+
<div class="metric-card">
|
|
14
|
+
<div class="metric-label">Total Delegations</div>
|
|
15
|
+
<div class="metric-value" id="delegation-count">0</div>
|
|
16
|
+
</div>
|
|
17
|
+
<div class="metric-card">
|
|
18
|
+
<div class="metric-label">Unique Agents</div>
|
|
19
|
+
<div class="metric-value" id="unique-agents">0</div>
|
|
20
|
+
</div>
|
|
21
|
+
<div class="metric-card">
|
|
22
|
+
<div class="metric-label">Active Agents</div>
|
|
23
|
+
<div class="metric-value" id="agent-list">—</div>
|
|
24
|
+
</div>
|
|
25
|
+
</div>
|
|
26
|
+
|
|
27
|
+
<div class="orchestration-chains" id="delegation-chains">
|
|
28
|
+
<div class="empty-state">
|
|
29
|
+
<p>No delegation events recorded yet.</p>
|
|
30
|
+
<p class="hint">Delegation events will appear here when Task() calls are made.</p>
|
|
31
|
+
</div>
|
|
32
|
+
</div>
|
|
33
|
+
|
|
34
|
+
<div class="orchestration-legend">
|
|
35
|
+
<div class="legend-item">
|
|
36
|
+
<span class="status-badge pending"></span>
|
|
37
|
+
<span>Pending</span>
|
|
38
|
+
</div>
|
|
39
|
+
<div class="legend-item">
|
|
40
|
+
<span class="status-badge accepted"></span>
|
|
41
|
+
<span>Accepted</span>
|
|
42
|
+
</div>
|
|
43
|
+
<div class="legend-item">
|
|
44
|
+
<span class="status-badge completed"></span>
|
|
45
|
+
<span>Completed</span>
|
|
46
|
+
</div>
|
|
47
|
+
<div class="legend-item">
|
|
48
|
+
<span class="status-badge failed"></span>
|
|
49
|
+
<span>Failed</span>
|
|
50
|
+
</div>
|
|
51
|
+
</div>
|
|
52
|
+
</div>
|
|
53
|
+
|
|
54
|
+
<style>
|
|
55
|
+
.orchestration-container {
|
|
56
|
+
padding: 2rem;
|
|
57
|
+
background: var(--bg-secondary);
|
|
58
|
+
border: 1px solid var(--border);
|
|
59
|
+
border-radius: 4px;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
.orchestration-header {
|
|
63
|
+
margin-bottom: 2rem;
|
|
64
|
+
border-bottom: 2px solid var(--border);
|
|
65
|
+
padding-bottom: 1rem;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
.orchestration-header h2 {
|
|
69
|
+
font-size: 1.5rem;
|
|
70
|
+
color: var(--text-primary);
|
|
71
|
+
margin-bottom: 0.5rem;
|
|
72
|
+
font-weight: 600;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
.orchestration-header .subtitle {
|
|
76
|
+
color: var(--text-secondary);
|
|
77
|
+
font-size: 0.9rem;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
.orchestration-metrics {
|
|
81
|
+
display: grid;
|
|
82
|
+
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
|
|
83
|
+
gap: 1rem;
|
|
84
|
+
margin-bottom: 2rem;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
.metric-card {
|
|
88
|
+
background: var(--bg-tertiary);
|
|
89
|
+
border: 1px solid var(--border);
|
|
90
|
+
border-radius: 4px;
|
|
91
|
+
padding: 1.5rem;
|
|
92
|
+
text-align: center;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
.metric-label {
|
|
96
|
+
color: var(--text-secondary);
|
|
97
|
+
font-size: 0.9rem;
|
|
98
|
+
margin-bottom: 0.5rem;
|
|
99
|
+
text-transform: uppercase;
|
|
100
|
+
letter-spacing: 0.05em;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
.metric-value {
|
|
104
|
+
font-size: 2rem;
|
|
105
|
+
font-weight: 700;
|
|
106
|
+
color: var(--accent);
|
|
107
|
+
font-family: 'JetBrains Mono', monospace;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
.orchestration-chains {
|
|
111
|
+
margin-bottom: 2rem;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
.empty-state {
|
|
115
|
+
text-align: center;
|
|
116
|
+
padding: 3rem 1rem;
|
|
117
|
+
color: var(--text-secondary);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
.empty-state p {
|
|
121
|
+
margin-bottom: 0.5rem;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
.empty-state .hint {
|
|
125
|
+
font-size: 0.85rem;
|
|
126
|
+
color: var(--text-muted);
|
|
127
|
+
font-style: italic;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
.delegation-chain {
|
|
131
|
+
margin-bottom: 1.5rem;
|
|
132
|
+
border-left: 3px solid var(--status-active);
|
|
133
|
+
padding-left: 1rem;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
.chain-from-agent {
|
|
137
|
+
font-weight: 600;
|
|
138
|
+
color: var(--text-primary);
|
|
139
|
+
font-size: 1rem;
|
|
140
|
+
margin-bottom: 0.5rem;
|
|
141
|
+
padding: 0.75rem;
|
|
142
|
+
background: rgba(41, 121, 255, 0.1);
|
|
143
|
+
border-radius: 4px;
|
|
144
|
+
border-left: 3px solid var(--status-active);
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
.chain-delegations {
|
|
148
|
+
margin-top: 0.5rem;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
.delegation-item {
|
|
152
|
+
display: flex;
|
|
153
|
+
align-items: flex-start;
|
|
154
|
+
gap: 1rem;
|
|
155
|
+
padding: 0.75rem;
|
|
156
|
+
margin-bottom: 0.5rem;
|
|
157
|
+
background: var(--bg-tertiary);
|
|
158
|
+
border-radius: 3px;
|
|
159
|
+
border-left: 3px solid var(--status-active);
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
.delegation-arrow {
|
|
163
|
+
color: var(--text-secondary);
|
|
164
|
+
font-weight: bold;
|
|
165
|
+
min-width: 1rem;
|
|
166
|
+
text-align: center;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
.delegation-details {
|
|
170
|
+
flex: 1;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
.delegation-to-agent {
|
|
174
|
+
font-weight: 600;
|
|
175
|
+
color: var(--text-primary);
|
|
176
|
+
font-size: 0.95rem;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
.delegation-task {
|
|
180
|
+
color: var(--text-secondary);
|
|
181
|
+
font-size: 0.85rem;
|
|
182
|
+
margin: 0.25rem 0;
|
|
183
|
+
font-family: 'JetBrains Mono', monospace;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
.delegation-timestamp {
|
|
187
|
+
color: var(--text-muted);
|
|
188
|
+
font-size: 0.8rem;
|
|
189
|
+
margin-top: 0.25rem;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
.status-badge {
|
|
193
|
+
display: inline-block;
|
|
194
|
+
width: 0.75rem;
|
|
195
|
+
height: 0.75rem;
|
|
196
|
+
border-radius: 50%;
|
|
197
|
+
margin-right: 0.5rem;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
.status-badge.pending {
|
|
201
|
+
background: var(--status-todo);
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
.status-badge.accepted {
|
|
205
|
+
background: var(--status-active);
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
.status-badge.completed {
|
|
209
|
+
background: var(--status-done);
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
.status-badge.failed {
|
|
213
|
+
background: var(--status-blocked);
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
.delegation-status {
|
|
217
|
+
display: inline-flex;
|
|
218
|
+
align-items: center;
|
|
219
|
+
gap: 0.5rem;
|
|
220
|
+
font-size: 0.8rem;
|
|
221
|
+
padding: 0.25rem 0.5rem;
|
|
222
|
+
background: var(--bg-primary);
|
|
223
|
+
border-radius: 3px;
|
|
224
|
+
margin-left: auto;
|
|
225
|
+
text-transform: uppercase;
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
.orchestration-legend {
|
|
229
|
+
display: flex;
|
|
230
|
+
gap: 1.5rem;
|
|
231
|
+
padding: 1rem;
|
|
232
|
+
background: var(--bg-tertiary);
|
|
233
|
+
border-radius: 4px;
|
|
234
|
+
flex-wrap: wrap;
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
.legend-item {
|
|
238
|
+
display: flex;
|
|
239
|
+
align-items: center;
|
|
240
|
+
gap: 0.5rem;
|
|
241
|
+
font-size: 0.85rem;
|
|
242
|
+
color: var(--text-secondary);
|
|
243
|
+
}
|
|
244
|
+
</style>
|
|
245
|
+
|
|
246
|
+
<script>
|
|
247
|
+
function renderOrchestrationView(data) {
|
|
248
|
+
document.getElementById('delegation-count').textContent = data.delegation_count;
|
|
249
|
+
document.getElementById('unique-agents').textContent = data.unique_agents;
|
|
250
|
+
document.getElementById('agent-list').textContent = data.agents.join(', ') || '—';
|
|
251
|
+
|
|
252
|
+
const chainsContainer = document.getElementById('delegation-chains');
|
|
253
|
+
|
|
254
|
+
if (data.delegation_count === 0) {
|
|
255
|
+
chainsContainer.textContent = '';
|
|
256
|
+
const emptyDiv = document.createElement('div');
|
|
257
|
+
emptyDiv.className = 'empty-state';
|
|
258
|
+
emptyDiv.innerHTML = '<p>No delegation events recorded yet.</p><p class="hint">Delegation events will appear here when Task() calls are made.</p>';
|
|
259
|
+
chainsContainer.appendChild(emptyDiv);
|
|
260
|
+
return;
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
chainsContainer.textContent = '';
|
|
264
|
+
|
|
265
|
+
for (const fromAgent in data.delegation_chains) {
|
|
266
|
+
const delegations = data.delegation_chains[fromAgent];
|
|
267
|
+
const chainDiv = document.createElement('div');
|
|
268
|
+
chainDiv.className = 'delegation-chain';
|
|
269
|
+
|
|
270
|
+
const fromAgentDiv = document.createElement('div');
|
|
271
|
+
fromAgentDiv.className = 'chain-from-agent';
|
|
272
|
+
fromAgentDiv.textContent = fromAgent;
|
|
273
|
+
chainDiv.appendChild(fromAgentDiv);
|
|
274
|
+
|
|
275
|
+
const delegationsDiv = document.createElement('div');
|
|
276
|
+
delegationsDiv.className = 'chain-delegations';
|
|
277
|
+
|
|
278
|
+
for (const delegation of delegations) {
|
|
279
|
+
const itemDiv = document.createElement('div');
|
|
280
|
+
itemDiv.className = 'delegation-item';
|
|
281
|
+
|
|
282
|
+
const arrowDiv = document.createElement('div');
|
|
283
|
+
arrowDiv.className = 'delegation-arrow';
|
|
284
|
+
arrowDiv.textContent = '↓';
|
|
285
|
+
itemDiv.appendChild(arrowDiv);
|
|
286
|
+
|
|
287
|
+
const detailsDiv = document.createElement('div');
|
|
288
|
+
detailsDiv.className = 'delegation-details';
|
|
289
|
+
|
|
290
|
+
const toAgentDiv = document.createElement('div');
|
|
291
|
+
toAgentDiv.className = 'delegation-to-agent';
|
|
292
|
+
toAgentDiv.textContent = delegation.to_agent;
|
|
293
|
+
detailsDiv.appendChild(toAgentDiv);
|
|
294
|
+
|
|
295
|
+
const taskDiv = document.createElement('div');
|
|
296
|
+
taskDiv.className = 'delegation-task';
|
|
297
|
+
taskDiv.textContent = 'Task: ' + delegation.task;
|
|
298
|
+
detailsDiv.appendChild(taskDiv);
|
|
299
|
+
|
|
300
|
+
const timeDiv = document.createElement('div');
|
|
301
|
+
timeDiv.className = 'delegation-timestamp';
|
|
302
|
+
try {
|
|
303
|
+
const date = new Date(delegation.timestamp);
|
|
304
|
+
timeDiv.textContent = date.toLocaleString();
|
|
305
|
+
} catch {
|
|
306
|
+
timeDiv.textContent = delegation.timestamp || 'N/A';
|
|
307
|
+
}
|
|
308
|
+
detailsDiv.appendChild(timeDiv);
|
|
309
|
+
|
|
310
|
+
itemDiv.appendChild(detailsDiv);
|
|
311
|
+
|
|
312
|
+
const statusDiv = document.createElement('div');
|
|
313
|
+
statusDiv.className = 'delegation-status';
|
|
314
|
+
const badgeSpan = document.createElement('span');
|
|
315
|
+
badgeSpan.className = 'status-badge ' + (delegation.status || 'pending');
|
|
316
|
+
statusDiv.appendChild(badgeSpan);
|
|
317
|
+
const statusText = document.createTextNode((delegation.status || 'pending').charAt(0).toUpperCase() + (delegation.status || 'pending').slice(1));
|
|
318
|
+
statusDiv.appendChild(statusText);
|
|
319
|
+
itemDiv.appendChild(statusDiv);
|
|
320
|
+
|
|
321
|
+
delegationsDiv.appendChild(itemDiv);
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
chainDiv.appendChild(delegationsDiv);
|
|
325
|
+
chainsContainer.appendChild(chainDiv);
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
async function loadOrchestrationView() {
|
|
330
|
+
try {
|
|
331
|
+
const response = await fetch('/api/orchestration');
|
|
332
|
+
if (!response.ok) {
|
|
333
|
+
console.warn('Orchestration view not available');
|
|
334
|
+
return;
|
|
335
|
+
}
|
|
336
|
+
const data = await response.json();
|
|
337
|
+
renderOrchestrationView(data);
|
|
338
|
+
} catch (error) {
|
|
339
|
+
console.error('Failed to load orchestration view:', error);
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
if (document.readyState === 'loading') {
|
|
344
|
+
document.addEventListener('DOMContentLoaded', loadOrchestrationView);
|
|
345
|
+
} else {
|
|
346
|
+
loadOrchestrationView();
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
setInterval(loadOrchestrationView, 10000);
|
|
350
|
+
</script>
|
htmlgraph/track_builder.py
CHANGED
|
@@ -1,48 +1,67 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
1
3
|
"""
|
|
2
4
|
Track Builder and Collection for agent-friendly track creation.
|
|
3
5
|
|
|
4
6
|
Note: TrackBuilder has been moved to builders/track.py for better organization.
|
|
5
7
|
This module now provides TrackCollection and re-exports TrackBuilder for backward compatibility.
|
|
6
8
|
"""
|
|
7
|
-
|
|
8
|
-
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
from collections.abc import Iterator
|
|
12
|
+
from contextlib import contextmanager
|
|
13
|
+
from typing import TYPE_CHECKING, Any
|
|
9
14
|
|
|
10
15
|
if TYPE_CHECKING:
|
|
16
|
+
from htmlgraph.graph import HtmlGraph
|
|
17
|
+
from htmlgraph.models import Node
|
|
11
18
|
from htmlgraph.sdk import SDK
|
|
12
19
|
|
|
13
20
|
# Import TrackBuilder from its new location
|
|
14
21
|
from htmlgraph.builders.track import TrackBuilder # noqa: F401
|
|
22
|
+
from htmlgraph.exceptions import NodeNotFoundError
|
|
15
23
|
|
|
16
24
|
|
|
17
25
|
class TrackCollection:
|
|
18
26
|
"""Collection interface for tracks with builder support and directory-based loading."""
|
|
19
27
|
|
|
20
|
-
def __init__(self, sdk:
|
|
28
|
+
def __init__(self, sdk: SDK):
|
|
21
29
|
self._sdk = sdk
|
|
22
30
|
self._collection_name = "tracks"
|
|
23
31
|
self._node_type = "track"
|
|
24
32
|
self.collection_name = "tracks" # For backward compatibility
|
|
25
33
|
self.id_prefix = "track"
|
|
26
|
-
self._graph = None # Lazy-loaded
|
|
34
|
+
self._graph: HtmlGraph | None = None # Lazy-loaded
|
|
35
|
+
self._ref_manager: Any = None # Set by SDK during initialization
|
|
36
|
+
|
|
37
|
+
def set_ref_manager(self, ref_manager: Any) -> None:
|
|
38
|
+
"""
|
|
39
|
+
Set the ref manager for this collection.
|
|
27
40
|
|
|
28
|
-
|
|
41
|
+
Called by SDK during initialization to enable short ref support.
|
|
42
|
+
|
|
43
|
+
Args:
|
|
44
|
+
ref_manager: RefManager instance from SDK
|
|
45
|
+
"""
|
|
46
|
+
self._ref_manager = ref_manager
|
|
47
|
+
|
|
48
|
+
def _ensure_graph(self) -> HtmlGraph:
|
|
29
49
|
"""Lazy-load the graph for tracks with multi-pattern support."""
|
|
30
50
|
if self._graph is None:
|
|
31
51
|
from htmlgraph.graph import HtmlGraph
|
|
52
|
+
|
|
32
53
|
collection_path = self._sdk._directory / self._collection_name
|
|
33
54
|
# Support both single-file tracks (track-xxx.html) and directory-based (track-xxx/index.html)
|
|
34
55
|
self._graph = HtmlGraph(
|
|
35
|
-
collection_path,
|
|
36
|
-
auto_load=True,
|
|
37
|
-
pattern=["*.html", "*/index.html"]
|
|
56
|
+
collection_path, auto_load=True, pattern=["*.html", "*/index.html"]
|
|
38
57
|
)
|
|
39
58
|
return self._graph
|
|
40
59
|
|
|
41
|
-
def get(self, node_id: str):
|
|
60
|
+
def get(self, node_id: str) -> Node | None:
|
|
42
61
|
"""Get a track by ID."""
|
|
43
62
|
return self._ensure_graph().get(node_id)
|
|
44
63
|
|
|
45
|
-
def all(self):
|
|
64
|
+
def all(self) -> list[Node]:
|
|
46
65
|
"""Get all tracks (both file-based and directory-based)."""
|
|
47
66
|
return [n for n in self._ensure_graph() if n.type == self._node_type]
|
|
48
67
|
|
|
@@ -50,20 +69,21 @@ class TrackCollection:
|
|
|
50
69
|
self,
|
|
51
70
|
status: str | None = None,
|
|
52
71
|
priority: str | None = None,
|
|
53
|
-
**extra_filters
|
|
54
|
-
):
|
|
72
|
+
**extra_filters: Any,
|
|
73
|
+
) -> list[Node]:
|
|
55
74
|
"""
|
|
56
75
|
Query tracks with filters.
|
|
57
76
|
|
|
58
77
|
Example:
|
|
59
78
|
active_tracks = sdk.tracks.where(status="active", priority="high")
|
|
60
79
|
"""
|
|
61
|
-
|
|
80
|
+
|
|
81
|
+
def matches(node: Node) -> bool:
|
|
62
82
|
if node.type != self._node_type:
|
|
63
83
|
return False
|
|
64
|
-
if status and getattr(node,
|
|
84
|
+
if status and getattr(node, "status", None) != status:
|
|
65
85
|
return False
|
|
66
|
-
if priority and getattr(node,
|
|
86
|
+
if priority and getattr(node, "priority", None) != priority:
|
|
67
87
|
return False
|
|
68
88
|
|
|
69
89
|
# Check extra filters
|
|
@@ -75,6 +95,56 @@ class TrackCollection:
|
|
|
75
95
|
|
|
76
96
|
return self._ensure_graph().filter(matches)
|
|
77
97
|
|
|
98
|
+
@contextmanager
|
|
99
|
+
def edit(self, track_id: str) -> Iterator[Node]:
|
|
100
|
+
"""
|
|
101
|
+
Context manager for editing a track.
|
|
102
|
+
|
|
103
|
+
Auto-saves on exit.
|
|
104
|
+
|
|
105
|
+
Args:
|
|
106
|
+
track_id: Track ID to edit
|
|
107
|
+
|
|
108
|
+
Yields:
|
|
109
|
+
The track node to edit
|
|
110
|
+
|
|
111
|
+
Raises:
|
|
112
|
+
NodeNotFoundError: If track not found
|
|
113
|
+
|
|
114
|
+
Example:
|
|
115
|
+
>>> with sdk.tracks.edit("track-abc123") as track:
|
|
116
|
+
... track.status = "completed"
|
|
117
|
+
... track.title = "Updated Title"
|
|
118
|
+
"""
|
|
119
|
+
graph = self._ensure_graph()
|
|
120
|
+
node = graph.get(track_id)
|
|
121
|
+
if not node:
|
|
122
|
+
raise NodeNotFoundError(self._node_type, track_id)
|
|
123
|
+
|
|
124
|
+
yield node
|
|
125
|
+
|
|
126
|
+
# Auto-save on exit
|
|
127
|
+
graph.update(node)
|
|
128
|
+
|
|
129
|
+
def create(self, title: str) -> TrackBuilder:
|
|
130
|
+
"""
|
|
131
|
+
Create a new track with fluent interface.
|
|
132
|
+
|
|
133
|
+
Args:
|
|
134
|
+
title: Track title
|
|
135
|
+
|
|
136
|
+
Returns:
|
|
137
|
+
TrackBuilder for method chaining
|
|
138
|
+
|
|
139
|
+
Example:
|
|
140
|
+
track = sdk.tracks.create("Multi-Agent Collaboration") \\
|
|
141
|
+
.set_priority("high") \\
|
|
142
|
+
.save()
|
|
143
|
+
"""
|
|
144
|
+
builder = TrackBuilder(self._sdk)
|
|
145
|
+
builder._title = title
|
|
146
|
+
return builder
|
|
147
|
+
|
|
78
148
|
def builder(self) -> TrackBuilder:
|
|
79
149
|
"""
|
|
80
150
|
Create a new track builder with fluent interface.
|
|
@@ -91,3 +161,64 @@ class TrackCollection:
|
|
|
91
161
|
.create()
|
|
92
162
|
"""
|
|
93
163
|
return TrackBuilder(self._sdk)
|
|
164
|
+
|
|
165
|
+
def delete(self, track_id: str) -> bool:
|
|
166
|
+
"""
|
|
167
|
+
Delete a track by ID.
|
|
168
|
+
|
|
169
|
+
Handles both single-file tracks (.html) and directory-based tracks (folder).
|
|
170
|
+
|
|
171
|
+
Args:
|
|
172
|
+
track_id: The track ID to delete
|
|
173
|
+
|
|
174
|
+
Returns:
|
|
175
|
+
True if deleted, False if not found
|
|
176
|
+
|
|
177
|
+
Example:
|
|
178
|
+
sdk.tracks.delete("track-abc123")
|
|
179
|
+
"""
|
|
180
|
+
import shutil
|
|
181
|
+
|
|
182
|
+
collection_path = self._sdk._directory / self._collection_name
|
|
183
|
+
|
|
184
|
+
# Check for single-file track: {track_id}.html
|
|
185
|
+
single_file = collection_path / f"{track_id}.html"
|
|
186
|
+
if single_file.exists():
|
|
187
|
+
single_file.unlink()
|
|
188
|
+
# Also remove from graph cache if loaded
|
|
189
|
+
if self._graph is not None and track_id in self._graph._nodes:
|
|
190
|
+
self._graph._edge_index.remove_node(track_id)
|
|
191
|
+
del self._graph._nodes[track_id]
|
|
192
|
+
return True
|
|
193
|
+
|
|
194
|
+
# Check for directory-based track: {track_id}/
|
|
195
|
+
track_dir = collection_path / track_id
|
|
196
|
+
if track_dir.exists() and track_dir.is_dir():
|
|
197
|
+
shutil.rmtree(track_dir)
|
|
198
|
+
# Also remove from graph cache if loaded
|
|
199
|
+
if self._graph is not None and track_id in self._graph._nodes:
|
|
200
|
+
self._graph._edge_index.remove_node(track_id)
|
|
201
|
+
del self._graph._nodes[track_id]
|
|
202
|
+
return True
|
|
203
|
+
|
|
204
|
+
return False
|
|
205
|
+
|
|
206
|
+
def batch_delete(self, track_ids: list[str]) -> int:
|
|
207
|
+
"""
|
|
208
|
+
Delete multiple tracks in batch.
|
|
209
|
+
|
|
210
|
+
Args:
|
|
211
|
+
track_ids: List of track IDs to delete
|
|
212
|
+
|
|
213
|
+
Returns:
|
|
214
|
+
Number of tracks successfully deleted
|
|
215
|
+
|
|
216
|
+
Example:
|
|
217
|
+
count = sdk.tracks.batch_delete(["track-001", "track-002"])
|
|
218
|
+
print(f"Deleted {count} tracks")
|
|
219
|
+
"""
|
|
220
|
+
count = 0
|
|
221
|
+
for track_id in track_ids:
|
|
222
|
+
if self.delete(track_id):
|
|
223
|
+
count += 1
|
|
224
|
+
return count
|