@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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@team-agent/installer",
3
- "version": "0.1.10",
3
+ "version": "0.1.11",
4
4
  "description": "npx installer for Team Agent",
5
5
  "keywords": [
6
6
  "codex",
@@ -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.
@@ -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
- return {
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: