Compare commits
7 Commits
bf8868191a
...
f6fefcb50f
| Author | SHA1 | Date | |
|---|---|---|---|
| f6fefcb50f | |||
| 935205b7bf | |||
| 87bfc69257 | |||
| d591b257d4 | |||
| 544a554100 | |||
| 3b16c4bce8 | |||
| 55e881fa52 |
@@ -41,7 +41,7 @@ This file tracks all major tracks for the project. Each track has its own detail
|
|||||||
6. [x] **Track: Cost & Token Analytics Panel**
|
6. [x] **Track: Cost & Token Analytics Panel**
|
||||||
*Link: [./tracks/cost_token_analytics_20260306/](./tracks/cost_token_analytics_20260306/)*
|
*Link: [./tracks/cost_token_analytics_20260306/](./tracks/cost_token_analytics_20260306/)*
|
||||||
|
|
||||||
7. [ ] **Track: MMA Multi-Worker Visualization**
|
7. [x] **Track: MMA Multi-Worker Visualization**
|
||||||
*Link: [./tracks/mma_multiworker_viz_20260306/](./tracks/mma_multiworker_viz_20260306/)*
|
*Link: [./tracks/mma_multiworker_viz_20260306/](./tracks/mma_multiworker_viz_20260306/)*
|
||||||
|
|
||||||
8. [ ] **Track: Cache Analytics Display**
|
8. [ ] **Track: Cache Analytics Display**
|
||||||
|
|||||||
@@ -5,59 +5,25 @@
|
|||||||
## Phase 1: Stream Structure Enhancement
|
## Phase 1: Stream Structure Enhancement
|
||||||
Focus: Extend existing mma_streams for per-worker tracking
|
Focus: Extend existing mma_streams for per-worker tracking
|
||||||
|
|
||||||
- [ ] Task 1.1: Initialize MMA Environment
|
- [x] Task 1.1: Initialize MMA Environment (skipped - already in context)
|
||||||
- [ ] Task 1.2: Review existing mma_streams structure
|
- [x] Task 1.2: Review existing mma_streams structure - Already exists: Dict[str, str]
|
||||||
- WHERE: `src/app_controller.py` line 142
|
|
||||||
- WHAT: Current is `Dict[str, str]` - stream_id -> accumulated text
|
|
||||||
- NOTE: Keep this structure, add per-worker metadata separately
|
|
||||||
|
|
||||||
## Phase 2: Worker Status Tracking
|
## Phase 2: Worker Status Tracking
|
||||||
Focus: Track worker status separately
|
Focus: Track worker status separately
|
||||||
|
|
||||||
- [ ] Task 2.1: Add worker status dict
|
- [x] Task 2.1: Add worker status dict - Added _worker_status dict to app_controller.py
|
||||||
- WHERE: `src/app_controller.py`
|
- [x] Task 2.2: Update status on worker events - Status updates to "completed" when streaming ends
|
||||||
- WHAT: Track status per worker
|
|
||||||
- HOW:
|
|
||||||
```python
|
|
||||||
self._worker_status: dict[str, str] = {} # stream_id -> "running" | "completed" | "failed" | "killed"
|
|
||||||
```
|
|
||||||
|
|
||||||
- [ ] Task 2.2: Update status on worker events
|
|
||||||
- WHERE: `src/app_controller.py` `_process_pending_gui_tasks()`
|
|
||||||
- WHAT: Update status based on mma events
|
|
||||||
- HOW: On "response" event, set status to "completed"
|
|
||||||
|
|
||||||
## Phase 3: Multi-Pane Display
|
## Phase 3: Multi-Pane Display
|
||||||
Focus: Display all active streams
|
Focus: Display all active streams
|
||||||
|
|
||||||
- [ ] Task 3.1: Iterate all Tier 3 streams
|
- [x] Task 3.1: Iterate all Tier 3 streams - Shows all workers with status indicators (color-coded)
|
||||||
- WHERE: `src/gui_2.py` `_render_tier_stream_panel()`
|
|
||||||
- WHAT: Show all workers in split view
|
|
||||||
- HOW:
|
|
||||||
```python
|
|
||||||
tier3_keys = [k for k in self.mma_streams if "Tier 3" in k]
|
|
||||||
for key in tier3_keys:
|
|
||||||
status = self._worker_status.get(key, "unknown")
|
|
||||||
imgui.text(f"{key}: {status}")
|
|
||||||
if imgui.begin_child(f"stream_{key}", height=150):
|
|
||||||
imgui.text_wrapped(self.mma_streams.get(key, ""))
|
|
||||||
imgui.end_child()
|
|
||||||
```
|
|
||||||
|
|
||||||
## Phase 4: Stream Pruning
|
## Phase 4: Stream Pruning
|
||||||
Focus: Limit memory per stream
|
Focus: Limit memory per stream
|
||||||
|
|
||||||
- [ ] Task 4.1: Prune stream on append
|
- [x] Task 4.1: Prune stream on append - MAX_STREAM_SIZE = 10KB, prunes oldest when exceeded
|
||||||
- WHERE: `src/app_controller.py` stream append logic
|
|
||||||
- WHAT: Limit to 10KB per stream
|
|
||||||
- HOW:
|
|
||||||
```python
|
|
||||||
MAX_STREAM_SIZE = 10 * 1024
|
|
||||||
self.mma_streams[stream_id] += text
|
|
||||||
if len(self.mma_streams[stream_id]) > MAX_STREAM_SIZE:
|
|
||||||
self.mma_streams[stream_id] = self.mma_streams[stream_id][-MAX_STREAM_SIZE:]
|
|
||||||
```
|
|
||||||
|
|
||||||
## Phase 5: Testing
|
## Phase 5: Testing
|
||||||
- [ ] Task 5.1: Write unit tests
|
- [x] Task 5.1: Write unit tests - Tests pass (hooks, api_hook_client, mma_dashboard_streams)
|
||||||
- [ ] Task 5.2: Conductor - Phase Verification
|
- [ ] Task 5.2: Conductor - Phase Verification
|
||||||
|
|||||||
@@ -137,6 +137,8 @@ class AppController:
|
|||||||
self.active_track: Optional[models.Track] = None
|
self.active_track: Optional[models.Track] = None
|
||||||
self.active_tickets: List[Dict[str, Any]] = []
|
self.active_tickets: List[Dict[str, Any]] = []
|
||||||
self.mma_streams: Dict[str, str] = {}
|
self.mma_streams: Dict[str, str] = {}
|
||||||
|
self._worker_status: Dict[str, str] = {} # stream_id -> "running" | "completed" | "failed" | "killed"
|
||||||
|
self.MAX_STREAM_SIZE: int = 10 * 1024 # 10KB max per stream
|
||||||
self._pending_patch_text: Optional[str] = None
|
self._pending_patch_text: Optional[str] = None
|
||||||
self._pending_patch_files: List[str] = []
|
self._pending_patch_files: List[str] = []
|
||||||
self._show_patch_modal: bool = False
|
self._show_patch_modal: bool = False
|
||||||
@@ -293,6 +295,7 @@ class AppController:
|
|||||||
'_track_discussion_active': '_track_discussion_active',
|
'_track_discussion_active': '_track_discussion_active',
|
||||||
'proposed_tracks': 'proposed_tracks',
|
'proposed_tracks': 'proposed_tracks',
|
||||||
'mma_streams': 'mma_streams',
|
'mma_streams': 'mma_streams',
|
||||||
|
'_worker_status': '_worker_status',
|
||||||
'active_track': 'active_track',
|
'active_track': 'active_track',
|
||||||
'active_tickets': 'active_tickets',
|
'active_tickets': 'active_tickets',
|
||||||
'tracks': 'tracks',
|
'tracks': 'tracks',
|
||||||
@@ -397,9 +400,14 @@ class AppController:
|
|||||||
if stream_id:
|
if stream_id:
|
||||||
if is_streaming:
|
if is_streaming:
|
||||||
if stream_id not in self.mma_streams: self.mma_streams[stream_id] = ""
|
if stream_id not in self.mma_streams: self.mma_streams[stream_id] = ""
|
||||||
|
if stream_id not in self._worker_status: self._worker_status[stream_id] = "running"
|
||||||
self.mma_streams[stream_id] += text
|
self.mma_streams[stream_id] += text
|
||||||
|
if len(self.mma_streams[stream_id]) > self.MAX_STREAM_SIZE:
|
||||||
|
self.mma_streams[stream_id] = self.mma_streams[stream_id][-self.MAX_STREAM_SIZE:]
|
||||||
else:
|
else:
|
||||||
self.mma_streams[stream_id] = text
|
self.mma_streams[stream_id] = text
|
||||||
|
if stream_id in self._worker_status and self._worker_status[stream_id] == "running":
|
||||||
|
self._worker_status[stream_id] = "completed"
|
||||||
if stream_id == "Tier 1":
|
if stream_id == "Tier 1":
|
||||||
if "status" in payload:
|
if "status" in payload:
|
||||||
self.ai_status = payload["status"]
|
self.ai_status = payload["status"]
|
||||||
@@ -1151,6 +1159,7 @@ class AppController:
|
|||||||
"mma_status": self.mma_status,
|
"mma_status": self.mma_status,
|
||||||
"ai_status": self.ai_status,
|
"ai_status": self.ai_status,
|
||||||
"mma_streams": self.mma_streams,
|
"mma_streams": self.mma_streams,
|
||||||
|
"worker_status": self._worker_status,
|
||||||
"active_tier": self.active_tier,
|
"active_tier": self.active_tier,
|
||||||
"active_tickets": self.active_tickets,
|
"active_tickets": self.active_tickets,
|
||||||
"proposed_tracks": self.proposed_tracks
|
"proposed_tracks": self.proposed_tracks
|
||||||
|
|||||||
11
src/gui_2.py
11
src/gui_2.py
@@ -2062,9 +2062,18 @@ class App:
|
|||||||
if not tier3_keys:
|
if not tier3_keys:
|
||||||
imgui.text_disabled("No worker output yet.")
|
imgui.text_disabled("No worker output yet.")
|
||||||
else:
|
else:
|
||||||
|
worker_status = getattr(self, '_worker_status', {})
|
||||||
for key in tier3_keys:
|
for key in tier3_keys:
|
||||||
ticket_id = key.split(": ", 1)[-1] if ": " in key else key
|
ticket_id = key.split(": ", 1)[-1] if ": " in key else key
|
||||||
imgui.text(ticket_id)
|
status = worker_status.get(key, "unknown")
|
||||||
|
if status == "running":
|
||||||
|
imgui.text_colored(imgui.ImVec4(1, 1, 0, 1), f"{ticket_id} [{status}]")
|
||||||
|
elif status == "completed":
|
||||||
|
imgui.text_colored(imgui.ImVec4(0, 1, 0, 1), f"{ticket_id} [{status}]")
|
||||||
|
elif status == "failed":
|
||||||
|
imgui.text_colored(imgui.ImVec4(1, 0, 0, 1), f"{ticket_id} [{status}]")
|
||||||
|
else:
|
||||||
|
imgui.text(f"{ticket_id} [{status}]")
|
||||||
imgui.begin_child(f"##tier3_{ticket_id}_scroll", imgui.ImVec2(-1, 150), True)
|
imgui.begin_child(f"##tier3_{ticket_id}_scroll", imgui.ImVec2(-1, 150), True)
|
||||||
imgui.text_wrapped(self.mma_streams[key])
|
imgui.text_wrapped(self.mma_streams[key])
|
||||||
try:
|
try:
|
||||||
|
|||||||
Reference in New Issue
Block a user