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.
Files changed (331) hide show
  1. htmlgraph/.htmlgraph/.session-warning-state.json +6 -0
  2. htmlgraph/.htmlgraph/agents.json +72 -0
  3. htmlgraph/.htmlgraph/htmlgraph.db +0 -0
  4. htmlgraph/__init__.py +173 -17
  5. htmlgraph/__init__.pyi +123 -0
  6. htmlgraph/agent_detection.py +127 -0
  7. htmlgraph/agent_registry.py +45 -30
  8. htmlgraph/agents.py +160 -107
  9. htmlgraph/analytics/__init__.py +9 -2
  10. htmlgraph/analytics/cli.py +190 -51
  11. htmlgraph/analytics/cost_analyzer.py +391 -0
  12. htmlgraph/analytics/cost_monitor.py +664 -0
  13. htmlgraph/analytics/cost_reporter.py +675 -0
  14. htmlgraph/analytics/cross_session.py +617 -0
  15. htmlgraph/analytics/dependency.py +192 -100
  16. htmlgraph/analytics/pattern_learning.py +771 -0
  17. htmlgraph/analytics/session_graph.py +707 -0
  18. htmlgraph/analytics/strategic/__init__.py +80 -0
  19. htmlgraph/analytics/strategic/cost_optimizer.py +611 -0
  20. htmlgraph/analytics/strategic/pattern_detector.py +876 -0
  21. htmlgraph/analytics/strategic/preference_manager.py +709 -0
  22. htmlgraph/analytics/strategic/suggestion_engine.py +747 -0
  23. htmlgraph/analytics/work_type.py +190 -14
  24. htmlgraph/analytics_index.py +135 -51
  25. htmlgraph/api/__init__.py +3 -0
  26. htmlgraph/api/cost_alerts_websocket.py +416 -0
  27. htmlgraph/api/main.py +2498 -0
  28. htmlgraph/api/static/htmx.min.js +1 -0
  29. htmlgraph/api/static/style-redesign.css +1344 -0
  30. htmlgraph/api/static/style.css +1079 -0
  31. htmlgraph/api/templates/dashboard-redesign.html +1366 -0
  32. htmlgraph/api/templates/dashboard.html +794 -0
  33. htmlgraph/api/templates/partials/activity-feed-hierarchical.html +326 -0
  34. htmlgraph/api/templates/partials/activity-feed.html +1100 -0
  35. htmlgraph/api/templates/partials/agents-redesign.html +317 -0
  36. htmlgraph/api/templates/partials/agents.html +317 -0
  37. htmlgraph/api/templates/partials/event-traces.html +373 -0
  38. htmlgraph/api/templates/partials/features-kanban-redesign.html +509 -0
  39. htmlgraph/api/templates/partials/features.html +578 -0
  40. htmlgraph/api/templates/partials/metrics-redesign.html +346 -0
  41. htmlgraph/api/templates/partials/metrics.html +346 -0
  42. htmlgraph/api/templates/partials/orchestration-redesign.html +443 -0
  43. htmlgraph/api/templates/partials/orchestration.html +198 -0
  44. htmlgraph/api/templates/partials/spawners.html +375 -0
  45. htmlgraph/api/templates/partials/work-items.html +613 -0
  46. htmlgraph/api/websocket.py +538 -0
  47. htmlgraph/archive/__init__.py +24 -0
  48. htmlgraph/archive/bloom.py +234 -0
  49. htmlgraph/archive/fts.py +297 -0
  50. htmlgraph/archive/manager.py +583 -0
  51. htmlgraph/archive/search.py +244 -0
  52. htmlgraph/atomic_ops.py +560 -0
  53. htmlgraph/attribute_index.py +208 -0
  54. htmlgraph/bounded_paths.py +539 -0
  55. htmlgraph/builders/__init__.py +14 -0
  56. htmlgraph/builders/base.py +118 -29
  57. htmlgraph/builders/bug.py +150 -0
  58. htmlgraph/builders/chore.py +119 -0
  59. htmlgraph/builders/epic.py +150 -0
  60. htmlgraph/builders/feature.py +31 -6
  61. htmlgraph/builders/insight.py +195 -0
  62. htmlgraph/builders/metric.py +217 -0
  63. htmlgraph/builders/pattern.py +202 -0
  64. htmlgraph/builders/phase.py +162 -0
  65. htmlgraph/builders/spike.py +52 -19
  66. htmlgraph/builders/track.py +148 -72
  67. htmlgraph/cigs/__init__.py +81 -0
  68. htmlgraph/cigs/autonomy.py +385 -0
  69. htmlgraph/cigs/cost.py +475 -0
  70. htmlgraph/cigs/messages_basic.py +472 -0
  71. htmlgraph/cigs/messaging.py +365 -0
  72. htmlgraph/cigs/models.py +771 -0
  73. htmlgraph/cigs/pattern_storage.py +427 -0
  74. htmlgraph/cigs/patterns.py +503 -0
  75. htmlgraph/cigs/posttool_analyzer.py +234 -0
  76. htmlgraph/cigs/reporter.py +818 -0
  77. htmlgraph/cigs/tracker.py +317 -0
  78. htmlgraph/cli/.htmlgraph/.session-warning-state.json +6 -0
  79. htmlgraph/cli/.htmlgraph/agents.json +72 -0
  80. htmlgraph/cli/.htmlgraph/htmlgraph.db +0 -0
  81. htmlgraph/cli/__init__.py +42 -0
  82. htmlgraph/cli/__main__.py +6 -0
  83. htmlgraph/cli/analytics.py +1424 -0
  84. htmlgraph/cli/base.py +685 -0
  85. htmlgraph/cli/constants.py +206 -0
  86. htmlgraph/cli/core.py +954 -0
  87. htmlgraph/cli/main.py +147 -0
  88. htmlgraph/cli/models.py +475 -0
  89. htmlgraph/cli/templates/__init__.py +1 -0
  90. htmlgraph/cli/templates/cost_dashboard.py +399 -0
  91. htmlgraph/cli/work/__init__.py +239 -0
  92. htmlgraph/cli/work/browse.py +115 -0
  93. htmlgraph/cli/work/features.py +568 -0
  94. htmlgraph/cli/work/orchestration.py +676 -0
  95. htmlgraph/cli/work/report.py +728 -0
  96. htmlgraph/cli/work/sessions.py +466 -0
  97. htmlgraph/cli/work/snapshot.py +559 -0
  98. htmlgraph/cli/work/tracks.py +486 -0
  99. htmlgraph/cli_commands/__init__.py +1 -0
  100. htmlgraph/cli_commands/feature.py +195 -0
  101. htmlgraph/cli_framework.py +115 -0
  102. htmlgraph/collections/__init__.py +18 -0
  103. htmlgraph/collections/base.py +415 -98
  104. htmlgraph/collections/bug.py +53 -0
  105. htmlgraph/collections/chore.py +53 -0
  106. htmlgraph/collections/epic.py +53 -0
  107. htmlgraph/collections/feature.py +12 -26
  108. htmlgraph/collections/insight.py +100 -0
  109. htmlgraph/collections/metric.py +92 -0
  110. htmlgraph/collections/pattern.py +97 -0
  111. htmlgraph/collections/phase.py +53 -0
  112. htmlgraph/collections/session.py +194 -0
  113. htmlgraph/collections/spike.py +56 -16
  114. htmlgraph/collections/task_delegation.py +241 -0
  115. htmlgraph/collections/todo.py +511 -0
  116. htmlgraph/collections/traces.py +487 -0
  117. htmlgraph/config/cost_models.json +56 -0
  118. htmlgraph/config.py +190 -0
  119. htmlgraph/context_analytics.py +344 -0
  120. htmlgraph/converter.py +216 -28
  121. htmlgraph/cost_analysis/__init__.py +5 -0
  122. htmlgraph/cost_analysis/analyzer.py +438 -0
  123. htmlgraph/dashboard.html +2406 -307
  124. htmlgraph/dashboard.html.backup +6592 -0
  125. htmlgraph/dashboard.html.bak +7181 -0
  126. htmlgraph/dashboard.html.bak2 +7231 -0
  127. htmlgraph/dashboard.html.bak3 +7232 -0
  128. htmlgraph/db/__init__.py +38 -0
  129. htmlgraph/db/queries.py +790 -0
  130. htmlgraph/db/schema.py +1788 -0
  131. htmlgraph/decorators.py +317 -0
  132. htmlgraph/dependency_models.py +19 -2
  133. htmlgraph/deploy.py +142 -125
  134. htmlgraph/deployment_models.py +474 -0
  135. htmlgraph/docs/API_REFERENCE.md +841 -0
  136. htmlgraph/docs/HTTP_API.md +750 -0
  137. htmlgraph/docs/INTEGRATION_GUIDE.md +752 -0
  138. htmlgraph/docs/ORCHESTRATION_PATTERNS.md +717 -0
  139. htmlgraph/docs/README.md +532 -0
  140. htmlgraph/docs/__init__.py +77 -0
  141. htmlgraph/docs/docs_version.py +55 -0
  142. htmlgraph/docs/metadata.py +93 -0
  143. htmlgraph/docs/migrations.py +232 -0
  144. htmlgraph/docs/template_engine.py +143 -0
  145. htmlgraph/docs/templates/_sections/cli_reference.md.j2 +52 -0
  146. htmlgraph/docs/templates/_sections/core_concepts.md.j2 +29 -0
  147. htmlgraph/docs/templates/_sections/sdk_basics.md.j2 +69 -0
  148. htmlgraph/docs/templates/base_agents.md.j2 +78 -0
  149. htmlgraph/docs/templates/example_user_override.md.j2 +47 -0
  150. htmlgraph/docs/version_check.py +163 -0
  151. htmlgraph/edge_index.py +182 -27
  152. htmlgraph/error_handler.py +544 -0
  153. htmlgraph/event_log.py +100 -52
  154. htmlgraph/event_migration.py +13 -4
  155. htmlgraph/exceptions.py +49 -0
  156. htmlgraph/file_watcher.py +101 -28
  157. htmlgraph/find_api.py +75 -63
  158. htmlgraph/git_events.py +145 -63
  159. htmlgraph/graph.py +1122 -106
  160. htmlgraph/hooks/.htmlgraph/.session-warning-state.json +6 -0
  161. htmlgraph/hooks/.htmlgraph/agents.json +72 -0
  162. htmlgraph/hooks/.htmlgraph/index.sqlite +0 -0
  163. htmlgraph/hooks/__init__.py +45 -0
  164. htmlgraph/hooks/bootstrap.py +169 -0
  165. htmlgraph/hooks/cigs_pretool_enforcer.py +354 -0
  166. htmlgraph/hooks/concurrent_sessions.py +208 -0
  167. htmlgraph/hooks/context.py +350 -0
  168. htmlgraph/hooks/drift_handler.py +525 -0
  169. htmlgraph/hooks/event_tracker.py +1314 -0
  170. htmlgraph/hooks/git_commands.py +175 -0
  171. htmlgraph/hooks/hooks-config.example.json +12 -0
  172. htmlgraph/hooks/installer.py +343 -0
  173. htmlgraph/hooks/orchestrator.py +674 -0
  174. htmlgraph/hooks/orchestrator_reflector.py +223 -0
  175. htmlgraph/hooks/post-checkout.sh +28 -0
  176. htmlgraph/hooks/post-commit.sh +24 -0
  177. htmlgraph/hooks/post-merge.sh +26 -0
  178. htmlgraph/hooks/post_tool_use_failure.py +273 -0
  179. htmlgraph/hooks/post_tool_use_handler.py +257 -0
  180. htmlgraph/hooks/posttooluse.py +408 -0
  181. htmlgraph/hooks/pre-commit.sh +94 -0
  182. htmlgraph/hooks/pre-push.sh +28 -0
  183. htmlgraph/hooks/pretooluse.py +819 -0
  184. htmlgraph/hooks/prompt_analyzer.py +637 -0
  185. htmlgraph/hooks/session_handler.py +668 -0
  186. htmlgraph/hooks/session_summary.py +395 -0
  187. htmlgraph/hooks/state_manager.py +504 -0
  188. htmlgraph/hooks/subagent_detection.py +202 -0
  189. htmlgraph/hooks/subagent_stop.py +369 -0
  190. htmlgraph/hooks/task_enforcer.py +255 -0
  191. htmlgraph/hooks/task_validator.py +177 -0
  192. htmlgraph/hooks/validator.py +628 -0
  193. htmlgraph/ids.py +41 -27
  194. htmlgraph/index.d.ts +286 -0
  195. htmlgraph/learning.py +767 -0
  196. htmlgraph/mcp_server.py +69 -23
  197. htmlgraph/models.py +1586 -87
  198. htmlgraph/operations/README.md +62 -0
  199. htmlgraph/operations/__init__.py +79 -0
  200. htmlgraph/operations/analytics.py +339 -0
  201. htmlgraph/operations/bootstrap.py +289 -0
  202. htmlgraph/operations/events.py +244 -0
  203. htmlgraph/operations/fastapi_server.py +231 -0
  204. htmlgraph/operations/hooks.py +350 -0
  205. htmlgraph/operations/initialization.py +597 -0
  206. htmlgraph/operations/initialization.py.backup +228 -0
  207. htmlgraph/operations/server.py +303 -0
  208. htmlgraph/orchestration/__init__.py +58 -0
  209. htmlgraph/orchestration/claude_launcher.py +179 -0
  210. htmlgraph/orchestration/command_builder.py +72 -0
  211. htmlgraph/orchestration/headless_spawner.py +281 -0
  212. htmlgraph/orchestration/live_events.py +377 -0
  213. htmlgraph/orchestration/model_selection.py +327 -0
  214. htmlgraph/orchestration/plugin_manager.py +140 -0
  215. htmlgraph/orchestration/prompts.py +137 -0
  216. htmlgraph/orchestration/spawner_event_tracker.py +383 -0
  217. htmlgraph/orchestration/spawners/__init__.py +16 -0
  218. htmlgraph/orchestration/spawners/base.py +194 -0
  219. htmlgraph/orchestration/spawners/claude.py +173 -0
  220. htmlgraph/orchestration/spawners/codex.py +435 -0
  221. htmlgraph/orchestration/spawners/copilot.py +294 -0
  222. htmlgraph/orchestration/spawners/gemini.py +471 -0
  223. htmlgraph/orchestration/subprocess_runner.py +36 -0
  224. htmlgraph/orchestration/task_coordination.py +343 -0
  225. htmlgraph/orchestration.md +563 -0
  226. htmlgraph/orchestrator-system-prompt-optimized.txt +863 -0
  227. htmlgraph/orchestrator.py +669 -0
  228. htmlgraph/orchestrator_config.py +357 -0
  229. htmlgraph/orchestrator_mode.py +328 -0
  230. htmlgraph/orchestrator_validator.py +133 -0
  231. htmlgraph/parallel.py +646 -0
  232. htmlgraph/parser.py +160 -35
  233. htmlgraph/path_query.py +608 -0
  234. htmlgraph/pattern_matcher.py +636 -0
  235. htmlgraph/planning.py +147 -52
  236. htmlgraph/pydantic_models.py +476 -0
  237. htmlgraph/quality_gates.py +350 -0
  238. htmlgraph/query_builder.py +109 -72
  239. htmlgraph/query_composer.py +509 -0
  240. htmlgraph/reflection.py +443 -0
  241. htmlgraph/refs.py +344 -0
  242. htmlgraph/repo_hash.py +512 -0
  243. htmlgraph/repositories/__init__.py +292 -0
  244. htmlgraph/repositories/analytics_repository.py +455 -0
  245. htmlgraph/repositories/analytics_repository_standard.py +628 -0
  246. htmlgraph/repositories/feature_repository.py +581 -0
  247. htmlgraph/repositories/feature_repository_htmlfile.py +668 -0
  248. htmlgraph/repositories/feature_repository_memory.py +607 -0
  249. htmlgraph/repositories/feature_repository_sqlite.py +858 -0
  250. htmlgraph/repositories/filter_service.py +620 -0
  251. htmlgraph/repositories/filter_service_standard.py +445 -0
  252. htmlgraph/repositories/shared_cache.py +621 -0
  253. htmlgraph/repositories/shared_cache_memory.py +395 -0
  254. htmlgraph/repositories/track_repository.py +552 -0
  255. htmlgraph/repositories/track_repository_htmlfile.py +619 -0
  256. htmlgraph/repositories/track_repository_memory.py +508 -0
  257. htmlgraph/repositories/track_repository_sqlite.py +711 -0
  258. htmlgraph/routing.py +8 -19
  259. htmlgraph/scripts/deploy.py +1 -2
  260. htmlgraph/sdk/__init__.py +398 -0
  261. htmlgraph/sdk/__init__.pyi +14 -0
  262. htmlgraph/sdk/analytics/__init__.py +19 -0
  263. htmlgraph/sdk/analytics/engine.py +155 -0
  264. htmlgraph/sdk/analytics/helpers.py +178 -0
  265. htmlgraph/sdk/analytics/registry.py +109 -0
  266. htmlgraph/sdk/base.py +484 -0
  267. htmlgraph/sdk/constants.py +216 -0
  268. htmlgraph/sdk/core.pyi +308 -0
  269. htmlgraph/sdk/discovery.py +120 -0
  270. htmlgraph/sdk/help/__init__.py +12 -0
  271. htmlgraph/sdk/help/mixin.py +699 -0
  272. htmlgraph/sdk/mixins/__init__.py +15 -0
  273. htmlgraph/sdk/mixins/attribution.py +113 -0
  274. htmlgraph/sdk/mixins/mixin.py +410 -0
  275. htmlgraph/sdk/operations/__init__.py +12 -0
  276. htmlgraph/sdk/operations/mixin.py +427 -0
  277. htmlgraph/sdk/orchestration/__init__.py +17 -0
  278. htmlgraph/sdk/orchestration/coordinator.py +203 -0
  279. htmlgraph/sdk/orchestration/spawner.py +204 -0
  280. htmlgraph/sdk/planning/__init__.py +19 -0
  281. htmlgraph/sdk/planning/bottlenecks.py +93 -0
  282. htmlgraph/sdk/planning/mixin.py +211 -0
  283. htmlgraph/sdk/planning/parallel.py +186 -0
  284. htmlgraph/sdk/planning/queue.py +210 -0
  285. htmlgraph/sdk/planning/recommendations.py +87 -0
  286. htmlgraph/sdk/planning/smart_planning.py +319 -0
  287. htmlgraph/sdk/session/__init__.py +19 -0
  288. htmlgraph/sdk/session/continuity.py +57 -0
  289. htmlgraph/sdk/session/handoff.py +110 -0
  290. htmlgraph/sdk/session/info.py +309 -0
  291. htmlgraph/sdk/session/manager.py +103 -0
  292. htmlgraph/sdk/strategic/__init__.py +26 -0
  293. htmlgraph/sdk/strategic/mixin.py +563 -0
  294. htmlgraph/server.py +685 -180
  295. htmlgraph/services/__init__.py +10 -0
  296. htmlgraph/services/claiming.py +199 -0
  297. htmlgraph/session_hooks.py +300 -0
  298. htmlgraph/session_manager.py +1392 -175
  299. htmlgraph/session_registry.py +587 -0
  300. htmlgraph/session_state.py +436 -0
  301. htmlgraph/session_warning.py +201 -0
  302. htmlgraph/sessions/__init__.py +23 -0
  303. htmlgraph/sessions/handoff.py +756 -0
  304. htmlgraph/setup.py +34 -17
  305. htmlgraph/spike_index.py +143 -0
  306. htmlgraph/sync_docs.py +12 -15
  307. htmlgraph/system_prompts.py +450 -0
  308. htmlgraph/templates/AGENTS.md.template +366 -0
  309. htmlgraph/templates/CLAUDE.md.template +97 -0
  310. htmlgraph/templates/GEMINI.md.template +87 -0
  311. htmlgraph/templates/orchestration-view.html +350 -0
  312. htmlgraph/track_builder.py +146 -15
  313. htmlgraph/track_manager.py +69 -21
  314. htmlgraph/transcript.py +890 -0
  315. htmlgraph/transcript_analytics.py +699 -0
  316. htmlgraph/types.py +323 -0
  317. htmlgraph/validation.py +115 -0
  318. htmlgraph/watch.py +8 -5
  319. htmlgraph/work_type_utils.py +3 -2
  320. {htmlgraph-0.9.3.data → htmlgraph-0.27.5.data}/data/htmlgraph/dashboard.html +2406 -307
  321. htmlgraph-0.27.5.data/data/htmlgraph/templates/AGENTS.md.template +366 -0
  322. htmlgraph-0.27.5.data/data/htmlgraph/templates/CLAUDE.md.template +97 -0
  323. htmlgraph-0.27.5.data/data/htmlgraph/templates/GEMINI.md.template +87 -0
  324. {htmlgraph-0.9.3.dist-info → htmlgraph-0.27.5.dist-info}/METADATA +97 -64
  325. htmlgraph-0.27.5.dist-info/RECORD +337 -0
  326. {htmlgraph-0.9.3.dist-info → htmlgraph-0.27.5.dist-info}/entry_points.txt +1 -1
  327. htmlgraph/cli.py +0 -2688
  328. htmlgraph/sdk.py +0 -709
  329. htmlgraph-0.9.3.dist-info/RECORD +0 -61
  330. {htmlgraph-0.9.3.data → htmlgraph-0.27.5.data}/data/htmlgraph/styles.css +0 -0
  331. {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>
@@ -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
- from __future__ import annotations
8
- from typing import TYPE_CHECKING
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: '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
- def _ensure_graph(self):
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
- def matches(node):
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, 'status', None) != status:
84
+ if status and getattr(node, "status", None) != status:
65
85
  return False
66
- if priority and getattr(node, 'priority', None) != priority:
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