htmlgraph 0.26.5__py3-none-any.whl → 0.26.7__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 (70) hide show
  1. htmlgraph/.htmlgraph/.session-warning-state.json +1 -1
  2. htmlgraph/__init__.py +1 -1
  3. htmlgraph/api/main.py +50 -10
  4. htmlgraph/api/templates/dashboard-redesign.html +608 -54
  5. htmlgraph/api/templates/partials/activity-feed.html +21 -0
  6. htmlgraph/api/templates/partials/features.html +81 -12
  7. htmlgraph/api/templates/partials/orchestration.html +35 -0
  8. htmlgraph/cli/.htmlgraph/.session-warning-state.json +6 -0
  9. htmlgraph/cli/.htmlgraph/agents.json +72 -0
  10. htmlgraph/cli/__init__.py +42 -0
  11. htmlgraph/cli/__main__.py +6 -0
  12. htmlgraph/cli/analytics.py +939 -0
  13. htmlgraph/cli/base.py +660 -0
  14. htmlgraph/cli/constants.py +206 -0
  15. htmlgraph/cli/core.py +856 -0
  16. htmlgraph/cli/main.py +143 -0
  17. htmlgraph/cli/models.py +462 -0
  18. htmlgraph/cli/templates/__init__.py +1 -0
  19. htmlgraph/cli/templates/cost_dashboard.py +398 -0
  20. htmlgraph/cli/work/__init__.py +159 -0
  21. htmlgraph/cli/work/features.py +567 -0
  22. htmlgraph/cli/work/orchestration.py +675 -0
  23. htmlgraph/cli/work/sessions.py +465 -0
  24. htmlgraph/cli/work/tracks.py +485 -0
  25. htmlgraph/dashboard.html +6414 -634
  26. htmlgraph/db/schema.py +8 -3
  27. htmlgraph/docs/ORCHESTRATION_PATTERNS.md +20 -13
  28. htmlgraph/docs/README.md +2 -3
  29. htmlgraph/hooks/event_tracker.py +355 -26
  30. htmlgraph/hooks/git_commands.py +175 -0
  31. htmlgraph/hooks/orchestrator.py +137 -71
  32. htmlgraph/hooks/orchestrator_reflector.py +23 -0
  33. htmlgraph/hooks/pretooluse.py +29 -6
  34. htmlgraph/hooks/session_handler.py +28 -0
  35. htmlgraph/hooks/session_summary.py +391 -0
  36. htmlgraph/hooks/subagent_detection.py +202 -0
  37. htmlgraph/hooks/subagent_stop.py +71 -12
  38. htmlgraph/hooks/validator.py +192 -79
  39. htmlgraph/operations/__init__.py +18 -0
  40. htmlgraph/operations/initialization.py +596 -0
  41. htmlgraph/operations/initialization.py.backup +228 -0
  42. htmlgraph/orchestration/__init__.py +16 -1
  43. htmlgraph/orchestration/claude_launcher.py +185 -0
  44. htmlgraph/orchestration/command_builder.py +71 -0
  45. htmlgraph/orchestration/headless_spawner.py +72 -1332
  46. htmlgraph/orchestration/plugin_manager.py +136 -0
  47. htmlgraph/orchestration/prompts.py +137 -0
  48. htmlgraph/orchestration/spawners/__init__.py +16 -0
  49. htmlgraph/orchestration/spawners/base.py +194 -0
  50. htmlgraph/orchestration/spawners/claude.py +170 -0
  51. htmlgraph/orchestration/spawners/codex.py +442 -0
  52. htmlgraph/orchestration/spawners/copilot.py +299 -0
  53. htmlgraph/orchestration/spawners/gemini.py +478 -0
  54. htmlgraph/orchestration/subprocess_runner.py +33 -0
  55. htmlgraph/orchestration.md +563 -0
  56. htmlgraph/orchestrator-system-prompt-optimized.txt +620 -55
  57. htmlgraph/orchestrator_config.py +357 -0
  58. htmlgraph/orchestrator_mode.py +45 -12
  59. htmlgraph/transcript.py +16 -4
  60. htmlgraph-0.26.7.data/data/htmlgraph/dashboard.html +6592 -0
  61. {htmlgraph-0.26.5.dist-info → htmlgraph-0.26.7.dist-info}/METADATA +1 -1
  62. {htmlgraph-0.26.5.dist-info → htmlgraph-0.26.7.dist-info}/RECORD +68 -34
  63. {htmlgraph-0.26.5.dist-info → htmlgraph-0.26.7.dist-info}/entry_points.txt +1 -1
  64. htmlgraph/cli.py +0 -7256
  65. htmlgraph-0.26.5.data/data/htmlgraph/dashboard.html +0 -812
  66. {htmlgraph-0.26.5.data → htmlgraph-0.26.7.data}/data/htmlgraph/styles.css +0 -0
  67. {htmlgraph-0.26.5.data → htmlgraph-0.26.7.data}/data/htmlgraph/templates/AGENTS.md.template +0 -0
  68. {htmlgraph-0.26.5.data → htmlgraph-0.26.7.data}/data/htmlgraph/templates/CLAUDE.md.template +0 -0
  69. {htmlgraph-0.26.5.data → htmlgraph-0.26.7.data}/data/htmlgraph/templates/GEMINI.md.template +0 -0
  70. {htmlgraph-0.26.5.dist-info → htmlgraph-0.26.7.dist-info}/WHEEL +0 -0
@@ -2,5 +2,5 @@
2
2
  "dismissed_at": null,
3
3
  "dismissed_by": null,
4
4
  "session_id": null,
5
- "show_count": 30
5
+ "show_count": 59
6
6
  }
htmlgraph/__init__.py CHANGED
@@ -95,7 +95,7 @@ from htmlgraph.types import (
95
95
  )
96
96
  from htmlgraph.work_type_utils import infer_work_type, infer_work_type_from_id
97
97
 
98
- __version__ = "0.26.5"
98
+ __version__ = "0.26.7"
99
99
  __all__ = [
100
100
  # Exceptions
101
101
  "HtmlGraphError",
htmlgraph/api/main.py CHANGED
@@ -87,6 +87,7 @@ class EventModel(BaseModel):
87
87
  input_summary: str | None = None
88
88
  output_summary: str | None = None
89
89
  session_id: str
90
+ feature_id: str | None = None
90
91
  parent_event_id: str | None = None
91
92
  status: str
92
93
  model: str | None = None
@@ -394,7 +395,7 @@ def get_app(db_path: str) -> FastAPI:
394
395
  query = """
395
396
  SELECT e.event_id, e.agent_id, e.event_type, e.timestamp, e.tool_name,
396
397
  e.input_summary, e.output_summary, e.session_id,
397
- e.parent_event_id, e.status, e.model
398
+ e.parent_event_id, e.status, e.model, e.feature_id
398
399
  FROM agent_events e
399
400
  WHERE 1=1
400
401
  """
@@ -431,6 +432,7 @@ def get_app(db_path: str) -> FastAPI:
431
432
  parent_event_id=row[8],
432
433
  status=row[9],
433
434
  model=row[10],
435
+ feature_id=row[11],
434
436
  )
435
437
  for row in rows
436
438
  ]
@@ -769,7 +771,8 @@ def get_app(db_path: str) -> FastAPI:
769
771
  session_id,
770
772
  status,
771
773
  model,
772
- parent_event_id
774
+ parent_event_id,
775
+ feature_id
773
776
  FROM agent_events
774
777
  WHERE event_type IN ({event_type_placeholders})
775
778
  """
@@ -801,6 +804,7 @@ def get_app(db_path: str) -> FastAPI:
801
804
  "status": row[9],
802
805
  "model": row[10],
803
806
  "parent_event_id": row[11],
807
+ "feature_id": row[12],
804
808
  }
805
809
  )
806
810
 
@@ -1022,7 +1026,8 @@ def get_app(db_path: str) -> FastAPI:
1022
1026
  agent_id,
1023
1027
  model,
1024
1028
  context,
1025
- subagent_type
1029
+ subagent_type,
1030
+ feature_id
1026
1031
  FROM agent_events
1027
1032
  WHERE parent_event_id = ?
1028
1033
  ORDER BY timestamp ASC
@@ -1055,6 +1060,7 @@ def get_app(db_path: str) -> FastAPI:
1055
1060
  model = row[7]
1056
1061
  context_json = row[8]
1057
1062
  subagent_type = row[9]
1063
+ feature_id = row[10]
1058
1064
 
1059
1065
  # Parse context to extract spawner metadata
1060
1066
  context = {}
@@ -1103,6 +1109,7 @@ def get_app(db_path: str) -> FastAPI:
1103
1109
  "agent": agent,
1104
1110
  "depth": depth,
1105
1111
  "model": model,
1112
+ "feature_id": feature_id,
1106
1113
  }
1107
1114
 
1108
1115
  # Include spawner metadata if present
@@ -1689,7 +1696,7 @@ def get_app(db_path: str) -> FastAPI:
1689
1696
  # OPTIMIZATION: Use composite index idx_features_status_priority
1690
1697
  # for efficient filtering and ordering
1691
1698
  query = """
1692
- SELECT id, type, title, status, priority, assigned_to, created_at, updated_at
1699
+ SELECT id, type, title, status, priority, assigned_to, created_at, updated_at, description
1693
1700
  FROM features
1694
1701
  WHERE 1=1
1695
1702
  """
@@ -1699,18 +1706,38 @@ def get_app(db_path: str) -> FastAPI:
1699
1706
  query += " AND status = ?"
1700
1707
  params.append(status)
1701
1708
 
1702
- query += " ORDER BY priority DESC, created_at DESC LIMIT 100"
1709
+ query += " ORDER BY priority DESC, created_at DESC LIMIT 1000"
1703
1710
 
1704
1711
  exec_start = time.time()
1705
1712
  cursor = await db.execute(query, params)
1706
1713
  rows = await cursor.fetchall()
1714
+
1715
+ # Query all unique agents per feature for attribution chain
1716
+ # This only works for events that have feature_id populated
1717
+ agents_query = """
1718
+ SELECT feature_id, agent_id
1719
+ FROM agent_events
1720
+ WHERE feature_id IS NOT NULL
1721
+ GROUP BY feature_id, agent_id
1722
+ """
1723
+ agents_cursor = await db.execute(agents_query)
1724
+ agents_rows = await agents_cursor.fetchall()
1725
+
1726
+ feature_agents: dict[str, list[str]] = {}
1727
+ for row in agents_rows:
1728
+ fid, aid = row[0], row[1]
1729
+ if fid not in feature_agents:
1730
+ feature_agents[fid] = []
1731
+ feature_agents[fid].append(aid)
1732
+
1707
1733
  exec_time_ms = (time.time() - exec_start) * 1000
1708
1734
 
1709
1735
  for row in rows:
1736
+ feature_id = row[0]
1710
1737
  feature_status = row[3]
1711
1738
  features_by_status.setdefault(feature_status, []).append(
1712
1739
  {
1713
- "id": row[0],
1740
+ "id": feature_id,
1714
1741
  "type": row[1],
1715
1742
  "title": row[2],
1716
1743
  "status": feature_status,
@@ -1718,6 +1745,8 @@ def get_app(db_path: str) -> FastAPI:
1718
1745
  "assigned_to": row[5],
1719
1746
  "created_at": row[6],
1720
1747
  "updated_at": row[7],
1748
+ "description": row[8],
1749
+ "contributors": feature_agents.get(feature_id, []),
1721
1750
  }
1722
1751
  )
1723
1752
 
@@ -2162,7 +2191,9 @@ def get_app(db_path: str) -> FastAPI:
2162
2191
  # Only fetch events AFTER last_timestamp to stream new events only
2163
2192
  query = """
2164
2193
  SELECT event_id, agent_id, event_type, timestamp, tool_name,
2165
- input_summary, output_summary, session_id, status, model
2194
+ input_summary, output_summary, session_id, status, model,
2195
+ parent_event_id, execution_duration_seconds, context,
2196
+ cost_tokens
2166
2197
  FROM agent_events
2167
2198
  WHERE timestamp > ?
2168
2199
  ORDER BY timestamp ASC
@@ -2180,6 +2211,14 @@ def get_app(db_path: str) -> FastAPI:
2180
2211
 
2181
2212
  # Send events in order (no need to reverse with ASC)
2182
2213
  for row in rows_list:
2214
+ # Parse context JSON if present
2215
+ context_data = {}
2216
+ if row[12]: # context column
2217
+ try:
2218
+ context_data = json.loads(row[12])
2219
+ except (json.JSONDecodeError, TypeError):
2220
+ pass
2221
+
2183
2222
  event_data = {
2184
2223
  "type": "event",
2185
2224
  "event_id": row[0],
@@ -2192,9 +2231,10 @@ def get_app(db_path: str) -> FastAPI:
2192
2231
  "session_id": row[7],
2193
2232
  "status": row[8],
2194
2233
  "model": row[9],
2195
- "parent_event_id": None,
2196
- "cost_tokens": 0,
2197
- "execution_duration_seconds": 0.0,
2234
+ "parent_event_id": row[10],
2235
+ "execution_duration_seconds": row[11] or 0.0,
2236
+ "cost_tokens": row[13] or 0,
2237
+ "context": context_data,
2198
2238
  }
2199
2239
  await websocket.send_json(event_data)
2200
2240