@team-agent/installer 0.2.11 → 0.3.0

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.
Files changed (326) hide show
  1. package/Cargo.lock +744 -0
  2. package/Cargo.toml +34 -0
  3. package/crates/team-agent/Cargo.toml +33 -0
  4. package/crates/team-agent/src/cli/adapters.rs +1343 -0
  5. package/crates/team-agent/src/cli/diagnose.rs +554 -0
  6. package/crates/team-agent/src/cli/emit.rs +1077 -0
  7. package/crates/team-agent/src/cli/helpers.rs +88 -0
  8. package/crates/team-agent/src/cli/leader.rs +216 -0
  9. package/crates/team-agent/src/cli/mod.rs +1141 -0
  10. package/crates/team-agent/src/cli/profile.rs +306 -0
  11. package/crates/team-agent/src/cli/send.rs +215 -0
  12. package/crates/team-agent/src/cli/status.rs +179 -0
  13. package/crates/team-agent/src/cli/status_port.rs +502 -0
  14. package/crates/team-agent/src/cli/tests/base.rs +616 -0
  15. package/crates/team-agent/src/cli/tests/compile.rs +96 -0
  16. package/crates/team-agent/src/cli/tests/divergence.rs +509 -0
  17. package/crates/team-agent/src/cli/tests/lane_c.rs +333 -0
  18. package/crates/team-agent/src/cli/tests/leader_watch.rs +395 -0
  19. package/crates/team-agent/src/cli/tests/main_preserved.rs +675 -0
  20. package/crates/team-agent/src/cli/tests/missing_subcommands.rs +390 -0
  21. package/crates/team-agent/src/cli/tests/mod.rs +97 -0
  22. package/crates/team-agent/src/cli/tests/peer_allow.rs +137 -0
  23. package/crates/team-agent/src/cli/tests/repair_state_byte_lock.rs +302 -0
  24. package/crates/team-agent/src/cli/tests/run_delegation.rs +305 -0
  25. package/crates/team-agent/src/cli/tests/status_send.rs +385 -0
  26. package/crates/team-agent/src/cli/tests/verb_profile.rs +182 -0
  27. package/crates/team-agent/src/cli/tests/verb_settle.rs +236 -0
  28. package/crates/team-agent/src/cli/tests/verb_validate.rs +184 -0
  29. package/crates/team-agent/src/cli/types.rs +605 -0
  30. package/crates/team-agent/src/compiler/tests.rs +701 -0
  31. package/crates/team-agent/src/compiler.rs +489 -0
  32. package/crates/team-agent/src/coordinator/backoff.rs +153 -0
  33. package/crates/team-agent/src/coordinator/health.rs +436 -0
  34. package/crates/team-agent/src/coordinator/mod.rs +80 -0
  35. package/crates/team-agent/src/coordinator/orphan.rs +179 -0
  36. package/crates/team-agent/src/coordinator/tests/abnormal.rs +255 -0
  37. package/crates/team-agent/src/coordinator/tests/basics.rs +262 -0
  38. package/crates/team-agent/src/coordinator/tests/daemon.rs +323 -0
  39. package/crates/team-agent/src/coordinator/tests/health_sync.rs +263 -0
  40. package/crates/team-agent/src/coordinator/tests/main_preserved.rs +136 -0
  41. package/crates/team-agent/src/coordinator/tests/mod.rs +310 -0
  42. package/crates/team-agent/src/coordinator/tests/spine.rs +261 -0
  43. package/crates/team-agent/src/coordinator/tests/takeover.rs +227 -0
  44. package/crates/team-agent/src/coordinator/tests/tick_core.rs +256 -0
  45. package/crates/team-agent/src/coordinator/tests/watch.rs +167 -0
  46. package/crates/team-agent/src/coordinator/tick.rs +2032 -0
  47. package/crates/team-agent/src/coordinator/types.rs +584 -0
  48. package/crates/team-agent/src/db/migration.rs +716 -0
  49. package/crates/team-agent/src/db/mod.rs +23 -0
  50. package/crates/team-agent/src/db/schema.rs +378 -0
  51. package/crates/team-agent/src/event_log.rs +375 -0
  52. package/crates/team-agent/src/fake_worker.rs +253 -0
  53. package/crates/team-agent/src/leader/helpers.rs +190 -0
  54. package/crates/team-agent/src/leader/inject.rs +33 -0
  55. package/crates/team-agent/src/leader/lease.rs +1063 -0
  56. package/crates/team-agent/src/leader/mod.rs +99 -0
  57. package/crates/team-agent/src/leader/owner_bind.rs +292 -0
  58. package/crates/team-agent/src/leader/rediscover/tests.rs +525 -0
  59. package/crates/team-agent/src/leader/rediscover.rs +1099 -0
  60. package/crates/team-agent/src/leader/start.rs +273 -0
  61. package/crates/team-agent/src/leader/takeover.rs +235 -0
  62. package/crates/team-agent/src/leader/tests/basics.rs +183 -0
  63. package/crates/team-agent/src/leader/tests/byte_findings.rs +234 -0
  64. package/crates/team-agent/src/leader/tests/identity.rs +206 -0
  65. package/crates/team-agent/src/leader/tests/idle.rs +271 -0
  66. package/crates/team-agent/src/leader/tests/lease_api.rs +225 -0
  67. package/crates/team-agent/src/leader/tests/lease_claim.rs +253 -0
  68. package/crates/team-agent/src/leader/tests/mod.rs +125 -0
  69. package/crates/team-agent/src/leader/tests/rediscover.rs +351 -0
  70. package/crates/team-agent/src/leader/tests/wake_start_owner.rs +204 -0
  71. package/crates/team-agent/src/leader/types.rs +487 -0
  72. package/crates/team-agent/src/lib.rs +85 -0
  73. package/crates/team-agent/src/lifecycle/display.rs +228 -0
  74. package/crates/team-agent/src/lifecycle/helpers.rs +112 -0
  75. package/crates/team-agent/src/lifecycle/launch/plan.rs +227 -0
  76. package/crates/team-agent/src/lifecycle/launch.rs +1833 -0
  77. package/crates/team-agent/src/lifecycle/mod.rs +62 -0
  78. package/crates/team-agent/src/lifecycle/restart/agent.rs +533 -0
  79. package/crates/team-agent/src/lifecycle/restart/common.rs +517 -0
  80. package/crates/team-agent/src/lifecycle/restart/orchestrator.rs +41 -0
  81. package/crates/team-agent/src/lifecycle/restart/rebuild.rs +268 -0
  82. package/crates/team-agent/src/lifecycle/restart/remove.rs +780 -0
  83. package/crates/team-agent/src/lifecycle/restart/selection.rs +208 -0
  84. package/crates/team-agent/src/lifecycle/restart/team_state.rs +242 -0
  85. package/crates/team-agent/src/lifecycle/restart.rs +76 -0
  86. package/crates/team-agent/src/lifecycle/tests/agent_ops.rs +455 -0
  87. package/crates/team-agent/src/lifecycle/tests/core.rs +989 -0
  88. package/crates/team-agent/src/lifecycle/tests/lane_ops.rs +583 -0
  89. package/crates/team-agent/src/lifecycle/tests/launch_spawn.rs +933 -0
  90. package/crates/team-agent/src/lifecycle/tests/main_preserved.rs +265 -0
  91. package/crates/team-agent/src/lifecycle/tests.rs +27 -0
  92. package/crates/team-agent/src/lifecycle/types.rs +685 -0
  93. package/crates/team-agent/src/main.rs +41 -0
  94. package/crates/team-agent/src/mcp_server/helpers.rs +228 -0
  95. package/crates/team-agent/src/mcp_server/mod.rs +183 -0
  96. package/crates/team-agent/src/mcp_server/normalize.rs +312 -0
  97. package/crates/team-agent/src/mcp_server/tests/golden.rs +283 -0
  98. package/crates/team-agent/src/mcp_server/tests/normalize.rs +244 -0
  99. package/crates/team-agent/src/mcp_server/tests/scoped.rs +189 -0
  100. package/crates/team-agent/src/mcp_server/tests/send.rs +222 -0
  101. package/crates/team-agent/src/mcp_server/tests/tools.rs +158 -0
  102. package/crates/team-agent/src/mcp_server/tests/wire.rs +159 -0
  103. package/crates/team-agent/src/mcp_server/tests.rs +38 -0
  104. package/crates/team-agent/src/mcp_server/tools.rs +603 -0
  105. package/crates/team-agent/src/mcp_server/types.rs +421 -0
  106. package/crates/team-agent/src/mcp_server/wire.rs +388 -0
  107. package/crates/team-agent/src/message_store.rs +767 -0
  108. package/crates/team-agent/src/messaging/activity.rs +433 -0
  109. package/crates/team-agent/src/messaging/delivery.rs +542 -0
  110. package/crates/team-agent/src/messaging/helpers.rs +209 -0
  111. package/crates/team-agent/src/messaging/leader_receiver.rs +340 -0
  112. package/crates/team-agent/src/messaging/mod.rs +147 -0
  113. package/crates/team-agent/src/messaging/peers.rs +32 -0
  114. package/crates/team-agent/src/messaging/results.rs +537 -0
  115. package/crates/team-agent/src/messaging/scheduler.rs +344 -0
  116. package/crates/team-agent/src/messaging/selftest.rs +100 -0
  117. package/crates/team-agent/src/messaging/send.rs +582 -0
  118. package/crates/team-agent/src/messaging/tests/basic.rs +357 -0
  119. package/crates/team-agent/src/messaging/tests/main_preserved.rs +122 -0
  120. package/crates/team-agent/src/messaging/tests/mod.rs +293 -0
  121. package/crates/team-agent/src/messaging/tests/runtime.rs +1422 -0
  122. package/crates/team-agent/src/messaging/tests/spine.rs +437 -0
  123. package/crates/team-agent/src/messaging/trust.rs +192 -0
  124. package/crates/team-agent/src/messaging/types.rs +355 -0
  125. package/crates/team-agent/src/messaging/watchers.rs +591 -0
  126. package/crates/team-agent/src/model/enums.rs +311 -0
  127. package/crates/team-agent/src/model/errors.rs +17 -0
  128. package/crates/team-agent/src/model/ids.rs +155 -0
  129. package/crates/team-agent/src/model/mod.rs +22 -0
  130. package/crates/team-agent/src/model/paths.rs +228 -0
  131. package/crates/team-agent/src/model/permissions.rs +567 -0
  132. package/crates/team-agent/src/model/routing.rs +340 -0
  133. package/crates/team-agent/src/model/spec.rs +680 -0
  134. package/crates/team-agent/src/model/task_graph.rs +380 -0
  135. package/crates/team-agent/src/model/testdata/fuzz.golden.yaml +43 -0
  136. package/crates/team-agent/src/model/testdata/fuzz.yaml +43 -0
  137. package/crates/team-agent/src/model/testdata/spec_invalid_a.yaml +207 -0
  138. package/crates/team-agent/src/model/testdata/team.spec.golden.yaml +206 -0
  139. package/crates/team-agent/src/model/testdata/team.spec.yaml +206 -0
  140. package/crates/team-agent/src/model/yaml/tests.rs +288 -0
  141. package/crates/team-agent/src/model/yaml.rs +800 -0
  142. package/crates/team-agent/src/packaging/install.rs +305 -0
  143. package/crates/team-agent/src/packaging/migrate.rs +30 -0
  144. package/crates/team-agent/src/packaging/mod.rs +82 -0
  145. package/crates/team-agent/src/packaging/repair.rs +24 -0
  146. package/crates/team-agent/src/packaging/tests.rs +829 -0
  147. package/crates/team-agent/src/packaging/types.rs +369 -0
  148. package/crates/team-agent/src/provider/adapter.rs +801 -0
  149. package/crates/team-agent/src/provider/approvals/mod.rs +2 -0
  150. package/crates/team-agent/src/provider/approvals/parsing.rs +452 -0
  151. package/crates/team-agent/src/provider/approvals/runtime_prompts.rs +163 -0
  152. package/crates/team-agent/src/provider/classify.rs +456 -0
  153. package/crates/team-agent/src/provider/faults.rs +136 -0
  154. package/crates/team-agent/src/provider/helpers.rs +41 -0
  155. package/crates/team-agent/src/provider/mod.rs +53 -0
  156. package/crates/team-agent/src/provider/startup_prompt.rs +423 -0
  157. package/crates/team-agent/src/provider/tests/adapter.rs +239 -0
  158. package/crates/team-agent/src/provider/tests/classify.rs +240 -0
  159. package/crates/team-agent/src/provider/tests/faults.rs +120 -0
  160. package/crates/team-agent/src/provider/tests/idle.rs +208 -0
  161. package/crates/team-agent/src/provider/tests/wire.rs +213 -0
  162. package/crates/team-agent/src/provider/tests.rs +31 -0
  163. package/crates/team-agent/src/provider/types.rs +424 -0
  164. package/crates/team-agent/src/state/identity.rs +656 -0
  165. package/crates/team-agent/src/state/mod.rs +58 -0
  166. package/crates/team-agent/src/state/owner_gate.rs +423 -0
  167. package/crates/team-agent/src/state/persist.rs +712 -0
  168. package/crates/team-agent/src/state/projection.rs +657 -0
  169. package/crates/team-agent/src/state/selector.rs +105 -0
  170. package/crates/team-agent/src/state/testdata/state-rich.canonical.json +133 -0
  171. package/crates/team-agent/src/tmux_backend/tests.rs +586 -0
  172. package/crates/team-agent/src/tmux_backend.rs +758 -0
  173. package/crates/team-agent/src/transport/test_support.rs +252 -0
  174. package/crates/team-agent/src/transport/tests/behavior.rs +327 -0
  175. package/crates/team-agent/src/transport/tests/mod.rs +199 -0
  176. package/crates/team-agent/src/transport/tests/wire.rs +527 -0
  177. package/crates/team-agent/src/transport.rs +774 -0
  178. package/npm/install.mjs +90 -106
  179. package/package.json +15 -13
  180. package/crates/team-agent-core/Cargo.toml +0 -12
  181. package/crates/team-agent-core/src/lib.rs +0 -332
  182. package/crates/team-agent-core/src/main.rs +0 -152
  183. package/pyproject.toml +0 -18
  184. package/scripts/install.py +0 -88
  185. package/scripts/run_regression_tests.py +0 -83
  186. package/src/team_agent/__init__.py +0 -3
  187. package/src/team_agent/__main__.py +0 -5
  188. package/src/team_agent/_legacy_pane_discovery.py +0 -186
  189. package/src/team_agent/abnormal_track.py +0 -253
  190. package/src/team_agent/approvals/__init__.py +0 -65
  191. package/src/team_agent/approvals/constants.py +0 -6
  192. package/src/team_agent/approvals/parsing.py +0 -176
  193. package/src/team_agent/approvals/runtime_prompts.py +0 -171
  194. package/src/team_agent/approvals/status.py +0 -176
  195. package/src/team_agent/cli/__init__.py +0 -137
  196. package/src/team_agent/cli/commands.py +0 -481
  197. package/src/team_agent/cli/e2e.py +0 -202
  198. package/src/team_agent/cli/helpers.py +0 -226
  199. package/src/team_agent/cli/parser.py +0 -540
  200. package/src/team_agent/compiler.py +0 -334
  201. package/src/team_agent/coordinator/__init__.py +0 -53
  202. package/src/team_agent/coordinator/__main__.py +0 -119
  203. package/src/team_agent/coordinator/lifecycle.py +0 -411
  204. package/src/team_agent/coordinator/metadata.py +0 -61
  205. package/src/team_agent/coordinator/paths.py +0 -17
  206. package/src/team_agent/diagnose/__init__.py +0 -48
  207. package/src/team_agent/diagnose/checks.py +0 -101
  208. package/src/team_agent/diagnose/comms.py +0 -213
  209. package/src/team_agent/diagnose/health.py +0 -241
  210. package/src/team_agent/diagnose/orphan_cleanup.py +0 -364
  211. package/src/team_agent/diagnose/preflight.py +0 -194
  212. package/src/team_agent/diagnose/quick_start.py +0 -324
  213. package/src/team_agent/display/__init__.py +0 -92
  214. package/src/team_agent/display/adaptive.py +0 -511
  215. package/src/team_agent/display/backend.py +0 -46
  216. package/src/team_agent/display/close.py +0 -154
  217. package/src/team_agent/display/ghostty.py +0 -77
  218. package/src/team_agent/display/rebuild.py +0 -102
  219. package/src/team_agent/display/tiling.py +0 -156
  220. package/src/team_agent/display/worker_window.py +0 -114
  221. package/src/team_agent/display/workspace.py +0 -382
  222. package/src/team_agent/errors.py +0 -10
  223. package/src/team_agent/events.py +0 -84
  224. package/src/team_agent/fake_worker.py +0 -80
  225. package/src/team_agent/idle_predicate.py +0 -218
  226. package/src/team_agent/idle_takeover.py +0 -59
  227. package/src/team_agent/idle_takeover_wiring.py +0 -114
  228. package/src/team_agent/launch/__init__.py +0 -41
  229. package/src/team_agent/launch/bootstrap.py +0 -85
  230. package/src/team_agent/launch/config.py +0 -106
  231. package/src/team_agent/launch/core.py +0 -301
  232. package/src/team_agent/launch/requirements.py +0 -57
  233. package/src/team_agent/leader/__init__.py +0 -926
  234. package/src/team_agent/leader_binding.py +0 -183
  235. package/src/team_agent/lifecycle/__init__.py +0 -5
  236. package/src/team_agent/lifecycle/agents.py +0 -278
  237. package/src/team_agent/lifecycle/operations.py +0 -411
  238. package/src/team_agent/lifecycle/paste_buffer_hygiene.py +0 -39
  239. package/src/team_agent/lifecycle/start.py +0 -363
  240. package/src/team_agent/mcp_server/__init__.py +0 -42
  241. package/src/team_agent/mcp_server/__main__.py +0 -7
  242. package/src/team_agent/mcp_server/contracts.py +0 -148
  243. package/src/team_agent/mcp_server/normalize.py +0 -257
  244. package/src/team_agent/mcp_server/server.py +0 -150
  245. package/src/team_agent/mcp_server/tools.py +0 -352
  246. package/src/team_agent/message_store/__init__.py +0 -23
  247. package/src/team_agent/message_store/agent_health.py +0 -113
  248. package/src/team_agent/message_store/core.py +0 -497
  249. package/src/team_agent/message_store/leader_notification_log.py +0 -198
  250. package/src/team_agent/message_store/result_watchers.py +0 -251
  251. package/src/team_agent/message_store/schema.py +0 -308
  252. package/src/team_agent/message_store/schema_migration.py +0 -448
  253. package/src/team_agent/messaging/__init__.py +0 -1
  254. package/src/team_agent/messaging/activity_detector.py +0 -262
  255. package/src/team_agent/messaging/delivery.py +0 -504
  256. package/src/team_agent/messaging/deps.py +0 -247
  257. package/src/team_agent/messaging/idle_alerts.py +0 -423
  258. package/src/team_agent/messaging/internal_delivery.py +0 -46
  259. package/src/team_agent/messaging/leader.py +0 -497
  260. package/src/team_agent/messaging/leader_api_errors.py +0 -216
  261. package/src/team_agent/messaging/leader_panes.py +0 -673
  262. package/src/team_agent/messaging/owner_bypass.py +0 -29
  263. package/src/team_agent/messaging/result_delivery.py +0 -539
  264. package/src/team_agent/messaging/results.py +0 -447
  265. package/src/team_agent/messaging/scheduler.py +0 -450
  266. package/src/team_agent/messaging/send.py +0 -532
  267. package/src/team_agent/messaging/session_drift.py +0 -94
  268. package/src/team_agent/messaging/tmux_io.py +0 -506
  269. package/src/team_agent/messaging/tmux_prompt.py +0 -338
  270. package/src/team_agent/messaging/trust_auto_answer.py +0 -52
  271. package/src/team_agent/orchestrator/__init__.py +0 -376
  272. package/src/team_agent/orchestrator/plan.py +0 -122
  273. package/src/team_agent/orchestrator/state.py +0 -128
  274. package/src/team_agent/paths.py +0 -45
  275. package/src/team_agent/permissions.py +0 -123
  276. package/src/team_agent/profiles/__init__.py +0 -82
  277. package/src/team_agent/profiles/constants.py +0 -19
  278. package/src/team_agent/profiles/core.py +0 -407
  279. package/src/team_agent/profiles/helpers.py +0 -69
  280. package/src/team_agent/profiles/provider_env.py +0 -188
  281. package/src/team_agent/profiles/smoke.py +0 -201
  282. package/src/team_agent/provider_cli/__init__.py +0 -43
  283. package/src/team_agent/provider_cli/adapter.py +0 -172
  284. package/src/team_agent/provider_cli/base.py +0 -48
  285. package/src/team_agent/provider_cli/claude.py +0 -503
  286. package/src/team_agent/provider_cli/codex.py +0 -336
  287. package/src/team_agent/provider_cli/copilot.py +0 -8
  288. package/src/team_agent/provider_cli/fake.py +0 -39
  289. package/src/team_agent/provider_cli/gemini.py +0 -95
  290. package/src/team_agent/provider_cli/opencode.py +0 -8
  291. package/src/team_agent/provider_cli/prompt.py +0 -62
  292. package/src/team_agent/provider_cli/registry.py +0 -18
  293. package/src/team_agent/provider_cli/unsupported.py +0 -32
  294. package/src/team_agent/provider_state/README.md +0 -78
  295. package/src/team_agent/provider_state/__init__.py +0 -91
  296. package/src/team_agent/provider_state/claude.py +0 -86
  297. package/src/team_agent/provider_state/codex.py +0 -84
  298. package/src/team_agent/provider_state/common.py +0 -207
  299. package/src/team_agent/provider_state/registry.py +0 -118
  300. package/src/team_agent/providers.py +0 -163
  301. package/src/team_agent/quality_gates.py +0 -104
  302. package/src/team_agent/restart/__init__.py +0 -34
  303. package/src/team_agent/restart/orchestration.py +0 -554
  304. package/src/team_agent/restart/selection.py +0 -89
  305. package/src/team_agent/restart/snapshot.py +0 -70
  306. package/src/team_agent/routing.py +0 -84
  307. package/src/team_agent/runtime.py +0 -1243
  308. package/src/team_agent/rust_core.py +0 -327
  309. package/src/team_agent/sessions/__init__.py +0 -25
  310. package/src/team_agent/sessions/capture.py +0 -144
  311. package/src/team_agent/sessions/inventory.py +0 -44
  312. package/src/team_agent/sessions/resume.py +0 -135
  313. package/src/team_agent/simple_yaml.py +0 -236
  314. package/src/team_agent/spec.py +0 -370
  315. package/src/team_agent/state.py +0 -693
  316. package/src/team_agent/status/__init__.py +0 -63
  317. package/src/team_agent/status/approvals.py +0 -52
  318. package/src/team_agent/status/compact.py +0 -158
  319. package/src/team_agent/status/constants.py +0 -18
  320. package/src/team_agent/status/inbox.py +0 -58
  321. package/src/team_agent/status/peek.py +0 -117
  322. package/src/team_agent/status/queries.py +0 -199
  323. package/src/team_agent/task_graph.py +0 -80
  324. package/src/team_agent/terminal.py +0 -57
  325. package/src/team_agent/wake.py +0 -58
  326. package/src/team_agent/watch/__init__.py +0 -145
@@ -1,63 +0,0 @@
1
- from __future__ import annotations
2
-
3
- from team_agent.status.approvals import approvals, format_approvals
4
- from team_agent.status.compact import (
5
- compact_agent_state,
6
- compact_event,
7
- compact_mapping,
8
- compact_status,
9
- compact_task,
10
- compact_value,
11
- )
12
- from team_agent.status.constants import (
13
- APPROVAL_SCAN_LINES,
14
- PEEK_MAX_LINES,
15
- PEEK_MAX_MATCHES,
16
- PEEK_SEARCH_SCAN_LINES,
17
- PENDING_DELIVERY_STATUSES,
18
- STATUS_EVENT_LIMIT,
19
- STATUS_TEXT_LIMIT,
20
- )
21
- from team_agent.status.inbox import format_inbox, inbox
22
- from team_agent.status.peek import (
23
- format_search_matches,
24
- peek,
25
- search_lines,
26
- validate_line_count,
27
- )
28
- from team_agent.status.queries import (
29
- format_status,
30
- latest_result_summaries,
31
- queued_message_statuses,
32
- result_summary_from_row,
33
- status,
34
- )
35
-
36
- __all__ = [
37
- "APPROVAL_SCAN_LINES",
38
- "PEEK_MAX_LINES",
39
- "PEEK_MAX_MATCHES",
40
- "PEEK_SEARCH_SCAN_LINES",
41
- "PENDING_DELIVERY_STATUSES",
42
- "STATUS_EVENT_LIMIT",
43
- "STATUS_TEXT_LIMIT",
44
- "approvals",
45
- "compact_agent_state",
46
- "compact_event",
47
- "compact_mapping",
48
- "compact_status",
49
- "compact_task",
50
- "compact_value",
51
- "format_approvals",
52
- "format_inbox",
53
- "format_search_matches",
54
- "format_status",
55
- "inbox",
56
- "latest_result_summaries",
57
- "peek",
58
- "queued_message_statuses",
59
- "result_summary_from_row",
60
- "search_lines",
61
- "status",
62
- "validate_line_count",
63
- ]
@@ -1,52 +0,0 @@
1
- from __future__ import annotations
2
-
3
- from pathlib import Path
4
- from typing import Any
5
-
6
- from team_agent.state import load_runtime_state
7
- from team_agent.status.constants import APPROVAL_SCAN_LINES
8
-
9
-
10
- def approvals(workspace: Path, agent_id: str | None = None) -> dict[str, Any]:
11
- from team_agent.runtime import RuntimeError, _extract_approval_prompt, _tmux_window_exists, run_cmd
12
- state = load_runtime_state(workspace)
13
- session_name = state.get("session_name")
14
- approvals_found: list[dict[str, Any]] = []
15
- agents = state.get("agents", {})
16
- target_ids = [agent_id] if agent_id else sorted(agents)
17
- for target_id in target_ids:
18
- agent = agents.get(target_id)
19
- if not agent:
20
- raise RuntimeError(f"unknown agent id: {target_id}")
21
- window = agent.get("window", target_id)
22
- if not session_name or not _tmux_window_exists(session_name, window):
23
- continue
24
- proc = run_cmd(["tmux", "capture-pane", "-p", "-S", f"-{APPROVAL_SCAN_LINES}", "-t", f"{session_name}:{window}"], timeout=5)
25
- if proc.returncode != 0:
26
- continue
27
- prompt = _extract_approval_prompt(target_id, proc.stdout)
28
- if prompt:
29
- approvals_found.append(prompt)
30
- return {
31
- "ok": True,
32
- "waiting": bool(approvals_found),
33
- "waiting_count": len(approvals_found),
34
- "approvals": approvals_found,
35
- "scan": {"mode": "tail", "lines": APPROVAL_SCAN_LINES, "raw_output": False},
36
- }
37
-
38
-
39
- def format_approvals(workspace: Path, agent_id: str | None = None) -> str:
40
- result = approvals(workspace, agent_id=agent_id)
41
- if not result["approvals"]:
42
- return "No pending approvals."
43
- lines: list[str] = []
44
- for item in result["approvals"]:
45
- detail = item.get("tool") or item.get("command") or item.get("kind")
46
- lines.append(f"{item['agent_id']}: {item['state']} {item['kind']} {detail}".rstrip())
47
- if item.get("prompt"):
48
- lines.append(f" prompt: {item['prompt']}")
49
- if item.get("choices"):
50
- lines.append(" choices: " + "; ".join(item["choices"]))
51
- lines.append(" raw terminal output omitted; use debug-only peek with --search/--tail/--head if the user explicitly asks.")
52
- return "\n".join(lines)
@@ -1,158 +0,0 @@
1
- from __future__ import annotations
2
-
3
- from typing import Any
4
-
5
- from team_agent.status.constants import STATUS_EVENT_LIMIT, STATUS_TEXT_LIMIT
6
-
7
-
8
- def compact_status(data: dict[str, Any]) -> dict[str, Any]:
9
- return {
10
- "team": data.get("team"),
11
- "session_name": data.get("session_name"),
12
- "tmux_session_present": data.get("tmux_session_present"),
13
- "leader_receiver": compact_mapping(
14
- data.get("leader_receiver", {}),
15
- {
16
- "status",
17
- "provider",
18
- "mode",
19
- "session_name",
20
- "window_name",
21
- "pane_id",
22
- "pane_current_command",
23
- },
24
- ),
25
- "agents": {
26
- agent_id: compact_agent_state(agent_id, agent)
27
- for agent_id, agent in (data.get("agents") or {}).items()
28
- },
29
- "agent_health": data.get("agent_health", {}),
30
- "tasks": [compact_task(task) for task in data.get("tasks", [])],
31
- "messages": data.get("messages", {}),
32
- "queued_messages": data.get("queued_messages", [])[:8],
33
- "results": data.get("results", {}),
34
- "latest_results": data.get("latest_results", [])[:5],
35
- "coordinator": compact_mapping(data.get("coordinator", {}), {"status", "pid", "metadata_ok", "schema_ok"}),
36
- "last_events": [compact_event(event) for event in data.get("last_events", [])[-STATUS_EVENT_LIMIT:]],
37
- }
38
-
39
-
40
- def compact_agent_state(agent_id: str, agent: dict[str, Any]) -> dict[str, Any]:
41
- display = agent.get("display") or {}
42
- result = compact_mapping(
43
- agent,
44
- {
45
- "agent_id",
46
- "status",
47
- "provider",
48
- "model",
49
- "tmux_window_present",
50
- "session_id",
51
- "captured_via",
52
- "attribution_confidence",
53
- },
54
- )
55
- result.setdefault("agent_id", agent_id)
56
- if display:
57
- result["display"] = compact_mapping(
58
- display,
59
- {
60
- "backend",
61
- "status",
62
- "workspace_window",
63
- "pane_id",
64
- "pid",
65
- "pids",
66
- "reason",
67
- },
68
- )
69
- return result
70
-
71
-
72
- def compact_task(task: dict[str, Any]) -> dict[str, Any]:
73
- return compact_mapping(
74
- task,
75
- {
76
- "id",
77
- "title",
78
- "status",
79
- "assignee",
80
- "type",
81
- "risk",
82
- "accepted_result_id",
83
- "last_result_summary",
84
- },
85
- )
86
-
87
-
88
- def compact_event(event: dict[str, Any]) -> dict[str, Any]:
89
- skipped = {"command", "payload", "launch_args", "content", "prompt", "developer_instructions"}
90
- kept = {
91
- "event",
92
- "ts",
93
- "agent_id",
94
- "task_id",
95
- "message_id",
96
- "result_id",
97
- "status",
98
- "ok",
99
- "reason",
100
- "error",
101
- "session",
102
- "window",
103
- "target",
104
- "backend",
105
- "workspace_window",
106
- "pane_id",
107
- "restart_mode",
108
- "provider",
109
- "delivery_status",
110
- "warning",
111
- "collected",
112
- "notified",
113
- "lock",
114
- "waited_sec",
115
- "once",
116
- "pid",
117
- }
118
- result: dict[str, Any] = {}
119
- for key, value in event.items():
120
- if key in skipped or key not in kept | {"agents", "coordinator"}:
121
- continue
122
- if key == "agents" and isinstance(value, list):
123
- result["agent_count"] = len(value)
124
- result["agents"] = [
125
- compact_mapping(item, {"agent_id", "restart_mode", "session_id"})
126
- for item in value[:8]
127
- if isinstance(item, dict)
128
- ]
129
- continue
130
- result[key] = compact_value(value)
131
- return result
132
-
133
-
134
- def compact_mapping(source: Any, keys: set[str]) -> dict[str, Any]:
135
- if not isinstance(source, dict):
136
- return {}
137
- return {key: compact_value(source[key]) for key in keys if key in source}
138
-
139
-
140
- def compact_value(value: Any) -> Any:
141
- if isinstance(value, str):
142
- return value if len(value) <= STATUS_TEXT_LIMIT else value[: STATUS_TEXT_LIMIT - 1] + "…"
143
- if isinstance(value, (int, float, bool)) or value is None:
144
- return value
145
- if isinstance(value, list):
146
- if all(isinstance(item, (str, int, float, bool)) or item is None for item in value):
147
- compact = [compact_value(item) for item in value[:8]]
148
- if len(value) > 8:
149
- compact.append(f"... {len(value) - 8} more")
150
- return compact
151
- return f"{len(value)} item(s)"
152
- if isinstance(value, dict):
153
- return {
154
- key: compact_value(item)
155
- for key, item in value.items()
156
- if key not in {"command", "payload", "launch_args", "content", "prompt", "developer_instructions"}
157
- }
158
- return str(value)
@@ -1,18 +0,0 @@
1
- from __future__ import annotations
2
-
3
-
4
- STATUS_TEXT_LIMIT = 240
5
- STATUS_EVENT_LIMIT = 3
6
- PEEK_MAX_LINES = 80
7
- PEEK_SEARCH_SCAN_LINES = 300
8
- PEEK_MAX_MATCHES = 5
9
- APPROVAL_SCAN_LINES = 120
10
-
11
- PENDING_DELIVERY_STATUSES = {
12
- "pending",
13
- "accepted",
14
- "queued_until_idle",
15
- "queued_until_start",
16
- "queued_stopped",
17
- "queued_pane_missing",
18
- }
@@ -1,58 +0,0 @@
1
- from __future__ import annotations
2
-
3
- from datetime import datetime, timezone
4
- from pathlib import Path
5
- from typing import Any
6
-
7
- from team_agent.message_store import MessageStore
8
-
9
-
10
- def _parse_since(since: str | None) -> datetime | None:
11
- if not since:
12
- return None
13
- try:
14
- dt = datetime.fromisoformat(since.replace("Z", "+00:00"))
15
- except (ValueError, AttributeError):
16
- return None
17
- if dt.tzinfo is None:
18
- dt = dt.replace(tzinfo=timezone.utc)
19
- return dt
20
-
21
-
22
- def _filter_since(rows: list[dict[str, Any]], since: str | None) -> list[dict[str, Any]]:
23
- cutoff = _parse_since(since)
24
- if cutoff is None:
25
- return rows
26
- filtered: list[dict[str, Any]] = []
27
- for row in rows:
28
- ts_raw = str(row.get("created_at") or "")
29
- ts = _parse_since(ts_raw)
30
- if ts and ts >= cutoff:
31
- filtered.append(row)
32
- return filtered
33
-
34
-
35
- def inbox(workspace: Path, agent_id: str, limit: int = 20, since: str | None = None) -> dict[str, Any]:
36
- rows = MessageStore(workspace).inbox(agent_id, limit=limit)
37
- rows = _filter_since(rows, since)
38
- return {"ok": True, "agent_id": agent_id, "messages": rows, "since": since}
39
-
40
-
41
- def format_inbox(workspace: Path, agent_id: str, limit: int = 20, since: str | None = None) -> str:
42
- store = MessageStore(workspace)
43
- rows = store.inbox(agent_id, limit=limit)
44
- rows = _filter_since(rows, since)
45
- result_counts = store.result_counts()
46
- note = "final results are not in inbox; use team-agent collect"
47
- if result_counts.get("uncollected", 0):
48
- note += f" ({result_counts['uncollected']} uncollected result(s) pending)"
49
- if not rows:
50
- if since:
51
- return f"{agent_id}: no messages since {since}\n{note}"
52
- return f"{agent_id}: no messages\n{note}"
53
- lines = [
54
- f"{row['created_at']} {row['sender']} -> {row['recipient']} {row['status']}: {row['content']}"
55
- for row in rows
56
- ]
57
- lines.append(note)
58
- return "\n".join(lines)
@@ -1,117 +0,0 @@
1
- from __future__ import annotations
2
-
3
- from pathlib import Path
4
- from typing import Any
5
-
6
- from team_agent.state import load_runtime_state
7
- from team_agent.status.constants import (
8
- PEEK_MAX_LINES,
9
- PEEK_MAX_MATCHES,
10
- PEEK_SEARCH_SCAN_LINES,
11
- )
12
-
13
-
14
- def peek(
15
- workspace: Path,
16
- agent_id: str,
17
- *,
18
- head: int | None = None,
19
- tail: int | None = None,
20
- search: str | None = None,
21
- context: int = 3,
22
- ) -> dict[str, Any]:
23
- from team_agent.runtime import RuntimeError, _tmux_window_exists, run_cmd
24
- modes = [head is not None, tail is not None, search is not None]
25
- if sum(modes) != 1:
26
- raise RuntimeError("peek requires exactly one of --head, --tail, or --search")
27
- if head is not None:
28
- validate_line_count("--head", head)
29
- if tail is not None:
30
- validate_line_count("--tail", tail)
31
- if search is not None and not search.strip():
32
- raise RuntimeError("--search must not be empty")
33
- if context < 0 or context > 10:
34
- raise RuntimeError("--context must be between 0 and 10")
35
- state = load_runtime_state(workspace)
36
- agent = state.get("agents", {}).get(agent_id)
37
- if not agent:
38
- raise RuntimeError(f"unknown agent id: {agent_id}")
39
- session_name = state.get("session_name")
40
- window = agent.get("window", agent_id)
41
- if not session_name or not _tmux_window_exists(session_name, window):
42
- raise RuntimeError(f"agent terminal is not available: {agent_id}")
43
- scan_lines = tail or PEEK_SEARCH_SCAN_LINES
44
- proc = run_cmd(["tmux", "capture-pane", "-p", "-S", f"-{scan_lines}", "-t", f"{session_name}:{window}"], timeout=5)
45
- if proc.returncode != 0:
46
- raise RuntimeError(proc.stderr.strip() or f"capture failed for {agent_id}")
47
- captured = proc.stdout.splitlines()
48
- if head is not None:
49
- selected = captured[:head]
50
- return {
51
- "ok": True,
52
- "agent_id": agent_id,
53
- "mode": "head",
54
- "lines": head,
55
- "scanned_lines": scan_lines,
56
- "text": "\n".join(selected),
57
- }
58
- if tail is not None:
59
- return {
60
- "ok": True,
61
- "agent_id": agent_id,
62
- "mode": "tail",
63
- "lines": tail,
64
- "scanned_lines": scan_lines,
65
- "text": "\n".join(captured[-tail:]),
66
- }
67
- assert search is not None
68
- matches = search_lines(captured, search, context)
69
- return {
70
- "ok": True,
71
- "agent_id": agent_id,
72
- "mode": "search",
73
- "search": search,
74
- "context": context,
75
- "scanned_lines": scan_lines,
76
- "matches": matches,
77
- "truncated": len(matches) >= PEEK_MAX_MATCHES,
78
- "text": format_search_matches(matches),
79
- }
80
-
81
-
82
- def validate_line_count(flag: str, value: int) -> None:
83
- from team_agent.runtime import RuntimeError
84
- if value < 1 or value > PEEK_MAX_LINES:
85
- raise RuntimeError(f"{flag} must be between 1 and {PEEK_MAX_LINES}")
86
-
87
-
88
- def search_lines(lines: list[str], needle: str, context: int) -> list[dict[str, Any]]:
89
- needle_lower = needle.lower()
90
- matches: list[dict[str, Any]] = []
91
- used_ranges: list[tuple[int, int]] = []
92
- for index, line in enumerate(lines):
93
- if needle_lower not in line.lower():
94
- continue
95
- start = max(0, index - context)
96
- end = min(len(lines), index + context + 1)
97
- if used_ranges and start <= used_ranges[-1][1]:
98
- previous = matches[-1]
99
- previous["lines"] = lines[previous["start_line"] - 1 : end]
100
- previous["end_line"] = end
101
- used_ranges[-1] = (previous["start_line"] - 1, end)
102
- else:
103
- matches.append({"line": index + 1, "start_line": start + 1, "end_line": end, "lines": lines[start:end]})
104
- used_ranges.append((start, end))
105
- if len(matches) >= PEEK_MAX_MATCHES:
106
- break
107
- return matches
108
-
109
-
110
- def format_search_matches(matches: list[dict[str, Any]]) -> str:
111
- if not matches:
112
- return "no matches"
113
- blocks: list[str] = []
114
- for match in matches:
115
- blocks.append(f"match line {match['line']} ({match['start_line']}-{match['end_line']}):")
116
- blocks.extend(str(line) for line in match["lines"])
117
- return "\n".join(blocks)
@@ -1,199 +0,0 @@
1
- from __future__ import annotations
2
-
3
- import json
4
- from datetime import datetime
5
- from pathlib import Path
6
- from typing import Any
7
-
8
- from team_agent.events import EventLog
9
- from team_agent.message_store import MessageStore
10
- from team_agent.state import load_runtime_state, save_runtime_state
11
- from team_agent.status.compact import compact_status
12
- from team_agent.status.constants import PENDING_DELIVERY_STATUSES
13
-
14
-
15
- def _interacted_marker(first_send_at: Any) -> str:
16
- """C3 (cr verdict, 2026-05-27): render the persisted first_send_at as a
17
- user-visible status field. Valid ISO 8601 UTC strings pass through; any
18
- other shape (None, empty string, 0, False, corrupt garbage) renders as
19
- the literal "never" so the operator sees a consistent classification
20
- instead of leaking raw garbage into status output. Restart enforces
21
- strict typing separately (corrupt values fail the operation); status is
22
- a read-only surface and tolerantly degrades to "never" rather than
23
- failing the status command."""
24
- if isinstance(first_send_at, str) and first_send_at:
25
- try:
26
- datetime.fromisoformat(first_send_at)
27
- except (ValueError, TypeError):
28
- return "never"
29
- return first_send_at
30
- return "never"
31
-
32
-
33
- def status(workspace: Path, as_json: bool = False, *, compact: bool = False) -> dict[str, Any]:
34
- from team_agent.runtime import (
35
- _capture_missing_sessions,
36
- _handle_provider_startup_prompts,
37
- _refresh_agent_runtime_statuses,
38
- _sync_agent_health,
39
- _tmux_session_exists,
40
- coordinator_health,
41
- )
42
- _ = as_json
43
- state = load_runtime_state(workspace)
44
- store = MessageStore(workspace)
45
- event_log = EventLog(workspace)
46
- _capture_missing_sessions(workspace, state, event_log, timeout_s=0.0, log_miss=False)
47
- _refresh_agent_runtime_statuses(workspace, state, event_log)
48
- _handle_provider_startup_prompts(workspace, state, event_log)
49
- _sync_agent_health(workspace, state, store)
50
- save_runtime_state(workspace, state)
51
- session_name = state.get("session_name")
52
- tmux_exists = _tmux_session_exists(session_name) if session_name else False
53
- # C3 (cr verdict): enrich each worker entry with an explicit `interacted`
54
- # field derived from the persisted first_send_at. The original entry
55
- # passes through unchanged so any pre-existing field (including raw
56
- # first_send_at) stays visible.
57
- enriched_agents: dict[str, Any] = {}
58
- for aid, raw in (state.get("agents") or {}).items():
59
- if isinstance(raw, dict):
60
- entry = dict(raw)
61
- entry["interacted"] = _interacted_marker(raw.get("first_send_at"))
62
- else:
63
- entry = raw
64
- enriched_agents[aid] = entry
65
- result = {
66
- "team": state.get("leader", {}).get("id", "leader"),
67
- "session_name": session_name,
68
- "tmux_session_present": tmux_exists,
69
- "leader_receiver": state.get("leader_receiver", {}),
70
- "agents": enriched_agents,
71
- "agent_health": store.agent_health(),
72
- "tasks": state.get("tasks", []),
73
- "messages": store.message_counts(),
74
- "queued_messages": queued_message_statuses(store.messages()),
75
- "results": store.result_counts(),
76
- "latest_results": latest_result_summaries(store),
77
- "coordinator": coordinator_health(workspace),
78
- "last_events": EventLog(workspace).tail(10),
79
- }
80
- return compact_status(result) if compact else result
81
-
82
-
83
- def latest_result_summaries(store: MessageStore, limit: int = 5) -> list[dict[str, Any]]:
84
- summaries: list[dict[str, Any]] = []
85
- for row in store.latest_results(limit=limit):
86
- summary = result_summary_from_row(row)
87
- if summary:
88
- summaries.append(summary)
89
- return summaries
90
-
91
-
92
- def result_summary_from_row(row: dict[str, Any]) -> dict[str, Any] | None:
93
- try:
94
- envelope = json.loads(row["envelope"]) if isinstance(row.get("envelope"), str) else row.get("envelope")
95
- except (TypeError, json.JSONDecodeError):
96
- return None
97
- if not isinstance(envelope, dict):
98
- return None
99
- return {
100
- "result_id": row.get("result_id"),
101
- "task_id": envelope.get("task_id") or row.get("task_id"),
102
- "agent_id": envelope.get("agent_id") or row.get("agent_id"),
103
- "status": envelope.get("status") or row.get("status"),
104
- "summary": envelope.get("summary"),
105
- "created_at": row.get("created_at"),
106
- }
107
-
108
-
109
- def queued_message_statuses(messages: list[dict[str, Any]]) -> list[dict[str, Any]]:
110
- from team_agent.runtime import _age_text
111
- visible_statuses = PENDING_DELIVERY_STATUSES | {"target_resolved", "delivery_blocked", "injected_unverified"}
112
- queued: list[dict[str, Any]] = []
113
- for row in messages:
114
- if row.get("status") not in visible_statuses:
115
- continue
116
- queued.append(
117
- {
118
- "message_id": row.get("message_id"),
119
- "recipient": row.get("recipient"),
120
- "sender": row.get("sender"),
121
- "status": row.get("status"),
122
- "reason": row.get("error"),
123
- "age": _age_text(row.get("created_at")),
124
- "attempts": row.get("delivery_attempts") or 0,
125
- }
126
- )
127
- return queued
128
-
129
-
130
- def format_status(workspace: Path, agent_id: str | None = None) -> str:
131
- from team_agent.runtime import RuntimeError, _agent_health_status, _age_text, _current_task_for_agent
132
- data = status(workspace, as_json=True)
133
- health = data.get("agent_health", {})
134
- tasks = data.get("tasks", [])
135
- if agent_id:
136
- if agent_id not in data.get("agents", {}) and agent_id not in health:
137
- raise RuntimeError(f"unknown agent id: {agent_id}")
138
- agent = data.get("agents", {}).get(agent_id, {})
139
- row = health.get(agent_id, {})
140
- task_id = _current_task_for_agent(tasks, agent_id) or "-"
141
- inbox_rows = MessageStore(workspace).inbox(agent_id, limit=3)
142
- lines = [
143
- f"{agent_id} {row.get('status', _agent_health_status(agent))}",
144
- f" provider: {agent.get('provider', '-')}",
145
- f" model: {agent.get('model', '-')}",
146
- f" profile: {agent.get('profile', '-')}",
147
- f" session_id: {agent.get('session_id') or '-'}",
148
- f" captured_via: {agent.get('captured_via') or '-'}",
149
- f" attribution_confidence: {agent.get('attribution_confidence') or '-'}",
150
- f" task: {task_id}",
151
- f" handoff: {agent.get('handoff_path', '-')}",
152
- " recent messages:",
153
- ]
154
- if inbox_rows:
155
- for item in inbox_rows:
156
- lines.append(
157
- f" {item['created_at']} {item['sender']} -> {item['recipient']} "
158
- f"{item['status']}: {item['content'][:120]}"
159
- )
160
- else:
161
- lines.append(" none")
162
- return "\n".join(lines)
163
-
164
- agents = data.get("agents", {})
165
- state_name = "up" if data.get("tmux_session_present") else "down"
166
- results = data.get("results", {})
167
- lines = [
168
- f"team {data.get('session_name') or '-'} ({state_name})",
169
- (
170
- "results "
171
- f"total {results.get('total', 0)} "
172
- f"uncollected {results.get('uncollected', 0)} "
173
- f"collected {results.get('collected', 0)} "
174
- f"invalid {results.get('invalid', 0)}"
175
- ),
176
- ]
177
- if results.get("uncollected", 0):
178
- lines.append(" final result pending in result store; run team-agent collect")
179
- queued_messages = data.get("queued_messages") or []
180
- if queued_messages:
181
- lines.append("queued messages")
182
- for item in queued_messages[:8]:
183
- reason = item.get("reason") or "-"
184
- lines.append(
185
- f" {item.get('message_id')} -> {item.get('recipient')} "
186
- f"{item.get('status')} age {item.get('age')} attempts {item.get('attempts')} reason {reason}"
187
- )
188
- for aid in sorted(agents):
189
- agent = agents[aid]
190
- row = health.get(aid, {})
191
- status_value = row.get("status") or _agent_health_status(agent)
192
- task_id = _current_task_for_agent(tasks, aid) or "-"
193
- context = row.get("context_usage_pct")
194
- context_text = f"ctx {context}%" if context is not None else "ctx -"
195
- last = _age_text(row.get("last_output_at"))
196
- session_text = f"sid {agent.get('session_id') or '-'}"
197
- capture_text = f"via {agent.get('captured_via') or '-'} {agent.get('attribution_confidence') or '-'}"
198
- lines.append(f" {aid} {status_value} {task_id} {context_text} last {last} {session_text} {capture_text}")
199
- return "\n".join(lines)