@oswaldzsh/devhive 0.1.1 → 0.1.3
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.
- package/README.md +4 -3
- package/control_plane/cli.py +37 -5
- package/control_plane/tui.py +14 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -5,13 +5,14 @@ Multi-Agent Software Development System — autonomous coding with verify-specia
|
|
|
5
5
|
## Install
|
|
6
6
|
|
|
7
7
|
```bash
|
|
8
|
-
npm install -g devhive
|
|
8
|
+
npm install -g @oswaldzsh/devhive
|
|
9
9
|
```
|
|
10
10
|
|
|
11
|
-
Or
|
|
11
|
+
Or from source:
|
|
12
12
|
|
|
13
13
|
```bash
|
|
14
|
-
|
|
14
|
+
git clone https://github.com/Oswald-Hao/devhive
|
|
15
|
+
cd devhive && bash install.sh
|
|
15
16
|
```
|
|
16
17
|
|
|
17
18
|
Requires Python 3.12+.
|
package/control_plane/cli.py
CHANGED
|
@@ -315,7 +315,22 @@ class DevHiveREPL:
|
|
|
315
315
|
|
|
316
316
|
match cmd_name:
|
|
317
317
|
case "help" | "h":
|
|
318
|
-
self.
|
|
318
|
+
self.tui.show(
|
|
319
|
+
"── Help ──",
|
|
320
|
+
"",
|
|
321
|
+
" :do, :d <desc> Submit task from description",
|
|
322
|
+
" :status, :st Show system status",
|
|
323
|
+
" :log, :l <id> Show task timeline",
|
|
324
|
+
" :review, :rv Review escalations",
|
|
325
|
+
" :resolve, :rs <id> Resolve escalation",
|
|
326
|
+
" :tasks, :t List all tasks",
|
|
327
|
+
" :watch <id> Zoom into a task",
|
|
328
|
+
" :quit, :q Exit",
|
|
329
|
+
"",
|
|
330
|
+
" !<cmd> Escape to shell",
|
|
331
|
+
"",
|
|
332
|
+
" Bare text → auto-submit as task",
|
|
333
|
+
)
|
|
319
334
|
self.tui.log_activity("system", "Showed help")
|
|
320
335
|
|
|
321
336
|
case "quit" | "q" | "exit":
|
|
@@ -365,7 +380,12 @@ class DevHiveREPL:
|
|
|
365
380
|
self.tui.update_task(task_id, "SPECIFY", "parsed",
|
|
366
381
|
spec.title)
|
|
367
382
|
self.tui.log_activity("task", f"Created {task_id[-16:]}: {spec.title}")
|
|
368
|
-
self.
|
|
383
|
+
self.tui.show(
|
|
384
|
+
f"✓ Task created: {task_id}",
|
|
385
|
+
f" Title: {spec.title}",
|
|
386
|
+
f" Priority: {spec.priority.value}",
|
|
387
|
+
*([f" Criteria: {c}" for c in spec.acceptance_criteria[:3]] if spec.acceptance_criteria else []),
|
|
388
|
+
)
|
|
369
389
|
except Exception as e:
|
|
370
390
|
self.tui.log_activity("error", f"Failed: {e}")
|
|
371
391
|
|
|
@@ -374,7 +394,10 @@ class DevHiveREPL:
|
|
|
374
394
|
store = self.orchestrator.checkpoint
|
|
375
395
|
tasks = store.get_pending_tasks()
|
|
376
396
|
escs = store.get_open_escalations()
|
|
377
|
-
|
|
397
|
+
lines = [f"Active tasks: {len(tasks)}", f"Open escalations: {len(escs)}"]
|
|
398
|
+
for e in escs[:5]:
|
|
399
|
+
lines.append(f" ⚠ {e.get('id', '?')[:30]}")
|
|
400
|
+
self.tui.show(*lines)
|
|
378
401
|
|
|
379
402
|
async def _cmd_list_tasks(self):
|
|
380
403
|
"""List all tasks in the TUI detail panel."""
|
|
@@ -385,18 +408,27 @@ class DevHiveREPL:
|
|
|
385
408
|
self.tui.update_task(t["id"], stage, t.get("status", ""),
|
|
386
409
|
t.get("spec_json", "{}")[:80])
|
|
387
410
|
self.tui.log_activity("system", f"Loaded {len(tasks)} tasks")
|
|
411
|
+
self.tui.show(f"Loaded {len(tasks)} tasks — see detail panel")
|
|
388
412
|
|
|
389
413
|
async def _cmd_show_log(self, task_id: str = None):
|
|
390
414
|
"""Show task execution timeline."""
|
|
391
415
|
if not task_id:
|
|
392
416
|
task_id = self.tui._selected_task
|
|
393
417
|
if not task_id:
|
|
394
|
-
self.tui.
|
|
418
|
+
self.tui.show("Usage: :log <task-id>")
|
|
395
419
|
return
|
|
396
420
|
|
|
397
421
|
store = self.orchestrator.checkpoint
|
|
398
422
|
history = store.get_task_history(task_id)
|
|
399
|
-
|
|
423
|
+
|
|
424
|
+
lines = [f"── Timeline: {task_id[-20:]} ──"]
|
|
425
|
+
for cp in history:
|
|
426
|
+
stage = cp.get("stage", "?")
|
|
427
|
+
outcome = cp.get("outcome", "?")
|
|
428
|
+
created = cp.get("created_at", "?")
|
|
429
|
+
icon = "+" if outcome in ("COMPLETED", "PASS") else "x" if outcome == "FAIL" else "~"
|
|
430
|
+
lines.append(f" [{created}] {icon} {stage} → {outcome}")
|
|
431
|
+
self.tui.show(*lines)
|
|
400
432
|
|
|
401
433
|
async def _cmd_review(self):
|
|
402
434
|
"""Interactive escalation review."""
|
package/control_plane/tui.py
CHANGED
|
@@ -63,6 +63,7 @@ class DevHiveTUI:
|
|
|
63
63
|
self._tasks: dict = {}
|
|
64
64
|
self._selected_task: Optional[str] = None
|
|
65
65
|
self._running = False
|
|
66
|
+
self._output_lines: list[str] = [] # command output shown in detail pane
|
|
66
67
|
|
|
67
68
|
def log_activity(self, source: str, message: str):
|
|
68
69
|
"""Add an entry to the activity feed."""
|
|
@@ -78,6 +79,10 @@ class DevHiveTUI:
|
|
|
78
79
|
def set_tasks(self, tasks: dict):
|
|
79
80
|
self._tasks = tasks
|
|
80
81
|
|
|
82
|
+
def show(self, *lines: str):
|
|
83
|
+
"""Set output lines to display in the detail panel. Auto-clears after next update."""
|
|
84
|
+
self._output_lines = list(lines)
|
|
85
|
+
|
|
81
86
|
@property
|
|
82
87
|
def uptime(self) -> str:
|
|
83
88
|
seconds = int(time.monotonic() - self._start_time)
|
|
@@ -158,7 +163,15 @@ class DevHiveTUI:
|
|
|
158
163
|
title_align="left")
|
|
159
164
|
|
|
160
165
|
def _detail_panel(self) -> Panel:
|
|
161
|
-
"""Detail view for selected or
|
|
166
|
+
"""Detail view for selected task, output, or command results."""
|
|
167
|
+
|
|
168
|
+
# Output mode: show command output when available
|
|
169
|
+
if self._output_lines:
|
|
170
|
+
text = Text("\n").join(Text(line) for line in self._output_lines)
|
|
171
|
+
panel = Panel(text, title="Output", border_style="bright_cyan",
|
|
172
|
+
title_align="left")
|
|
173
|
+
return panel
|
|
174
|
+
|
|
162
175
|
if self._selected_task and self._selected_task in self._tasks:
|
|
163
176
|
tasks_to_show = {self._selected_task: self._tasks[self._selected_task]}
|
|
164
177
|
elif self._tasks:
|
package/package.json
CHANGED