@team-agent/installer 0.1.10 → 0.1.11
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/package.json
CHANGED
|
@@ -118,7 +118,7 @@ For diagnosis, run `team-agent profile show deepseek --workspace . --json`; neve
|
|
|
118
118
|
- `team-agent send --watch-result coder "Do the bounded task"` sends a direct worker message, returns after delivery, and lets the coordinator collect/report completion asynchronously.
|
|
119
119
|
- After `send --watch-result` succeeds, do not run `sleep`, `status`, `inbox`, or `collect` polling loops unless the user explicitly asks for diagnosis; the coordinator will notify the leader when the result arrives.
|
|
120
120
|
- `team-agent send --task task_initial "Start"` routes by task.
|
|
121
|
-
- `team-agent status` shows team, worker health, result-store counts, `session_id`, `captured_via`, and attribution confidence.
|
|
121
|
+
- `team-agent status` shows team, worker health, result-store counts, `session_id`, `captured_via`, and attribution confidence. `team-agent status --json` is compact and context-safe by default; use `team-agent status --detail --json` only for raw runtime-state diagnostics.
|
|
122
122
|
- `team-agent status coder` shows one worker.
|
|
123
123
|
- `team-agent approvals [coder]` shows structured pending approval prompts without copying worker terminal pages.
|
|
124
124
|
- `team-agent inbox coder` shows message history only. Final results are not in inbox.
|
package/src/team_agent/cli.py
CHANGED
|
@@ -135,6 +135,7 @@ def main(argv: list[str] | None = None) -> None:
|
|
|
135
135
|
p = sub.add_parser("status", help="Show team runtime status")
|
|
136
136
|
p.add_argument("agent", nargs="?")
|
|
137
137
|
p.add_argument("--workspace", default=".")
|
|
138
|
+
p.add_argument("--detail", action="store_true", help="Include full raw runtime state in --json output")
|
|
138
139
|
add_json(p)
|
|
139
140
|
p.set_defaults(func=cmd_status)
|
|
140
141
|
|
|
@@ -504,7 +505,7 @@ def cmd_settle(args: argparse.Namespace) -> dict[str, Any]:
|
|
|
504
505
|
|
|
505
506
|
def cmd_status(args: argparse.Namespace) -> dict[str, Any]:
|
|
506
507
|
if args.json:
|
|
507
|
-
return runtime.status(Path(args.workspace).resolve(), as_json=True)
|
|
508
|
+
return runtime.status(Path(args.workspace).resolve(), as_json=True, compact=not args.detail)
|
|
508
509
|
return runtime.format_status(Path(args.workspace).resolve(), args.agent)
|
|
509
510
|
|
|
510
511
|
|
|
@@ -170,7 +170,7 @@ class TeamOrchestratorTools:
|
|
|
170
170
|
return {"ok": True, "state_file": str(path)}
|
|
171
171
|
|
|
172
172
|
def get_team_status(self) -> dict[str, Any]:
|
|
173
|
-
return runtime.status(self.workspace, as_json=True)
|
|
173
|
+
return runtime.status(self.workspace, as_json=True, compact=True)
|
|
174
174
|
|
|
175
175
|
def request_human(self, question: str, task_id: str | None = None, agent_id: str | None = None) -> dict[str, Any]:
|
|
176
176
|
store = MessageStore(self.workspace)
|
|
@@ -56,6 +56,8 @@ TMUX_PANE_FORMAT = (
|
|
|
56
56
|
HEALTH_STATUSES = {"RUNNING", "IDLE", "AWAITING_APPROVAL", "BLOCKED", "ERROR", "DONE"}
|
|
57
57
|
GHOSTTY_DISPLAY_BACKENDS = {"ghostty", "ghostty_window", "ghostty_workspace"}
|
|
58
58
|
GHOSTTY_WORKSPACE_PANES_PER_WINDOW = 3
|
|
59
|
+
STATUS_TEXT_LIMIT = 240
|
|
60
|
+
STATUS_EVENT_LIMIT = 3
|
|
59
61
|
PEEK_MAX_LINES = 80
|
|
60
62
|
PEEK_SEARCH_SCAN_LINES = 300
|
|
61
63
|
PEEK_MAX_MATCHES = 5
|
|
@@ -635,7 +637,7 @@ def _quick_start_existing_context(workspace: Path, session_name: str) -> dict[st
|
|
|
635
637
|
return None
|
|
636
638
|
|
|
637
639
|
|
|
638
|
-
def status(workspace: Path, as_json: bool = False) -> dict[str, Any]:
|
|
640
|
+
def status(workspace: Path, as_json: bool = False, *, compact: bool = False) -> dict[str, Any]:
|
|
639
641
|
state = load_runtime_state(workspace)
|
|
640
642
|
store = MessageStore(workspace)
|
|
641
643
|
event_log = EventLog(workspace)
|
|
@@ -646,7 +648,7 @@ def status(workspace: Path, as_json: bool = False) -> dict[str, Any]:
|
|
|
646
648
|
save_runtime_state(workspace, state)
|
|
647
649
|
session_name = state.get("session_name")
|
|
648
650
|
tmux_exists = _tmux_session_exists(session_name) if session_name else False
|
|
649
|
-
|
|
651
|
+
result = {
|
|
650
652
|
"team": state.get("leader", {}).get("id", "leader"),
|
|
651
653
|
"session_name": session_name,
|
|
652
654
|
"tmux_session_present": tmux_exists,
|
|
@@ -658,6 +660,157 @@ def status(workspace: Path, as_json: bool = False) -> dict[str, Any]:
|
|
|
658
660
|
"results": store.result_counts(),
|
|
659
661
|
"last_events": EventLog(workspace).tail(10),
|
|
660
662
|
}
|
|
663
|
+
return _compact_status(result) if compact else result
|
|
664
|
+
|
|
665
|
+
|
|
666
|
+
def _compact_status(data: dict[str, Any]) -> dict[str, Any]:
|
|
667
|
+
return {
|
|
668
|
+
"team": data.get("team"),
|
|
669
|
+
"session_name": data.get("session_name"),
|
|
670
|
+
"tmux_session_present": data.get("tmux_session_present"),
|
|
671
|
+
"leader_receiver": _compact_mapping(
|
|
672
|
+
data.get("leader_receiver", {}),
|
|
673
|
+
{
|
|
674
|
+
"status",
|
|
675
|
+
"provider",
|
|
676
|
+
"mode",
|
|
677
|
+
"session_name",
|
|
678
|
+
"window_name",
|
|
679
|
+
"pane_id",
|
|
680
|
+
"pane_current_command",
|
|
681
|
+
},
|
|
682
|
+
),
|
|
683
|
+
"agents": {
|
|
684
|
+
agent_id: _compact_agent_state(agent_id, agent)
|
|
685
|
+
for agent_id, agent in (data.get("agents") or {}).items()
|
|
686
|
+
},
|
|
687
|
+
"agent_health": data.get("agent_health", {}),
|
|
688
|
+
"tasks": [_compact_task(task) for task in data.get("tasks", [])],
|
|
689
|
+
"messages": data.get("messages", {}),
|
|
690
|
+
"results": data.get("results", {}),
|
|
691
|
+
"last_events": [_compact_event(event) for event in data.get("last_events", [])[-STATUS_EVENT_LIMIT:]],
|
|
692
|
+
}
|
|
693
|
+
|
|
694
|
+
|
|
695
|
+
def _compact_agent_state(agent_id: str, agent: dict[str, Any]) -> dict[str, Any]:
|
|
696
|
+
display = agent.get("display") or {}
|
|
697
|
+
result = _compact_mapping(
|
|
698
|
+
agent,
|
|
699
|
+
{
|
|
700
|
+
"agent_id",
|
|
701
|
+
"status",
|
|
702
|
+
"provider",
|
|
703
|
+
"model",
|
|
704
|
+
"tmux_window_present",
|
|
705
|
+
"session_id",
|
|
706
|
+
"captured_via",
|
|
707
|
+
"attribution_confidence",
|
|
708
|
+
},
|
|
709
|
+
)
|
|
710
|
+
result.setdefault("agent_id", agent_id)
|
|
711
|
+
if display:
|
|
712
|
+
result["display"] = _compact_mapping(
|
|
713
|
+
display,
|
|
714
|
+
{
|
|
715
|
+
"backend",
|
|
716
|
+
"status",
|
|
717
|
+
"workspace_window",
|
|
718
|
+
"pane_id",
|
|
719
|
+
"pid",
|
|
720
|
+
"pids",
|
|
721
|
+
"reason",
|
|
722
|
+
},
|
|
723
|
+
)
|
|
724
|
+
return result
|
|
725
|
+
|
|
726
|
+
|
|
727
|
+
def _compact_task(task: dict[str, Any]) -> dict[str, Any]:
|
|
728
|
+
return _compact_mapping(
|
|
729
|
+
task,
|
|
730
|
+
{
|
|
731
|
+
"id",
|
|
732
|
+
"title",
|
|
733
|
+
"status",
|
|
734
|
+
"assignee",
|
|
735
|
+
"type",
|
|
736
|
+
"risk",
|
|
737
|
+
"accepted_result_id",
|
|
738
|
+
"last_result_summary",
|
|
739
|
+
},
|
|
740
|
+
)
|
|
741
|
+
|
|
742
|
+
|
|
743
|
+
def _compact_event(event: dict[str, Any]) -> dict[str, Any]:
|
|
744
|
+
skipped = {"command", "payload", "launch_args", "content", "prompt", "developer_instructions"}
|
|
745
|
+
kept = {
|
|
746
|
+
"event",
|
|
747
|
+
"ts",
|
|
748
|
+
"agent_id",
|
|
749
|
+
"task_id",
|
|
750
|
+
"message_id",
|
|
751
|
+
"result_id",
|
|
752
|
+
"status",
|
|
753
|
+
"ok",
|
|
754
|
+
"reason",
|
|
755
|
+
"error",
|
|
756
|
+
"session",
|
|
757
|
+
"window",
|
|
758
|
+
"target",
|
|
759
|
+
"backend",
|
|
760
|
+
"workspace_window",
|
|
761
|
+
"pane_id",
|
|
762
|
+
"restart_mode",
|
|
763
|
+
"provider",
|
|
764
|
+
"delivery_status",
|
|
765
|
+
"warning",
|
|
766
|
+
"collected",
|
|
767
|
+
"notified",
|
|
768
|
+
"lock",
|
|
769
|
+
"waited_sec",
|
|
770
|
+
"once",
|
|
771
|
+
"pid",
|
|
772
|
+
}
|
|
773
|
+
result: dict[str, Any] = {}
|
|
774
|
+
for key, value in event.items():
|
|
775
|
+
if key in skipped or key not in kept | {"agents", "coordinator"}:
|
|
776
|
+
continue
|
|
777
|
+
if key == "agents" and isinstance(value, list):
|
|
778
|
+
result["agent_count"] = len(value)
|
|
779
|
+
result["agents"] = [
|
|
780
|
+
_compact_mapping(item, {"agent_id", "restart_mode", "session_id"})
|
|
781
|
+
for item in value[:8]
|
|
782
|
+
if isinstance(item, dict)
|
|
783
|
+
]
|
|
784
|
+
continue
|
|
785
|
+
result[key] = _compact_value(value)
|
|
786
|
+
return result
|
|
787
|
+
|
|
788
|
+
|
|
789
|
+
def _compact_mapping(source: Any, keys: set[str]) -> dict[str, Any]:
|
|
790
|
+
if not isinstance(source, dict):
|
|
791
|
+
return {}
|
|
792
|
+
return {key: _compact_value(source[key]) for key in keys if key in source}
|
|
793
|
+
|
|
794
|
+
|
|
795
|
+
def _compact_value(value: Any) -> Any:
|
|
796
|
+
if isinstance(value, str):
|
|
797
|
+
return value if len(value) <= STATUS_TEXT_LIMIT else value[: STATUS_TEXT_LIMIT - 1] + "…"
|
|
798
|
+
if isinstance(value, (int, float, bool)) or value is None:
|
|
799
|
+
return value
|
|
800
|
+
if isinstance(value, list):
|
|
801
|
+
if all(isinstance(item, (str, int, float, bool)) or item is None for item in value):
|
|
802
|
+
compact = [_compact_value(item) for item in value[:8]]
|
|
803
|
+
if len(value) > 8:
|
|
804
|
+
compact.append(f"... {len(value) - 8} more")
|
|
805
|
+
return compact
|
|
806
|
+
return f"{len(value)} item(s)"
|
|
807
|
+
if isinstance(value, dict):
|
|
808
|
+
return {
|
|
809
|
+
key: _compact_value(item)
|
|
810
|
+
for key, item in value.items()
|
|
811
|
+
if key not in {"command", "payload", "launch_args", "content", "prompt", "developer_instructions"}
|
|
812
|
+
}
|
|
813
|
+
return str(value)
|
|
661
814
|
|
|
662
815
|
|
|
663
816
|
def format_status(workspace: Path, agent_id: str | None = None) -> str:
|