htmlgraph 0.20.1__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 (304) 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 +51 -1
  5. htmlgraph/__init__.pyi +123 -0
  6. htmlgraph/agent_detection.py +26 -10
  7. htmlgraph/agent_registry.py +2 -1
  8. htmlgraph/analytics/__init__.py +8 -1
  9. htmlgraph/analytics/cli.py +86 -20
  10. htmlgraph/analytics/cost_analyzer.py +391 -0
  11. htmlgraph/analytics/cost_monitor.py +664 -0
  12. htmlgraph/analytics/cost_reporter.py +675 -0
  13. htmlgraph/analytics/cross_session.py +617 -0
  14. htmlgraph/analytics/dependency.py +10 -6
  15. htmlgraph/analytics/pattern_learning.py +771 -0
  16. htmlgraph/analytics/session_graph.py +707 -0
  17. htmlgraph/analytics/strategic/__init__.py +80 -0
  18. htmlgraph/analytics/strategic/cost_optimizer.py +611 -0
  19. htmlgraph/analytics/strategic/pattern_detector.py +876 -0
  20. htmlgraph/analytics/strategic/preference_manager.py +709 -0
  21. htmlgraph/analytics/strategic/suggestion_engine.py +747 -0
  22. htmlgraph/analytics/work_type.py +67 -27
  23. htmlgraph/analytics_index.py +53 -20
  24. htmlgraph/api/__init__.py +3 -0
  25. htmlgraph/api/cost_alerts_websocket.py +416 -0
  26. htmlgraph/api/main.py +2498 -0
  27. htmlgraph/api/static/htmx.min.js +1 -0
  28. htmlgraph/api/static/style-redesign.css +1344 -0
  29. htmlgraph/api/static/style.css +1079 -0
  30. htmlgraph/api/templates/dashboard-redesign.html +1366 -0
  31. htmlgraph/api/templates/dashboard.html +794 -0
  32. htmlgraph/api/templates/partials/activity-feed-hierarchical.html +326 -0
  33. htmlgraph/api/templates/partials/activity-feed.html +1100 -0
  34. htmlgraph/api/templates/partials/agents-redesign.html +317 -0
  35. htmlgraph/api/templates/partials/agents.html +317 -0
  36. htmlgraph/api/templates/partials/event-traces.html +373 -0
  37. htmlgraph/api/templates/partials/features-kanban-redesign.html +509 -0
  38. htmlgraph/api/templates/partials/features.html +578 -0
  39. htmlgraph/api/templates/partials/metrics-redesign.html +346 -0
  40. htmlgraph/api/templates/partials/metrics.html +346 -0
  41. htmlgraph/api/templates/partials/orchestration-redesign.html +443 -0
  42. htmlgraph/api/templates/partials/orchestration.html +198 -0
  43. htmlgraph/api/templates/partials/spawners.html +375 -0
  44. htmlgraph/api/templates/partials/work-items.html +613 -0
  45. htmlgraph/api/websocket.py +538 -0
  46. htmlgraph/archive/__init__.py +24 -0
  47. htmlgraph/archive/bloom.py +234 -0
  48. htmlgraph/archive/fts.py +297 -0
  49. htmlgraph/archive/manager.py +583 -0
  50. htmlgraph/archive/search.py +244 -0
  51. htmlgraph/atomic_ops.py +560 -0
  52. htmlgraph/attribute_index.py +2 -1
  53. htmlgraph/bounded_paths.py +539 -0
  54. htmlgraph/builders/base.py +57 -2
  55. htmlgraph/builders/bug.py +19 -3
  56. htmlgraph/builders/chore.py +19 -3
  57. htmlgraph/builders/epic.py +19 -3
  58. htmlgraph/builders/feature.py +27 -3
  59. htmlgraph/builders/insight.py +2 -1
  60. htmlgraph/builders/metric.py +2 -1
  61. htmlgraph/builders/pattern.py +2 -1
  62. htmlgraph/builders/phase.py +19 -3
  63. htmlgraph/builders/spike.py +29 -3
  64. htmlgraph/builders/track.py +42 -1
  65. htmlgraph/cigs/__init__.py +81 -0
  66. htmlgraph/cigs/autonomy.py +385 -0
  67. htmlgraph/cigs/cost.py +475 -0
  68. htmlgraph/cigs/messages_basic.py +472 -0
  69. htmlgraph/cigs/messaging.py +365 -0
  70. htmlgraph/cigs/models.py +771 -0
  71. htmlgraph/cigs/pattern_storage.py +427 -0
  72. htmlgraph/cigs/patterns.py +503 -0
  73. htmlgraph/cigs/posttool_analyzer.py +234 -0
  74. htmlgraph/cigs/reporter.py +818 -0
  75. htmlgraph/cigs/tracker.py +317 -0
  76. htmlgraph/cli/.htmlgraph/.session-warning-state.json +6 -0
  77. htmlgraph/cli/.htmlgraph/agents.json +72 -0
  78. htmlgraph/cli/.htmlgraph/htmlgraph.db +0 -0
  79. htmlgraph/cli/__init__.py +42 -0
  80. htmlgraph/cli/__main__.py +6 -0
  81. htmlgraph/cli/analytics.py +1424 -0
  82. htmlgraph/cli/base.py +685 -0
  83. htmlgraph/cli/constants.py +206 -0
  84. htmlgraph/cli/core.py +954 -0
  85. htmlgraph/cli/main.py +147 -0
  86. htmlgraph/cli/models.py +475 -0
  87. htmlgraph/cli/templates/__init__.py +1 -0
  88. htmlgraph/cli/templates/cost_dashboard.py +399 -0
  89. htmlgraph/cli/work/__init__.py +239 -0
  90. htmlgraph/cli/work/browse.py +115 -0
  91. htmlgraph/cli/work/features.py +568 -0
  92. htmlgraph/cli/work/orchestration.py +676 -0
  93. htmlgraph/cli/work/report.py +728 -0
  94. htmlgraph/cli/work/sessions.py +466 -0
  95. htmlgraph/cli/work/snapshot.py +559 -0
  96. htmlgraph/cli/work/tracks.py +486 -0
  97. htmlgraph/cli_commands/__init__.py +1 -0
  98. htmlgraph/cli_commands/feature.py +195 -0
  99. htmlgraph/cli_framework.py +115 -0
  100. htmlgraph/collections/__init__.py +2 -0
  101. htmlgraph/collections/base.py +197 -14
  102. htmlgraph/collections/bug.py +2 -1
  103. htmlgraph/collections/chore.py +2 -1
  104. htmlgraph/collections/epic.py +2 -1
  105. htmlgraph/collections/feature.py +2 -1
  106. htmlgraph/collections/insight.py +2 -1
  107. htmlgraph/collections/metric.py +2 -1
  108. htmlgraph/collections/pattern.py +2 -1
  109. htmlgraph/collections/phase.py +2 -1
  110. htmlgraph/collections/session.py +194 -0
  111. htmlgraph/collections/spike.py +13 -2
  112. htmlgraph/collections/task_delegation.py +241 -0
  113. htmlgraph/collections/todo.py +14 -1
  114. htmlgraph/collections/traces.py +487 -0
  115. htmlgraph/config/cost_models.json +56 -0
  116. htmlgraph/config.py +190 -0
  117. htmlgraph/context_analytics.py +2 -1
  118. htmlgraph/converter.py +116 -7
  119. htmlgraph/cost_analysis/__init__.py +5 -0
  120. htmlgraph/cost_analysis/analyzer.py +438 -0
  121. htmlgraph/dashboard.html +2246 -248
  122. htmlgraph/dashboard.html.backup +6592 -0
  123. htmlgraph/dashboard.html.bak +7181 -0
  124. htmlgraph/dashboard.html.bak2 +7231 -0
  125. htmlgraph/dashboard.html.bak3 +7232 -0
  126. htmlgraph/db/__init__.py +38 -0
  127. htmlgraph/db/queries.py +790 -0
  128. htmlgraph/db/schema.py +1788 -0
  129. htmlgraph/decorators.py +317 -0
  130. htmlgraph/dependency_models.py +2 -1
  131. htmlgraph/deploy.py +26 -27
  132. htmlgraph/docs/API_REFERENCE.md +841 -0
  133. htmlgraph/docs/HTTP_API.md +750 -0
  134. htmlgraph/docs/INTEGRATION_GUIDE.md +752 -0
  135. htmlgraph/docs/ORCHESTRATION_PATTERNS.md +717 -0
  136. htmlgraph/docs/README.md +532 -0
  137. htmlgraph/docs/__init__.py +77 -0
  138. htmlgraph/docs/docs_version.py +55 -0
  139. htmlgraph/docs/metadata.py +93 -0
  140. htmlgraph/docs/migrations.py +232 -0
  141. htmlgraph/docs/template_engine.py +143 -0
  142. htmlgraph/docs/templates/_sections/cli_reference.md.j2 +52 -0
  143. htmlgraph/docs/templates/_sections/core_concepts.md.j2 +29 -0
  144. htmlgraph/docs/templates/_sections/sdk_basics.md.j2 +69 -0
  145. htmlgraph/docs/templates/base_agents.md.j2 +78 -0
  146. htmlgraph/docs/templates/example_user_override.md.j2 +47 -0
  147. htmlgraph/docs/version_check.py +163 -0
  148. htmlgraph/edge_index.py +2 -1
  149. htmlgraph/error_handler.py +544 -0
  150. htmlgraph/event_log.py +86 -37
  151. htmlgraph/event_migration.py +2 -1
  152. htmlgraph/file_watcher.py +12 -8
  153. htmlgraph/find_api.py +2 -1
  154. htmlgraph/git_events.py +67 -9
  155. htmlgraph/hooks/.htmlgraph/.session-warning-state.json +6 -0
  156. htmlgraph/hooks/.htmlgraph/agents.json +72 -0
  157. htmlgraph/hooks/.htmlgraph/index.sqlite +0 -0
  158. htmlgraph/hooks/__init__.py +8 -0
  159. htmlgraph/hooks/bootstrap.py +169 -0
  160. htmlgraph/hooks/cigs_pretool_enforcer.py +354 -0
  161. htmlgraph/hooks/concurrent_sessions.py +208 -0
  162. htmlgraph/hooks/context.py +350 -0
  163. htmlgraph/hooks/drift_handler.py +525 -0
  164. htmlgraph/hooks/event_tracker.py +790 -99
  165. htmlgraph/hooks/git_commands.py +175 -0
  166. htmlgraph/hooks/installer.py +5 -1
  167. htmlgraph/hooks/orchestrator.py +327 -76
  168. htmlgraph/hooks/orchestrator_reflector.py +31 -4
  169. htmlgraph/hooks/post_tool_use_failure.py +32 -7
  170. htmlgraph/hooks/post_tool_use_handler.py +257 -0
  171. htmlgraph/hooks/posttooluse.py +92 -19
  172. htmlgraph/hooks/pretooluse.py +527 -7
  173. htmlgraph/hooks/prompt_analyzer.py +637 -0
  174. htmlgraph/hooks/session_handler.py +668 -0
  175. htmlgraph/hooks/session_summary.py +395 -0
  176. htmlgraph/hooks/state_manager.py +504 -0
  177. htmlgraph/hooks/subagent_detection.py +202 -0
  178. htmlgraph/hooks/subagent_stop.py +369 -0
  179. htmlgraph/hooks/task_enforcer.py +99 -4
  180. htmlgraph/hooks/validator.py +212 -91
  181. htmlgraph/ids.py +2 -1
  182. htmlgraph/learning.py +125 -100
  183. htmlgraph/mcp_server.py +2 -1
  184. htmlgraph/models.py +217 -18
  185. htmlgraph/operations/README.md +62 -0
  186. htmlgraph/operations/__init__.py +79 -0
  187. htmlgraph/operations/analytics.py +339 -0
  188. htmlgraph/operations/bootstrap.py +289 -0
  189. htmlgraph/operations/events.py +244 -0
  190. htmlgraph/operations/fastapi_server.py +231 -0
  191. htmlgraph/operations/hooks.py +350 -0
  192. htmlgraph/operations/initialization.py +597 -0
  193. htmlgraph/operations/initialization.py.backup +228 -0
  194. htmlgraph/operations/server.py +303 -0
  195. htmlgraph/orchestration/__init__.py +58 -0
  196. htmlgraph/orchestration/claude_launcher.py +179 -0
  197. htmlgraph/orchestration/command_builder.py +72 -0
  198. htmlgraph/orchestration/headless_spawner.py +281 -0
  199. htmlgraph/orchestration/live_events.py +377 -0
  200. htmlgraph/orchestration/model_selection.py +327 -0
  201. htmlgraph/orchestration/plugin_manager.py +140 -0
  202. htmlgraph/orchestration/prompts.py +137 -0
  203. htmlgraph/orchestration/spawner_event_tracker.py +383 -0
  204. htmlgraph/orchestration/spawners/__init__.py +16 -0
  205. htmlgraph/orchestration/spawners/base.py +194 -0
  206. htmlgraph/orchestration/spawners/claude.py +173 -0
  207. htmlgraph/orchestration/spawners/codex.py +435 -0
  208. htmlgraph/orchestration/spawners/copilot.py +294 -0
  209. htmlgraph/orchestration/spawners/gemini.py +471 -0
  210. htmlgraph/orchestration/subprocess_runner.py +36 -0
  211. htmlgraph/{orchestration.py → orchestration/task_coordination.py} +16 -8
  212. htmlgraph/orchestration.md +563 -0
  213. htmlgraph/orchestrator-system-prompt-optimized.txt +863 -0
  214. htmlgraph/orchestrator.py +2 -1
  215. htmlgraph/orchestrator_config.py +357 -0
  216. htmlgraph/orchestrator_mode.py +115 -4
  217. htmlgraph/parallel.py +2 -1
  218. htmlgraph/parser.py +86 -6
  219. htmlgraph/path_query.py +608 -0
  220. htmlgraph/pattern_matcher.py +636 -0
  221. htmlgraph/pydantic_models.py +476 -0
  222. htmlgraph/quality_gates.py +350 -0
  223. htmlgraph/query_builder.py +2 -1
  224. htmlgraph/query_composer.py +509 -0
  225. htmlgraph/reflection.py +443 -0
  226. htmlgraph/refs.py +344 -0
  227. htmlgraph/repo_hash.py +512 -0
  228. htmlgraph/repositories/__init__.py +292 -0
  229. htmlgraph/repositories/analytics_repository.py +455 -0
  230. htmlgraph/repositories/analytics_repository_standard.py +628 -0
  231. htmlgraph/repositories/feature_repository.py +581 -0
  232. htmlgraph/repositories/feature_repository_htmlfile.py +668 -0
  233. htmlgraph/repositories/feature_repository_memory.py +607 -0
  234. htmlgraph/repositories/feature_repository_sqlite.py +858 -0
  235. htmlgraph/repositories/filter_service.py +620 -0
  236. htmlgraph/repositories/filter_service_standard.py +445 -0
  237. htmlgraph/repositories/shared_cache.py +621 -0
  238. htmlgraph/repositories/shared_cache_memory.py +395 -0
  239. htmlgraph/repositories/track_repository.py +552 -0
  240. htmlgraph/repositories/track_repository_htmlfile.py +619 -0
  241. htmlgraph/repositories/track_repository_memory.py +508 -0
  242. htmlgraph/repositories/track_repository_sqlite.py +711 -0
  243. htmlgraph/sdk/__init__.py +398 -0
  244. htmlgraph/sdk/__init__.pyi +14 -0
  245. htmlgraph/sdk/analytics/__init__.py +19 -0
  246. htmlgraph/sdk/analytics/engine.py +155 -0
  247. htmlgraph/sdk/analytics/helpers.py +178 -0
  248. htmlgraph/sdk/analytics/registry.py +109 -0
  249. htmlgraph/sdk/base.py +484 -0
  250. htmlgraph/sdk/constants.py +216 -0
  251. htmlgraph/sdk/core.pyi +308 -0
  252. htmlgraph/sdk/discovery.py +120 -0
  253. htmlgraph/sdk/help/__init__.py +12 -0
  254. htmlgraph/sdk/help/mixin.py +699 -0
  255. htmlgraph/sdk/mixins/__init__.py +15 -0
  256. htmlgraph/sdk/mixins/attribution.py +113 -0
  257. htmlgraph/sdk/mixins/mixin.py +410 -0
  258. htmlgraph/sdk/operations/__init__.py +12 -0
  259. htmlgraph/sdk/operations/mixin.py +427 -0
  260. htmlgraph/sdk/orchestration/__init__.py +17 -0
  261. htmlgraph/sdk/orchestration/coordinator.py +203 -0
  262. htmlgraph/sdk/orchestration/spawner.py +204 -0
  263. htmlgraph/sdk/planning/__init__.py +19 -0
  264. htmlgraph/sdk/planning/bottlenecks.py +93 -0
  265. htmlgraph/sdk/planning/mixin.py +211 -0
  266. htmlgraph/sdk/planning/parallel.py +186 -0
  267. htmlgraph/sdk/planning/queue.py +210 -0
  268. htmlgraph/sdk/planning/recommendations.py +87 -0
  269. htmlgraph/sdk/planning/smart_planning.py +319 -0
  270. htmlgraph/sdk/session/__init__.py +19 -0
  271. htmlgraph/sdk/session/continuity.py +57 -0
  272. htmlgraph/sdk/session/handoff.py +110 -0
  273. htmlgraph/sdk/session/info.py +309 -0
  274. htmlgraph/sdk/session/manager.py +103 -0
  275. htmlgraph/sdk/strategic/__init__.py +26 -0
  276. htmlgraph/sdk/strategic/mixin.py +563 -0
  277. htmlgraph/server.py +295 -107
  278. htmlgraph/session_hooks.py +300 -0
  279. htmlgraph/session_manager.py +285 -3
  280. htmlgraph/session_registry.py +587 -0
  281. htmlgraph/session_state.py +436 -0
  282. htmlgraph/session_warning.py +2 -1
  283. htmlgraph/sessions/__init__.py +23 -0
  284. htmlgraph/sessions/handoff.py +756 -0
  285. htmlgraph/system_prompts.py +450 -0
  286. htmlgraph/templates/orchestration-view.html +350 -0
  287. htmlgraph/track_builder.py +33 -1
  288. htmlgraph/track_manager.py +38 -0
  289. htmlgraph/transcript.py +18 -5
  290. htmlgraph/validation.py +115 -0
  291. htmlgraph/watch.py +2 -1
  292. htmlgraph/work_type_utils.py +2 -1
  293. {htmlgraph-0.20.1.data → htmlgraph-0.27.5.data}/data/htmlgraph/dashboard.html +2246 -248
  294. {htmlgraph-0.20.1.dist-info → htmlgraph-0.27.5.dist-info}/METADATA +95 -64
  295. htmlgraph-0.27.5.dist-info/RECORD +337 -0
  296. {htmlgraph-0.20.1.dist-info → htmlgraph-0.27.5.dist-info}/entry_points.txt +1 -1
  297. htmlgraph/cli.py +0 -4839
  298. htmlgraph/sdk.py +0 -2359
  299. htmlgraph-0.20.1.dist-info/RECORD +0 -118
  300. {htmlgraph-0.20.1.data → htmlgraph-0.27.5.data}/data/htmlgraph/styles.css +0 -0
  301. {htmlgraph-0.20.1.data → htmlgraph-0.27.5.data}/data/htmlgraph/templates/AGENTS.md.template +0 -0
  302. {htmlgraph-0.20.1.data → htmlgraph-0.27.5.data}/data/htmlgraph/templates/CLAUDE.md.template +0 -0
  303. {htmlgraph-0.20.1.data → htmlgraph-0.27.5.data}/data/htmlgraph/templates/GEMINI.md.template +0 -0
  304. {htmlgraph-0.20.1.dist-info → htmlgraph-0.27.5.dist-info}/WHEEL +0 -0
@@ -0,0 +1,443 @@
1
+ <div class="view-container orchestration-view">
2
+ <div class="view-header">
3
+ <h2>Agent Orchestration Graph</h2>
4
+ <div class="view-description">
5
+ Real-time visualization of agent delegation chains and multi-hop workflows
6
+ </div>
7
+ <div class="view-filters">
8
+ <div class="filter-group">
9
+ <label>Filter by Agent:</label>
10
+ <select class="filter-select" id="agent-filter">
11
+ <option value="all">All Agents</option>
12
+ {% set agents = [] %}
13
+ {% for d in delegations %}
14
+ {% if d.from_agent not in agents %}
15
+ {% set _ = agents.append(d.from_agent) %}
16
+ {% endif %}
17
+ {% if d.to_agent not in agents %}
18
+ {% set _ = agents.append(d.to_agent) %}
19
+ {% endif %}
20
+ {% endfor %}
21
+ {% for agent in agents|sort %}
22
+ <option value="{{ agent }}">{{ agent }}</option>
23
+ {% endfor %}
24
+ </select>
25
+ </div>
26
+ </div>
27
+ </div>
28
+
29
+ <!-- DAG Visualization Container -->
30
+ <div class="orchestration-graph">
31
+ <div class="graph-container">
32
+ <svg class="graph-edges" id="graph-edges"></svg>
33
+ <div class="graph-nodes" id="graph-nodes"></div>
34
+ </div>
35
+ </div>
36
+
37
+ <!-- Stats -->
38
+ <div style="margin-top: var(--spacing-2xl); padding-top: var(--spacing-xl); border-top: 1px solid var(--border-subtle);">
39
+ <h3 style="color: var(--accent-lime); text-transform: uppercase; letter-spacing: 0.1em; margin-bottom: var(--spacing-lg);">
40
+ Orchestration Statistics
41
+ </h3>
42
+ <div class="metrics-grid">
43
+ <div class="metric-card">
44
+ <div class="metric-label">Total Delegations</div>
45
+ <div class="metric-value">{{ delegations|length }}</div>
46
+ <div class="metric-trend">Agent-to-agent handoffs</div>
47
+ </div>
48
+ <div class="metric-card">
49
+ <div class="metric-label">Unique Agents</div>
50
+ <div class="metric-value" id="unique-agents">
51
+ {% set unique_agents = {} %}
52
+ {% for d in delegations %}
53
+ {% if d.from_agent not in unique_agents %}
54
+ {% set _ = unique_agents.update({d.from_agent: True}) %}
55
+ {% endif %}
56
+ {% if d.to_agent not in unique_agents %}
57
+ {% set _ = unique_agents.update({d.to_agent: True}) %}
58
+ {% endif %}
59
+ {% endfor %}
60
+ {{ unique_agents|length }}
61
+ </div>
62
+ <div class="metric-trend">In network</div>
63
+ </div>
64
+ <div class="metric-card">
65
+ <div class="metric-label">Deepest Chain</div>
66
+ <div class="metric-value" id="deepest-chain">—</div>
67
+ <div class="metric-trend">Hops in longest path</div>
68
+ </div>
69
+ <div class="metric-card">
70
+ <div class="metric-label">Avg Chain Length</div>
71
+ <div class="metric-value" id="avg-chain-length">—</div>
72
+ <div class="metric-trend">Mean delegation depth</div>
73
+ </div>
74
+ </div>
75
+ </div>
76
+
77
+ <!-- Delegation List -->
78
+ {% if delegations %}
79
+ <div style="margin-top: var(--spacing-2xl); padding-top: var(--spacing-xl); border-top: 1px solid var(--border-subtle);">
80
+ <h3 style="color: var(--accent-lime); text-transform: uppercase; letter-spacing: 0.1em; margin-bottom: var(--spacing-lg);">
81
+ Recent Delegations
82
+ </h3>
83
+ <div style="background: var(--bg-card); border: 1px solid var(--border-subtle); border-radius: 2px; overflow: hidden;">
84
+ <table style="width: 100%; border-collapse: collapse;">
85
+ <thead style="background: var(--bg-darker); border-bottom: 1px solid var(--border-subtle);">
86
+ <tr>
87
+ <th style="padding: var(--spacing-lg); text-align: left; color: var(--accent-lime); font-size: 0.85rem; text-transform: uppercase; letter-spacing: 0.05em;">From</th>
88
+ <th style="padding: var(--spacing-lg); text-align: left; color: var(--accent-lime); font-size: 0.85rem; text-transform: uppercase; letter-spacing: 0.05em;">To</th>
89
+ <th style="padding: var(--spacing-lg); text-align: left; color: var(--accent-lime); font-size: 0.85rem; text-transform: uppercase; letter-spacing: 0.05em;">Task</th>
90
+ <th style="padding: var(--spacing-lg); text-align: left; color: var(--accent-lime); font-size: 0.85rem; text-transform: uppercase; letter-spacing: 0.05em;">Timestamp</th>
91
+ </tr>
92
+ </thead>
93
+ <tbody>
94
+ {% for delegation in delegations[:20] %}
95
+ <tr style="border-bottom: 1px solid var(--border-subtle);">
96
+ <td style="padding: var(--spacing-lg);">
97
+ <span style="background: rgba(139, 92, 246, 0.1); border: 1px solid rgba(139, 92, 246, 0.3); padding: var(--spacing-xs) var(--spacing-sm); border-radius: 2px; color: var(--agent-claude); font-size: 0.85rem; font-weight: 600;">
98
+ {{ delegation.from_agent }}
99
+ </span>
100
+ </td>
101
+ <td style="padding: var(--spacing-lg);">
102
+ <span style="background: rgba(59, 130, 246, 0.1); border: 1px solid rgba(59, 130, 246, 0.3); padding: var(--spacing-xs) var(--spacing-sm); border-radius: 2px; color: var(--agent-gemini); font-size: 0.85rem; font-weight: 600;">
103
+ {{ delegation.to_agent }}
104
+ </span>
105
+ </td>
106
+ <td style="padding: var(--spacing-lg); color: var(--text-secondary); max-width: 300px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;">
107
+ {% if delegation.task %}
108
+ {{ delegation.task[:60] }}{% if delegation.task|length > 60 %}...{% endif %}
109
+ {% else %}
110
+ <span style="color: var(--text-muted);">—</span>
111
+ {% endif %}
112
+ </td>
113
+ <td style="padding: var(--spacing-lg); color: var(--text-secondary); font-family: 'Courier New', monospace; font-size: 0.9rem;">
114
+ {{ delegation.timestamp }}
115
+ </td>
116
+ </tr>
117
+ {% endfor %}
118
+ </tbody>
119
+ </table>
120
+ </div>
121
+ </div>
122
+ {% else %}
123
+ <div style="margin-top: var(--spacing-2xl); padding: var(--spacing-2xl); background: var(--bg-card); border: 1px solid var(--border-subtle); border-radius: 2px; text-align: center; color: var(--text-muted);">
124
+ <p style="font-size: 1.1rem; margin-bottom: var(--spacing-md);">No delegation chains found</p>
125
+ <small>Agent-to-agent delegations will appear here as tasks are assigned</small>
126
+ </div>
127
+ {% endif %}
128
+ </div>
129
+
130
+ <script>
131
+ // Graph rendering for orchestration DAG
132
+ class OrchestrationGraph {
133
+ constructor(delegations) {
134
+ this.delegations = delegations;
135
+ this.nodes = [];
136
+ this.edges = [];
137
+ this.nodeMap = new Map();
138
+ this.init();
139
+ }
140
+
141
+ init() {
142
+ // Build node map from delegations
143
+ this.delegations.forEach(d => {
144
+ if (!this.nodeMap.has(d.from_agent)) {
145
+ this.nodeMap.set(d.from_agent, {
146
+ id: d.from_agent,
147
+ label: d.from_agent,
148
+ x: 0,
149
+ y: 0,
150
+ inDegree: 0,
151
+ outDegree: 0,
152
+ totalCost: 0
153
+ });
154
+ }
155
+ if (!this.nodeMap.has(d.to_agent)) {
156
+ this.nodeMap.set(d.to_agent, {
157
+ id: d.to_agent,
158
+ label: d.to_agent,
159
+ x: 0,
160
+ y: 0,
161
+ inDegree: 0,
162
+ outDegree: 0,
163
+ totalCost: 0
164
+ });
165
+ }
166
+
167
+ const fromNode = this.nodeMap.get(d.from_agent);
168
+ const toNode = this.nodeMap.get(d.to_agent);
169
+
170
+ fromNode.outDegree++;
171
+ toNode.inDegree++;
172
+ fromNode.totalCost += d.cost || 0;
173
+
174
+ this.edges.push({
175
+ from: d.from_agent,
176
+ to: d.to_agent,
177
+ task: d.task,
178
+ cost: d.cost || 0
179
+ });
180
+ });
181
+
182
+ this.nodes = Array.from(this.nodeMap.values());
183
+
184
+ // Layout nodes using simple force-directed approach
185
+ this.layoutNodes();
186
+ this.render();
187
+ }
188
+
189
+ layoutNodes() {
190
+ const container = document.getElementById('graph-nodes');
191
+ const width = container.parentElement.offsetWidth;
192
+ const height = container.parentElement.offsetHeight;
193
+
194
+ // Arrange nodes horizontally by level (topological sort)
195
+ const levels = this.getNodeLevels();
196
+ const levelCounts = new Map();
197
+
198
+ this.nodes.forEach(node => {
199
+ const level = levels.get(node.id) || 0;
200
+ const count = levelCounts.get(level) || 0;
201
+ levelCounts.set(level, count + 1);
202
+
203
+ const maxLevel = Math.max(...levels.values());
204
+ const levelWidth = width / (maxLevel + 2);
205
+ const levelHeight = height / (Math.max(...levelCounts.values()) + 1);
206
+
207
+ node.x = (level + 1) * levelWidth;
208
+ node.y = (count + 1) * levelHeight;
209
+ });
210
+ }
211
+
212
+ getNodeLevels() {
213
+ const levels = new Map();
214
+ const visited = new Set();
215
+
216
+ const visit = (nodeId, level) => {
217
+ if (visited.has(nodeId)) return;
218
+ visited.add(nodeId);
219
+
220
+ levels.set(nodeId, Math.max(levels.get(nodeId) || 0, level));
221
+
222
+ // Visit outgoing nodes
223
+ this.edges
224
+ .filter(e => e.from === nodeId)
225
+ .forEach(e => visit(e.to, level + 1));
226
+ };
227
+
228
+ this.nodes.forEach(node => visit(node.id, 0));
229
+ return levels;
230
+ }
231
+
232
+ render() {
233
+ const container = document.getElementById('graph-nodes');
234
+ container.innerHTML = '';
235
+
236
+ // Render edges first (so they appear behind nodes)
237
+ this.renderEdges();
238
+
239
+ // Render nodes
240
+ this.nodes.forEach(node => {
241
+ const nodeEl = document.createElement('div');
242
+ nodeEl.className = 'graph-node';
243
+ nodeEl.style.left = (node.x - 60) + 'px';
244
+ nodeEl.style.top = (node.y - 40) + 'px';
245
+
246
+ // Determine color based on model
247
+ const modelClass = node.id.toLowerCase().includes('gemini') ? 'gemini'
248
+ : node.id.toLowerCase().includes('copilot') ? 'copilot'
249
+ : 'claude';
250
+ nodeEl.classList.add(modelClass);
251
+
252
+ nodeEl.innerHTML = `
253
+ <div class="node-label">${node.label}</div>
254
+ <div class="node-cost">OUT: ${node.outDegree} | IN: ${node.inDegree}</div>
255
+ `;
256
+
257
+ container.appendChild(nodeEl);
258
+
259
+ // Add hover effect
260
+ nodeEl.addEventListener('mouseenter', () => {
261
+ this.highlightConnections(node.id);
262
+ });
263
+ nodeEl.addEventListener('mouseleave', () => {
264
+ this.clearHighlights();
265
+ });
266
+ });
267
+ }
268
+
269
+ renderEdges() {
270
+ const svg = document.getElementById('graph-edges');
271
+ svg.innerHTML = '';
272
+
273
+ this.edges.forEach(edge => {
274
+ const fromNode = this.nodeMap.get(edge.from);
275
+ const toNode = this.nodeMap.get(edge.to);
276
+
277
+ const x1 = fromNode.x + 60;
278
+ const y1 = fromNode.y;
279
+ const x2 = toNode.x - 60;
280
+ const y2 = toNode.y;
281
+
282
+ // Create curved path
283
+ const path = document.createElementNS('http://www.w3.org/2000/svg', 'path');
284
+ const curve = `M ${x1} ${y1} Q ${(x1 + x2) / 2} ${(y1 + y2) / 2 - 50} ${x2} ${y2}`;
285
+
286
+ path.setAttribute('d', curve);
287
+ path.setAttribute('stroke', 'rgba(205, 255, 0, 0.3)');
288
+ path.setAttribute('stroke-width', '2');
289
+ path.setAttribute('fill', 'none');
290
+ path.setAttribute('marker-end', 'url(#arrowhead)');
291
+
292
+ svg.appendChild(path);
293
+ });
294
+
295
+ // Add arrow marker
296
+ const defs = document.createElementNS('http://www.w3.org/2000/svg', 'defs');
297
+ const marker = document.createElementNS('http://www.w3.org/2000/svg', 'marker');
298
+ marker.setAttribute('id', 'arrowhead');
299
+ marker.setAttribute('markerWidth', '10');
300
+ marker.setAttribute('markerHeight', '10');
301
+ marker.setAttribute('refX', '9');
302
+ marker.setAttribute('refY', '3');
303
+ marker.setAttribute('orient', 'auto');
304
+
305
+ const polygon = document.createElementNS('http://www.w3.org/2000/svg', 'polygon');
306
+ polygon.setAttribute('points', '0 0, 10 3, 0 6');
307
+ polygon.setAttribute('fill', 'rgba(205, 255, 0, 0.5)');
308
+
309
+ marker.appendChild(polygon);
310
+ defs.appendChild(marker);
311
+ svg.appendChild(defs);
312
+ }
313
+
314
+ highlightConnections(nodeId) {
315
+ const svg = document.getElementById('graph-edges');
316
+ const paths = svg.querySelectorAll('path');
317
+
318
+ // Dim all paths first
319
+ paths.forEach(p => {
320
+ p.style.opacity = '0.2';
321
+ p.style.stroke = 'rgba(205, 255, 0, 0.2)';
322
+ });
323
+
324
+ // Highlight connected paths
325
+ this.edges.forEach((edge, idx) => {
326
+ if (edge.from === nodeId || edge.to === nodeId) {
327
+ paths[idx].style.opacity = '1';
328
+ paths[idx].style.stroke = 'rgba(205, 255, 0, 0.8)';
329
+ paths[idx].style.strokeWidth = '3';
330
+ }
331
+ });
332
+ }
333
+
334
+ clearHighlights() {
335
+ const svg = document.getElementById('graph-edges');
336
+ const paths = svg.querySelectorAll('path');
337
+ paths.forEach(p => {
338
+ p.style.opacity = '1';
339
+ p.style.stroke = 'rgba(205, 255, 0, 0.3)';
340
+ p.style.strokeWidth = '2';
341
+ });
342
+ }
343
+ }
344
+
345
+ // Initialize graph if delegations exist
346
+ const delegationsData = {{ delegations|tojson }};
347
+ if (delegationsData && delegationsData.length > 0) {
348
+ document.addEventListener('DOMContentLoaded', () => {
349
+ window.graph = new OrchestrationGraph(delegationsData);
350
+ });
351
+ }
352
+ </script>
353
+
354
+ <style>
355
+ .orchestration-graph {
356
+ background: var(--bg-card);
357
+ border: 1px solid var(--border-subtle);
358
+ border-radius: 2px;
359
+ padding: var(--spacing-xl);
360
+ height: 600px;
361
+ position: relative;
362
+ overflow: hidden;
363
+ margin-bottom: var(--spacing-2xl);
364
+ }
365
+
366
+ .graph-container {
367
+ width: 100%;
368
+ height: 100%;
369
+ position: relative;
370
+ }
371
+
372
+ .graph-edges {
373
+ position: absolute;
374
+ top: 0;
375
+ left: 0;
376
+ width: 100%;
377
+ height: 100%;
378
+ pointer-events: none;
379
+ z-index: 0;
380
+ }
381
+
382
+ .graph-nodes {
383
+ position: relative;
384
+ z-index: 1;
385
+ width: 100%;
386
+ height: 100%;
387
+ }
388
+
389
+ .graph-node {
390
+ position: absolute;
391
+ background: var(--bg-darker);
392
+ border: 2px solid var(--border-medium);
393
+ border-radius: 4px;
394
+ padding: var(--spacing-md);
395
+ min-width: 140px;
396
+ text-align: center;
397
+ cursor: pointer;
398
+ transition: all var(--transition-base);
399
+ user-select: none;
400
+ transform: translate(-50%, -50%);
401
+ }
402
+
403
+ .graph-node:hover {
404
+ border-color: var(--accent-lime);
405
+ box-shadow: var(--shadow-lg);
406
+ transform: translate(-50%, -50%) scale(1.1);
407
+ }
408
+
409
+ .graph-node.claude {
410
+ background: rgba(139, 92, 246, 0.1);
411
+ border-color: var(--agent-claude);
412
+ }
413
+
414
+ .graph-node.gemini {
415
+ background: rgba(59, 130, 246, 0.1);
416
+ border-color: var(--agent-gemini);
417
+ }
418
+
419
+ .graph-node.copilot {
420
+ background: rgba(107, 114, 128, 0.1);
421
+ border-color: var(--agent-copilot);
422
+ }
423
+
424
+ .node-label {
425
+ font-weight: 700;
426
+ color: var(--accent-lime);
427
+ font-size: 0.95rem;
428
+ margin-bottom: var(--spacing-sm);
429
+ text-transform: uppercase;
430
+ letter-spacing: 0.05em;
431
+ }
432
+
433
+ .node-cost {
434
+ font-size: 0.75rem;
435
+ color: var(--text-secondary);
436
+ }
437
+
438
+ @media (max-width: 768px) {
439
+ .orchestration-graph {
440
+ height: 400px;
441
+ }
442
+ }
443
+ </style>
@@ -0,0 +1,198 @@
1
+ <div class="view-container orchestration-view">
2
+ <div class="view-header">
3
+ <h2>Agent Orchestration Graph</h2>
4
+ <div class="view-description">
5
+ Real-time visualization of agent delegation chains and multi-hop workflows
6
+ </div>
7
+ <div class="view-filters">
8
+ <div class="filter-group">
9
+ <label>Filter by Agent:</label>
10
+ <select class="filter-select" id="agent-filter">
11
+ <option value="all">All Agents</option>
12
+ {% set agents = [] %}
13
+ {% for d in delegations %}
14
+ {% if d.from_agent not in agents %}
15
+ {% set _ = agents.append(d.from_agent) %}
16
+ {% endif %}
17
+ {% if d.to_agent not in agents %}
18
+ {% set _ = agents.append(d.to_agent) %}
19
+ {% endif %}
20
+ {% endfor %}
21
+ {% for agent in agents|sort %}
22
+ <option value="{{ agent }}">{{ agent }}</option>
23
+ {% endfor %}
24
+ </select>
25
+ </div>
26
+ </div>
27
+ </div>
28
+
29
+ <!-- Stats -->
30
+ <div style="margin-top: 1rem; padding-top: 0.75rem; border-top: 1px solid var(--border-subtle);">
31
+ <h3 style="color: var(--accent-lime); text-transform: uppercase; letter-spacing: 0.1em; margin-bottom: 0.5rem; font-size: 0.85rem;">
32
+ Orchestration Statistics
33
+ </h3>
34
+ <div class="metrics-grid">
35
+ <div class="metric-card">
36
+ <div class="metric-label">Total Delegations</div>
37
+ <div class="metric-value">{{ delegations|length }}</div>
38
+ <div class="metric-trend">Agent-to-agent handoffs</div>
39
+ </div>
40
+ <div class="metric-card">
41
+ <div class="metric-label">Unique Agents</div>
42
+ <div class="metric-value" id="unique-agents">
43
+ {% set unique_agents = {} %}
44
+ {% for d in delegations %}
45
+ {% if d.from_agent not in unique_agents %}
46
+ {% set _ = unique_agents.update({d.from_agent: True}) %}
47
+ {% endif %}
48
+ {% if d.to_agent not in unique_agents %}
49
+ {% set _ = unique_agents.update({d.to_agent: True}) %}
50
+ {% endif %}
51
+ {% endfor %}
52
+ {{ unique_agents|length }}
53
+ </div>
54
+ <div class="metric-trend">In network</div>
55
+ </div>
56
+ <div class="metric-card">
57
+ <div class="metric-label">Deepest Chain</div>
58
+ <div class="metric-value" id="deepest-chain">—</div>
59
+ <div class="metric-trend">Hops in longest path</div>
60
+ </div>
61
+ <div class="metric-card">
62
+ <div class="metric-label">Avg Chain Length</div>
63
+ <div class="metric-value" id="avg-chain-length">—</div>
64
+ <div class="metric-trend">Mean delegation depth</div>
65
+ </div>
66
+ </div>
67
+ </div>
68
+
69
+ <!-- Delegation List -->
70
+ {% if delegations %}
71
+ <div style="margin-top: 1rem; padding-top: 0.75rem; border-top: 1px solid var(--border-subtle);">
72
+ <h3 style="color: var(--accent-lime); text-transform: uppercase; letter-spacing: 0.1em; margin-bottom: 0.5rem; font-size: 0.85rem;">
73
+ Recent Delegations
74
+ </h3>
75
+ <div style="background: var(--bg-card); border: 1px solid var(--border-subtle); border-radius: 2px; overflow: hidden;">
76
+ <table style="width: 100%; border-collapse: collapse;">
77
+ <thead style="background: var(--bg-darker); border-bottom: 1px solid var(--border-subtle);">
78
+ <tr>
79
+ <th style="padding: 0.5rem 0.75rem; text-align: left; color: var(--accent-lime); font-size: 0.7rem; text-transform: uppercase; letter-spacing: 0.05em;">From</th>
80
+ <th style="padding: 0.5rem 0.75rem; text-align: left; color: var(--accent-lime); font-size: 0.7rem; text-transform: uppercase; letter-spacing: 0.05em;">To</th>
81
+ <th style="padding: 0.5rem 0.75rem; text-align: left; color: var(--accent-lime); font-size: 0.7rem; text-transform: uppercase; letter-spacing: 0.05em;">Task</th>
82
+ <th style="padding: 0.5rem 0.75rem; text-align: left; color: var(--accent-lime); font-size: 0.7rem; text-transform: uppercase; letter-spacing: 0.05em;">Status</th>
83
+ <th style="padding: 0.5rem 0.75rem; text-align: left; color: var(--accent-lime); font-size: 0.7rem; text-transform: uppercase; letter-spacing: 0.05em;">Session</th>
84
+ <th style="padding: 0.5rem 0.75rem; text-align: left; color: var(--accent-lime); font-size: 0.7rem; text-transform: uppercase; letter-spacing: 0.05em;">Timestamp</th>
85
+ </tr>
86
+ </thead>
87
+ <tbody>
88
+ {% for delegation in delegations[:20] %}
89
+ <tr style="border-bottom: 1px solid var(--border-subtle);">
90
+ <td style="padding: 0.4rem 0.75rem;">
91
+ <span style="background: rgba(139, 92, 246, 0.1); border: 1px solid rgba(139, 92, 246, 0.3); padding: 0.15rem 0.4rem; border-radius: 2px; color: var(--agent-claude); font-size: 0.75rem; font-weight: 600;">
92
+ {{ delegation.from_agent }}
93
+ </span>
94
+ </td>
95
+ <td style="padding: 0.4rem 0.75rem;">
96
+ <span style="background: rgba(59, 130, 246, 0.1); border: 1px solid rgba(59, 130, 246, 0.3); padding: 0.15rem 0.4rem; border-radius: 2px; color: var(--agent-gemini); font-size: 0.75rem; font-weight: 600;">
97
+ {{ delegation.to_agent }}
98
+ </span>
99
+ </td>
100
+ <td style="padding: 0.4rem 0.75rem; color: var(--text-secondary); max-width: 300px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 0.8rem;">
101
+ {% if delegation.task %}
102
+ {{ delegation.task[:60] }}{% if delegation.task|length > 60 %}...{% endif %}
103
+ {% else %}
104
+ <span style="color: var(--text-muted);">—</span>
105
+ {% endif %}
106
+ </td>
107
+ <td style="padding: 0.4rem 0.75rem;">
108
+ <span class="status-badge status-{{ delegation.status|lower }}">
109
+ {{ delegation.status }}
110
+ </span>
111
+ </td>
112
+ <td style="padding: 0.4rem 0.75rem; color: var(--text-muted); font-size: 0.7rem; font-family: monospace;">
113
+ {{ delegation.session_id[:8] }}
114
+ </td>
115
+ <td style="padding: 0.4rem 0.75rem; color: var(--text-secondary); font-family: 'Courier New', monospace; font-size: 0.75rem;">
116
+ {{ delegation.timestamp }}
117
+ </td>
118
+ </tr>
119
+ {% endfor %}
120
+ </tbody>
121
+ </table>
122
+ </div>
123
+ </div>
124
+ {% else %}
125
+ <div style="margin-top: 1rem; padding: 1rem; background: var(--bg-card); border: 1px solid var(--border-subtle); border-radius: 2px; text-align: center; color: var(--text-muted);">
126
+ <p style="font-size: 0.9rem; margin-bottom: 0.5rem;">No delegation chains found</p>
127
+ <small style="font-size: 0.75rem;">Agent-to-agent delegations will appear here as tasks are assigned</small>
128
+ </div>
129
+ {% endif %}
130
+ </div>
131
+
132
+ <style>
133
+ /* Compact view header */
134
+ .orchestration-view .view-header {
135
+ margin-bottom: 0.75rem;
136
+ }
137
+
138
+ .orchestration-view .view-description {
139
+ margin-bottom: 0.5rem;
140
+ }
141
+
142
+ /* Compact stats section */
143
+ .orchestration-view .metrics-grid {
144
+ display: grid;
145
+ grid-template-columns: repeat(4, 1fr);
146
+ gap: 0.75rem;
147
+ margin-bottom: 1rem;
148
+ }
149
+
150
+ .orchestration-view .metric-card {
151
+ padding: 0.75rem 1rem;
152
+ min-height: auto;
153
+ }
154
+
155
+ .orchestration-view .metric-value {
156
+ font-size: 1.5rem;
157
+ margin: 0.25rem 0;
158
+ }
159
+
160
+ .orchestration-view .metric-label {
161
+ font-size: 0.7rem;
162
+ }
163
+
164
+ .orchestration-view .metric-trend {
165
+ font-size: 0.65rem;
166
+ }
167
+
168
+ /* Status Badges */
169
+ .status-badge {
170
+ padding: 0.15rem 0.4rem;
171
+ border-radius: 2px;
172
+ font-size: 0.65rem;
173
+ font-weight: 600;
174
+ text-transform: uppercase;
175
+ letter-spacing: 0.05em;
176
+ }
177
+ .status-completed, .status-success, .status-recorded {
178
+ background: rgba(34, 197, 94, 0.15);
179
+ color: #4ade80;
180
+ border: 1px solid rgba(34, 197, 94, 0.3);
181
+ }
182
+ .status-pending, .status-active {
183
+ background: rgba(251, 191, 36, 0.15);
184
+ color: #fbbf24;
185
+ border: 1px solid rgba(251, 191, 36, 0.3);
186
+ }
187
+ .status-failed, .status-error {
188
+ background: rgba(239, 68, 68, 0.15);
189
+ color: #f87171;
190
+ border: 1px solid rgba(239, 68, 68, 0.3);
191
+ }
192
+
193
+ @media (max-width: 768px) {
194
+ .orchestration-view .metrics-grid {
195
+ grid-template-columns: repeat(2, 1fr);
196
+ }
197
+ }
198
+ </style>