htmlgraph 0.24.1__py3-none-any.whl → 0.25.0__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.
Files changed (103) hide show
  1. htmlgraph/__init__.py +20 -1
  2. htmlgraph/agent_detection.py +26 -10
  3. htmlgraph/analytics/cross_session.py +4 -3
  4. htmlgraph/analytics/work_type.py +52 -16
  5. htmlgraph/analytics_index.py +51 -19
  6. htmlgraph/api/__init__.py +3 -0
  7. htmlgraph/api/main.py +2115 -0
  8. htmlgraph/api/static/htmx.min.js +1 -0
  9. htmlgraph/api/static/style-redesign.css +1344 -0
  10. htmlgraph/api/static/style.css +1079 -0
  11. htmlgraph/api/templates/dashboard-redesign.html +812 -0
  12. htmlgraph/api/templates/dashboard.html +783 -0
  13. htmlgraph/api/templates/partials/activity-feed-hierarchical.html +326 -0
  14. htmlgraph/api/templates/partials/activity-feed.html +570 -0
  15. htmlgraph/api/templates/partials/agents-redesign.html +317 -0
  16. htmlgraph/api/templates/partials/agents.html +317 -0
  17. htmlgraph/api/templates/partials/event-traces.html +373 -0
  18. htmlgraph/api/templates/partials/features-kanban-redesign.html +509 -0
  19. htmlgraph/api/templates/partials/features.html +509 -0
  20. htmlgraph/api/templates/partials/metrics-redesign.html +346 -0
  21. htmlgraph/api/templates/partials/metrics.html +346 -0
  22. htmlgraph/api/templates/partials/orchestration-redesign.html +443 -0
  23. htmlgraph/api/templates/partials/orchestration.html +163 -0
  24. htmlgraph/api/templates/partials/spawners.html +375 -0
  25. htmlgraph/atomic_ops.py +560 -0
  26. htmlgraph/builders/base.py +55 -1
  27. htmlgraph/builders/bug.py +17 -2
  28. htmlgraph/builders/chore.py +17 -2
  29. htmlgraph/builders/epic.py +17 -2
  30. htmlgraph/builders/feature.py +25 -2
  31. htmlgraph/builders/phase.py +17 -2
  32. htmlgraph/builders/spike.py +27 -2
  33. htmlgraph/builders/track.py +14 -0
  34. htmlgraph/cigs/__init__.py +4 -0
  35. htmlgraph/cigs/reporter.py +818 -0
  36. htmlgraph/cli.py +1427 -401
  37. htmlgraph/cli_commands/__init__.py +1 -0
  38. htmlgraph/cli_commands/feature.py +195 -0
  39. htmlgraph/cli_framework.py +115 -0
  40. htmlgraph/collections/__init__.py +2 -0
  41. htmlgraph/collections/base.py +21 -0
  42. htmlgraph/collections/session.py +189 -0
  43. htmlgraph/collections/spike.py +7 -1
  44. htmlgraph/collections/task_delegation.py +236 -0
  45. htmlgraph/collections/traces.py +482 -0
  46. htmlgraph/config.py +113 -0
  47. htmlgraph/converter.py +41 -0
  48. htmlgraph/cost_analysis/__init__.py +5 -0
  49. htmlgraph/cost_analysis/analyzer.py +438 -0
  50. htmlgraph/dashboard.html +3315 -492
  51. htmlgraph-0.24.1.data/data/htmlgraph/dashboard.html → htmlgraph/dashboard.html.backup +2246 -248
  52. htmlgraph/dashboard.html.bak +7181 -0
  53. htmlgraph/dashboard.html.bak2 +7231 -0
  54. htmlgraph/dashboard.html.bak3 +7232 -0
  55. htmlgraph/db/__init__.py +38 -0
  56. htmlgraph/db/queries.py +790 -0
  57. htmlgraph/db/schema.py +1334 -0
  58. htmlgraph/deploy.py +26 -27
  59. htmlgraph/docs/API_REFERENCE.md +841 -0
  60. htmlgraph/docs/HTTP_API.md +750 -0
  61. htmlgraph/docs/INTEGRATION_GUIDE.md +752 -0
  62. htmlgraph/docs/ORCHESTRATION_PATTERNS.md +710 -0
  63. htmlgraph/docs/README.md +533 -0
  64. htmlgraph/docs/version_check.py +3 -1
  65. htmlgraph/error_handler.py +544 -0
  66. htmlgraph/event_log.py +2 -0
  67. htmlgraph/hooks/__init__.py +8 -0
  68. htmlgraph/hooks/bootstrap.py +169 -0
  69. htmlgraph/hooks/context.py +271 -0
  70. htmlgraph/hooks/drift_handler.py +521 -0
  71. htmlgraph/hooks/event_tracker.py +405 -15
  72. htmlgraph/hooks/post_tool_use_handler.py +257 -0
  73. htmlgraph/hooks/pretooluse.py +476 -6
  74. htmlgraph/hooks/prompt_analyzer.py +648 -0
  75. htmlgraph/hooks/session_handler.py +583 -0
  76. htmlgraph/hooks/state_manager.py +501 -0
  77. htmlgraph/hooks/subagent_stop.py +309 -0
  78. htmlgraph/hooks/task_enforcer.py +39 -0
  79. htmlgraph/models.py +111 -15
  80. htmlgraph/operations/fastapi_server.py +230 -0
  81. htmlgraph/orchestration/headless_spawner.py +22 -14
  82. htmlgraph/pydantic_models.py +476 -0
  83. htmlgraph/quality_gates.py +350 -0
  84. htmlgraph/repo_hash.py +511 -0
  85. htmlgraph/sdk.py +348 -10
  86. htmlgraph/server.py +194 -0
  87. htmlgraph/session_hooks.py +300 -0
  88. htmlgraph/session_manager.py +131 -1
  89. htmlgraph/session_registry.py +587 -0
  90. htmlgraph/session_state.py +436 -0
  91. htmlgraph/system_prompts.py +449 -0
  92. htmlgraph/templates/orchestration-view.html +350 -0
  93. htmlgraph/track_builder.py +19 -0
  94. htmlgraph/validation.py +115 -0
  95. htmlgraph-0.25.0.data/data/htmlgraph/dashboard.html +7417 -0
  96. {htmlgraph-0.24.1.dist-info → htmlgraph-0.25.0.dist-info}/METADATA +91 -64
  97. {htmlgraph-0.24.1.dist-info → htmlgraph-0.25.0.dist-info}/RECORD +103 -42
  98. {htmlgraph-0.24.1.data → htmlgraph-0.25.0.data}/data/htmlgraph/styles.css +0 -0
  99. {htmlgraph-0.24.1.data → htmlgraph-0.25.0.data}/data/htmlgraph/templates/AGENTS.md.template +0 -0
  100. {htmlgraph-0.24.1.data → htmlgraph-0.25.0.data}/data/htmlgraph/templates/CLAUDE.md.template +0 -0
  101. {htmlgraph-0.24.1.data → htmlgraph-0.25.0.data}/data/htmlgraph/templates/GEMINI.md.template +0 -0
  102. {htmlgraph-0.24.1.dist-info → htmlgraph-0.25.0.dist-info}/WHEEL +0 -0
  103. {htmlgraph-0.24.1.dist-info → htmlgraph-0.25.0.dist-info}/entry_points.txt +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>
@@ -113,6 +113,25 @@ class TrackCollection:
113
113
  # Auto-save on exit
114
114
  graph.update(node)
115
115
 
116
+ def create(self, title: str) -> TrackBuilder:
117
+ """
118
+ Create a new track with fluent interface.
119
+
120
+ Args:
121
+ title: Track title
122
+
123
+ Returns:
124
+ TrackBuilder for method chaining
125
+
126
+ Example:
127
+ track = sdk.tracks.create("Multi-Agent Collaboration") \\
128
+ .set_priority("high") \\
129
+ .save()
130
+ """
131
+ builder = TrackBuilder(self._sdk)
132
+ builder._title = title
133
+ return builder
134
+
116
135
  def builder(self) -> TrackBuilder:
117
136
  """
118
137
  Create a new track builder with fluent interface.
@@ -0,0 +1,115 @@
1
+ """
2
+ Rich CLI validation error formatting and utilities.
3
+
4
+ Provides beautiful error display for Pydantic validation failures.
5
+ """
6
+
7
+ from collections.abc import Callable
8
+ from typing import TypeVar
9
+
10
+ from pydantic import ValidationError
11
+ from rich.console import Console
12
+
13
+ console = Console()
14
+
15
+ T = TypeVar("T")
16
+
17
+
18
+ def display_validation_error(error: ValidationError) -> None:
19
+ """
20
+ Display a Pydantic validation error in Rich format.
21
+
22
+ Args:
23
+ error: ValidationError from Pydantic model validation
24
+
25
+ Example:
26
+ try:
27
+ input_data = FeatureCreateInput(title="", priority="invalid")
28
+ except ValidationError as e:
29
+ display_validation_error(e)
30
+ """
31
+ console.print("[red]✗ Validation Error[/red]")
32
+ console.print()
33
+
34
+ for err in error.errors():
35
+ field = ".".join(str(loc) for loc in err["loc"])
36
+ msg = err["msg"]
37
+ error_type = err["type"]
38
+
39
+ # Color code by error type for better UX
40
+ if "at least" in msg.lower() or "at most" in msg.lower():
41
+ # Length/range constraint violation
42
+ console.print(f" [yellow]{field}:[/yellow] {msg}")
43
+ elif "must be" in msg.lower() or "is not valid" in msg.lower():
44
+ # Type/value constraint violation
45
+ console.print(f" [cyan]{field}:[/cyan] {msg}")
46
+ elif error_type == "string_pattern":
47
+ # Pattern validation failed
48
+ console.print(f" [magenta]{field}:[/magenta] {msg}")
49
+ else:
50
+ # Generic validation error
51
+ console.print(f" [red]{field}:[/red] {msg}")
52
+
53
+ console.print()
54
+
55
+
56
+ def validate_input(
57
+ validator_class: type[T],
58
+ **kwargs: object,
59
+ ) -> T | None:
60
+ """
61
+ Validate input and display rich error messages on failure.
62
+
63
+ Args:
64
+ validator_class: Pydantic model class to validate against
65
+ **kwargs: Input data to validate
66
+
67
+ Returns:
68
+ Validated model instance, or None if validation failed
69
+
70
+ Example:
71
+ input_data = validate_input(FeatureCreateInput, title="My Feature", priority="high")
72
+ if input_data is None:
73
+ sys.exit(1)
74
+ # Use input_data.title, input_data.priority, etc.
75
+ """
76
+ try:
77
+ return validator_class(**kwargs)
78
+ except ValidationError as e:
79
+ display_validation_error(e)
80
+ return None
81
+
82
+
83
+ def wrap_command_validation(func: Callable[..., None]) -> Callable[..., None]:
84
+ """
85
+ Decorator to wrap CLI command functions with validation error handling.
86
+
87
+ This decorator catches ValidationError and displays it in Rich format,
88
+ then exits gracefully.
89
+
90
+ Args:
91
+ func: CLI command function
92
+
93
+ Returns:
94
+ Wrapped function with validation error handling
95
+
96
+ Example:
97
+ @wrap_command_validation
98
+ def cmd_feature_create(args: argparse.Namespace) -> None:
99
+ input_data = FeatureCreateInput(
100
+ title=args.title,
101
+ priority=args.priority
102
+ )
103
+ # Rest of command logic
104
+ """
105
+
106
+ def wrapper(*args: object, **kwargs: object) -> None:
107
+ import sys
108
+
109
+ try:
110
+ return func(*args, **kwargs)
111
+ except ValidationError as e:
112
+ display_validation_error(e)
113
+ sys.exit(1)
114
+
115
+ return wrapper