personal memory agent
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

Add 5-second ghost rows for finished tasks in sol top

When a task finishes, its row stays visible for 5 seconds as a dimmed
"ghost" showing the task name, exit code (✓/✗), and last output line.
Ghost rows expire using the existing STATUS_TIMEOUT pattern. Tasks
cleaned up by dead-task detection also produce a ghost with unknown
exit code (?).

+69 -2
+69 -2
think/top.py
··· 53 53 self.cpu_cache = {} # Maps pid -> last cpu_percent value 54 54 self.cpu_procs = {} # Maps pid -> Process object for cpu tracking 55 55 self.running_tasks = {} # Maps ref -> task info from logs tract 56 + self.finished_tasks = {} # Maps ref -> ghost entry for recently finished tasks 56 57 self.command_queues = {} # Maps command_name -> queued count 57 58 self.event_queue: queue.Queue = queue.Queue() # Callosum events for main loop 58 59 self.active_notifications = {} # Maps service_name -> notification_id ··· 355 356 # Process exited - clean up 356 357 ref = message.get("ref") 357 358 if ref: 359 + task = self.running_tasks.get(ref) 360 + name = task["name"] if task else message.get("name", "unknown") 361 + last_log_entry = self.last_log_lines.get(ref) 362 + last_log = last_log_entry[2] if last_log_entry else "" 363 + exit_code = message.get("exit_code") 364 + self.finished_tasks[ref] = { 365 + "name": name, 366 + "exit_code": exit_code, 367 + "last_log": last_log, 368 + "finished_at": time.time(), 369 + } 370 + 358 371 # Remove from running tasks 359 372 task = self.running_tasks.pop(ref, None) 360 373 if task: ··· 573 586 for ref in refs_to_remove: 574 587 task = self.running_tasks.pop(ref, None) 575 588 if task: 589 + # Create ghost entry for dead task (no exit event received) 590 + last_log_entry = self.last_log_lines.get(ref) 591 + last_log = last_log_entry[2] if last_log_entry else "" 592 + self.finished_tasks[ref] = { 593 + "name": task["name"], 594 + "exit_code": None, # Unknown - no exit event 595 + "last_log": last_log, 596 + "finished_at": time.time(), 597 + } 576 598 pid = task["pid"] 577 599 self.cpu_procs.pop(pid, None) 578 600 self.cpu_cache.pop(pid, None) ··· 602 624 header = f" {'Task':<15} {'PID':<8} {'Runtime':<12} {'MB':>7} {'%':>5} {'Last':>5} Log" 603 625 output.append(t.bold + header + t.normal) 604 626 605 - if not tasks_only: 627 + # Expire old ghost entries 628 + now = time.time() 629 + self.finished_tasks = { 630 + ref: ghost 631 + for ref, ghost in self.finished_tasks.items() 632 + if now - ghost["finished_at"] <= self.STATUS_TIMEOUT 633 + } 634 + 635 + if not tasks_only and not self.finished_tasks: 606 636 # Show queued commands even when no tasks are running 607 637 queued_only = { 608 638 cmd: count for cmd, count in self.command_queues.items() if count > 0 ··· 616 646 output.append(t.dim + " -" + t.normal) 617 647 return output 618 648 619 - # Task rows (sorted by start time, oldest first) 620 649 tasks_sorted = sorted(tasks_only, key=lambda x: x["start_time"]) 621 650 622 651 for task in tasks_sorted: ··· 634 663 635 664 line = f" {name:<15} {pid:<8} {runtime:<12} {memory:>7} {cpu:>5} {log_age:>5} " 636 665 output.append(line + log_color + log_display + t.normal) 666 + 667 + # Ghost rows for recently finished tasks 668 + for ref, ghost in sorted( 669 + self.finished_tasks.items(), 670 + key=lambda x: x[1]["finished_at"], 671 + ): 672 + name = ghost["name"][:14] 673 + # Exit code display: ✓ for 0, ✗ N for nonzero, ? for unknown 674 + exit_code = ghost["exit_code"] 675 + if exit_code is None: 676 + exit_indicator = "?" 677 + exit_color = t.yellow 678 + elif exit_code == 0: 679 + exit_indicator = "✓" 680 + exit_color = t.green 681 + else: 682 + exit_indicator = f"✗ {exit_code}" 683 + exit_color = t.red 684 + 685 + # Format ghost log line (truncate to available width) 686 + last_log = ghost["last_log"] 687 + log_width = max(0, t.width - self.LOG_FIXED_WIDTH) 688 + if last_log and log_width > 0: 689 + last_log = last_log[:log_width] 690 + else: 691 + last_log = "" 692 + 693 + line = f" {name:<15} {'':<8} {'':<12} {'':>7} {'':>5} {'':>5} " 694 + output.append( 695 + t.dim 696 + + line 697 + + exit_color 698 + + exit_indicator 699 + + t.normal 700 + + t.dim 701 + + (" " + last_log if last_log else "") 702 + + t.normal 703 + ) 637 704 638 705 # Show queued commands not visible as running tasks 639 706 visible_commands = {task["name"] for task in tasks_only}