@team-agent/installer 0.2.10 → 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 -83
  203. package/src/team_agent/coordinator/lifecycle.py +0 -363
  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 -200
  226. package/src/team_agent/idle_takeover.py +0 -59
  227. package/src/team_agent/idle_takeover_wiring.py +0 -111
  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 -254
  255. package/src/team_agent/messaging/delivery.py +0 -473
  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 -457
  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 -86
  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 -1239
  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 -143
  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 -602
  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,363 +0,0 @@
1
- from __future__ import annotations
2
-
3
- import os
4
- import signal
5
- import subprocess
6
- import sys
7
- from pathlib import Path
8
- from typing import Any
9
-
10
- from team_agent.coordinator.metadata import (
11
- COORDINATOR_PROTOCOL_VERSION,
12
- coordinator_metadata_ok,
13
- pid_is_running,
14
- read_coordinator_metadata,
15
- write_coordinator_metadata,
16
- )
17
- from team_agent.coordinator.paths import (
18
- coordinator_log_path,
19
- coordinator_meta_path,
20
- coordinator_pid_path,
21
- )
22
- from team_agent.events import EventLog
23
- from team_agent.message_store import MessageStore
24
-
25
-
26
- def coordinator_health(workspace: Path) -> dict[str, Any]:
27
- schema = message_store_schema_health(workspace)
28
- pid_path = coordinator_pid_path(workspace)
29
- if not pid_path.exists():
30
- return {"ok": False, "status": "missing", "pid": None, "metadata": None, "metadata_ok": False, **schema}
31
- try:
32
- pid = int(pid_path.read_text(encoding="utf-8").strip())
33
- except ValueError:
34
- return {"ok": False, "status": "invalid_pid", "pid": None, "metadata": None, "metadata_ok": False, **schema}
35
- running = pid_is_running(pid)
36
- metadata = read_coordinator_metadata(workspace)
37
- metadata_ok = coordinator_metadata_ok(metadata, pid)
38
- ok = running and metadata_ok and bool(schema.get("schema_ok"))
39
- return {
40
- "ok": ok,
41
- "status": "running" if running else "stale",
42
- "pid": pid,
43
- "metadata": metadata,
44
- "metadata_ok": metadata_ok,
45
- **schema,
46
- }
47
-
48
-
49
- def start_coordinator(workspace: Path) -> dict[str, Any]:
50
- from team_agent.runtime import ensure_workspace_dirs
51
- ensure_workspace_dirs(workspace)
52
- health = coordinator_health(workspace)
53
- if health["ok"]:
54
- return {"ok": True, "pid": health["pid"], "status": "already_running", "log": str(coordinator_log_path(workspace))}
55
- if health["status"] == "running" and not health.get("metadata_ok"):
56
- EventLog(workspace).write(
57
- "coordinator.restart_incompatible",
58
- pid=health.get("pid"),
59
- metadata=health.get("metadata"),
60
- expected_protocol=COORDINATOR_PROTOCOL_VERSION,
61
- expected_schema=MessageStore.SCHEMA_VERSION,
62
- )
63
- stopped = stop_coordinator(workspace)
64
- if not stopped.get("ok"):
65
- EventLog(workspace).write(
66
- "coordinator.restart_incompatible_stop_failed",
67
- pid=health.get("pid"),
68
- stop_result=stopped,
69
- )
70
- return {
71
- "ok": False,
72
- "pid": health.get("pid"),
73
- "status": "restart_incompatible_stop_failed",
74
- "error": stopped.get("error") or stopped.get("status"),
75
- "stop_result": stopped,
76
- }
77
- if not health.get("schema_ok", False):
78
- EventLog(workspace).write(
79
- "coordinator.schema_incompatible",
80
- error=health.get("schema_error"),
81
- schema=health.get("schema"),
82
- reason=health.get("reason"),
83
- table=health.get("table"),
84
- missing_columns=health.get("missing_columns"),
85
- )
86
- return {
87
- "ok": False,
88
- "pid": None,
89
- "status": "schema_incompatible",
90
- "error": health.get("schema_error"),
91
- "schema": health.get("schema"),
92
- "action": health.get("action", _SCHEMA_ACTION_HINT),
93
- "reason": health.get("reason"),
94
- "table": health.get("table"),
95
- "expected_columns": health.get("expected_columns"),
96
- "actual_columns": health.get("actual_columns"),
97
- "missing_columns": health.get("missing_columns"),
98
- }
99
- if health["status"] in {"stale", "invalid_pid"}:
100
- coordinator_pid_path(workspace).unlink(missing_ok=True)
101
- coordinator_meta_path(workspace).unlink(missing_ok=True)
102
- log_path = coordinator_log_path(workspace)
103
- log_path.parent.mkdir(parents=True, exist_ok=True)
104
- env = dict(os.environ)
105
- repo_src = str(Path(__file__).resolve().parents[2])
106
- env["PYTHONPATH"] = repo_src + (os.pathsep + env["PYTHONPATH"] if env.get("PYTHONPATH") else "")
107
- log = log_path.open("a", encoding="utf-8")
108
- proc = subprocess.Popen(
109
- [sys.executable, "-m", "team_agent.coordinator", "--workspace", str(workspace)],
110
- cwd=str(workspace),
111
- stdin=subprocess.DEVNULL,
112
- stdout=log,
113
- stderr=log,
114
- env=env,
115
- start_new_session=True,
116
- )
117
- log.close()
118
- coordinator_pid_path(workspace).write_text(str(proc.pid), encoding="utf-8")
119
- write_coordinator_metadata(workspace, proc.pid, source="start")
120
- EventLog(workspace).write("coordinator.started", pid=proc.pid, log=str(log_path))
121
- return {"ok": True, "pid": proc.pid, "status": "started", "log": str(log_path)}
122
-
123
-
124
- _SCHEMA_EXPECTED_COLUMNS: dict[str, set[str]] = {}
125
- _SCHEMA_MIGRATABLE_COLUMNS: dict[str, set[str]] = {
126
- "messages": {"delivery_attempts", "owner_team_id"},
127
- "scheduled_events": {"owner_team_id"},
128
- "agent_health": {"owner_team_id"},
129
- "result_watchers": {"owner_team_id"},
130
- }
131
- _SCHEMA_ACTION_HINT = (
132
- "use team-agent advanced repair-state --schema to re-run column migrations; "
133
- "if that fails, back up .team/runtime/team.db, then delete it and rerun team-agent launch "
134
- "(in-flight messages will be lost)"
135
- )
136
-
137
-
138
- def _load_expected_schema_columns() -> dict[str, set[str]]:
139
- if _SCHEMA_EXPECTED_COLUMNS:
140
- return _SCHEMA_EXPECTED_COLUMNS
141
- from team_agent.message_store.schema import (
142
- AGENT_HEALTH_COLUMNS,
143
- DELIVERY_TOKEN_COLUMNS,
144
- MESSAGE_COLUMNS,
145
- PEER_ALLOWLIST_COLUMNS,
146
- RESULT_COLUMNS,
147
- RESULT_WATCHER_COLUMNS,
148
- SCHEDULED_EVENT_COLUMNS,
149
- )
150
- _SCHEMA_EXPECTED_COLUMNS.update(
151
- {
152
- "messages": set(MESSAGE_COLUMNS),
153
- "results": set(RESULT_COLUMNS),
154
- "scheduled_events": set(SCHEDULED_EVENT_COLUMNS),
155
- "delivery_tokens": set(DELIVERY_TOKEN_COLUMNS),
156
- "agent_health": set(AGENT_HEALTH_COLUMNS),
157
- "peer_allowlist": set(PEER_ALLOWLIST_COLUMNS),
158
- "result_watchers": set(RESULT_WATCHER_COLUMNS),
159
- }
160
- )
161
- return _SCHEMA_EXPECTED_COLUMNS
162
-
163
-
164
- def _diagnose_schema_mismatch(workspace: Path, *, ignore_migratable: bool = False) -> dict[str, Any] | None:
165
- import sqlite3
166
- from team_agent.paths import runtime_dir
167
- db_path = runtime_dir(workspace) / "team.db"
168
- if not db_path.exists():
169
- return None
170
- conn = sqlite3.connect(db_path)
171
- try:
172
- for table, expected in _load_expected_schema_columns().items():
173
- present = conn.execute(
174
- "select name from sqlite_master where type='table' and name=?",
175
- (table,),
176
- ).fetchone()
177
- if present is None:
178
- continue
179
- actual = {row[1] for row in conn.execute(f"pragma table_info({table})").fetchall()}
180
- missing = expected - actual
181
- if ignore_migratable:
182
- migratable = _SCHEMA_MIGRATABLE_COLUMNS.get(table, set())
183
- missing = missing - migratable
184
- if missing:
185
- return {
186
- "reason": "schema_mismatch",
187
- "table": table,
188
- "expected_columns": sorted(expected),
189
- "actual_columns": sorted(actual),
190
- "missing_columns": sorted(missing),
191
- }
192
- finally:
193
- conn.close()
194
- return None
195
-
196
-
197
- def message_store_schema_health(workspace: Path) -> dict[str, Any]:
198
- schema_version = {"message_store_schema_version": MessageStore.SCHEMA_VERSION}
199
- pre_mismatch = _diagnose_schema_mismatch(workspace, ignore_migratable=True)
200
- if pre_mismatch is not None:
201
- return {
202
- "schema_ok": False,
203
- "schema_error": (
204
- f"team.db table {pre_mismatch['table']} is missing required column(s): "
205
- + ", ".join(pre_mismatch["missing_columns"])
206
- ),
207
- "schema": schema_version,
208
- "action": _SCHEMA_ACTION_HINT,
209
- **pre_mismatch,
210
- }
211
- try:
212
- MessageStore(workspace)
213
- except Exception as exc:
214
- post_init_mismatch = _diagnose_schema_mismatch(workspace) or {}
215
- return {
216
- "schema_ok": False,
217
- "schema_error": str(exc),
218
- "schema": schema_version,
219
- "action": _SCHEMA_ACTION_HINT,
220
- **post_init_mismatch,
221
- }
222
- return {
223
- "schema_ok": True,
224
- "schema_error": None,
225
- "schema": schema_version,
226
- }
227
-
228
-
229
- def stop_coordinator(workspace: Path) -> dict[str, Any]:
230
- pid_path = coordinator_pid_path(workspace)
231
- if not pid_path.exists():
232
- return {"ok": True, "status": "missing"}
233
- try:
234
- pid = int(pid_path.read_text(encoding="utf-8").strip())
235
- except ValueError:
236
- pid_path.unlink(missing_ok=True)
237
- coordinator_meta_path(workspace).unlink(missing_ok=True)
238
- return {"ok": True, "status": "invalid_pid_removed"}
239
- if pid_is_running(pid):
240
- try:
241
- os.kill(pid, signal.SIGTERM)
242
- except OSError as exc:
243
- return {"ok": False, "status": "kill_failed", "pid": pid, "error": str(exc)}
244
- pid_path.unlink(missing_ok=True)
245
- coordinator_meta_path(workspace).unlink(missing_ok=True)
246
- EventLog(workspace).write("coordinator.stopped", pid=pid)
247
- return {"ok": True, "status": "stopped", "pid": pid}
248
-
249
-
250
- def coordinator_tick(workspace: Path) -> dict[str, Any]:
251
- from team_agent.runtime import (
252
- _capture_missing_sessions,
253
- _deliver_pending_messages,
254
- _detect_stuck_agents,
255
- _fire_due_scheduled_events,
256
- _handle_provider_runtime_prompts,
257
- _handle_provider_startup_prompts,
258
- _refresh_agent_runtime_statuses,
259
- _sync_agent_health,
260
- _tmux_session_exists,
261
- _collect_results_and_notify_watchers,
262
- )
263
- from team_agent.messaging.idle_alerts import (
264
- detect_cross_worker_deadlocks,
265
- )
266
- from team_agent.idle_predicate import evaluate_takeover_reminder
267
- from team_agent.idle_takeover_wiring import build_idle_nodes, push_idle_reminder, IDLE_DEBOUNCE_SECONDS
268
- import time as _time
269
- from team_agent.messaging.activity_detector import detect_compaction_degradation
270
- from team_agent.messaging.leader_api_errors import detect_leader_api_errors
271
- from team_agent.messaging.session_drift import detect_session_drift
272
- from team_agent.state import load_runtime_state, save_runtime_state
273
- state = load_runtime_state(workspace)
274
- event_log = EventLog(workspace)
275
- store = MessageStore(workspace)
276
- session_name = state.get("session_name")
277
- if session_name and not _tmux_session_exists(session_name):
278
- event_log.write("coordinator.session_missing", session=session_name)
279
- return {"ok": False, "stop": True, "reason": "tmux_session_missing"}
280
- _capture_missing_sessions(workspace, state, event_log, timeout_s=0.0, log_miss=False)
281
- _refresh_agent_runtime_statuses(workspace, state, event_log)
282
- _handle_provider_startup_prompts(workspace, state, event_log)
283
- _handle_provider_runtime_prompts(workspace, state, event_log)
284
- captures = _sync_agent_health(workspace, state, store) or {}
285
- delivered = _deliver_pending_messages(workspace, state, event_log)
286
- fired = _fire_due_scheduled_events(workspace, store, event_log)
287
- stuck = _detect_stuck_agents(workspace, state, store, event_log)
288
- # Gap 32: the take-over reminder is driven by file-fact turn-state via the
289
- # idle_takeover predicate (the legacy screen-scrape obligation path is retired).
290
- _coord_meta = state.setdefault("coordinator", {})
291
- idle_eval = evaluate_takeover_reminder(
292
- build_idle_nodes(state),
293
- monitor_state=_coord_meta.get("idle_takeover_monitor"),
294
- now_monotonic=_time.monotonic(),
295
- debounce_seconds=IDLE_DEBOUNCE_SECONDS,
296
- )
297
- _coord_meta["idle_takeover_monitor"] = idle_eval.get("monitor_state")
298
- push_idle_reminder(workspace, state, event_log, idle_eval)
299
- idle_alerts = (
300
- [{"alert_type": "idle_takeover", "message": idle_eval.get("message"),
301
- "reason": idle_eval.get("reason"), "interrupted": idle_eval.get("interrupted_nodes")}]
302
- if idle_eval.get("should_ping")
303
- else []
304
- )
305
- deadlock_alerts = detect_cross_worker_deadlocks(workspace, state, store, event_log)
306
- compaction_results: list[dict[str, Any]] = []
307
- for agent_id, agent_state in state.get("agents", {}).items():
308
- provider = str(agent_state.get("provider") or "")
309
- if provider != "codex":
310
- continue
311
- cap = captures.get(agent_id) or {}
312
- scrollback = str(cap.get("scrollback") or "")
313
- if not scrollback:
314
- continue
315
- stuck_loop = agent_id in (stuck or [])
316
- result = detect_compaction_degradation(
317
- workspace,
318
- state,
319
- event_log,
320
- agent_id=agent_id,
321
- provider=provider,
322
- scrollback=scrollback,
323
- stuck_loop=stuck_loop,
324
- )
325
- if result.get("event") and result.get("event") != "compaction_threshold_crossed.none":
326
- compaction_results.append(result)
327
- drift_results: list[dict[str, Any]] = []
328
- for agent_id, agent_state in state.get("agents", {}).items():
329
- if str(agent_state.get("provider") or "") != "codex":
330
- continue
331
- scrollback = str((captures.get(agent_id) or {}).get("scrollback") or "")
332
- if not scrollback:
333
- continue
334
- drift = detect_session_drift(
335
- workspace, state, event_log,
336
- agent_id=agent_id, agent_state=agent_state, scrollback=scrollback,
337
- )
338
- if drift:
339
- drift_results.append(drift)
340
- api_errors = detect_leader_api_errors(workspace, state, store, event_log)
341
- save_runtime_state(workspace, state)
342
- results = _collect_results_and_notify_watchers(workspace, event_log)
343
- # Stage 12: prune the dedupe log every tick — cheap O(n) delete bounded by 24h window.
344
- from team_agent.message_store.leader_notification_log import prune_leader_notification_log
345
- try:
346
- pruned = prune_leader_notification_log(store, max_age_hours=24)
347
- if pruned:
348
- event_log.write("leader_notification.log_pruned", removed=pruned)
349
- except Exception as exc:
350
- event_log.write("leader_notification.prune_failed", error=str(exc))
351
- return {
352
- "ok": True,
353
- "stop": False,
354
- "delivered": delivered,
355
- "scheduled": fired,
356
- "stuck": stuck,
357
- "idle_alerts": idle_alerts,
358
- "deadlock_alerts": deadlock_alerts,
359
- "compaction": compaction_results,
360
- "session_drift": drift_results,
361
- "api_errors": api_errors,
362
- "results": results,
363
- }
@@ -1,61 +0,0 @@
1
- from __future__ import annotations
2
-
3
- import json
4
- import os
5
- from datetime import datetime, timezone
6
- from pathlib import Path
7
- from typing import Any
8
-
9
- from team_agent.coordinator.paths import coordinator_meta_path
10
- from team_agent.message_store import MessageStore
11
-
12
-
13
- COORDINATOR_PROTOCOL_VERSION = 2
14
-
15
-
16
- def pid_is_running(pid: int) -> bool:
17
- from team_agent.runtime import run_cmd
18
- try:
19
- os.kill(pid, 0)
20
- except OSError:
21
- return False
22
- proc = run_cmd(["ps", "-p", str(pid), "-o", "stat="], timeout=5)
23
- if proc.returncode == 0 and proc.stdout.strip().upper().startswith("Z"):
24
- return False
25
- return True
26
-
27
-
28
- def read_coordinator_metadata(workspace: Path) -> dict[str, Any] | None:
29
- path = coordinator_meta_path(workspace)
30
- try:
31
- raw = json.loads(path.read_text(encoding="utf-8"))
32
- except (OSError, json.JSONDecodeError):
33
- return None
34
- return raw if isinstance(raw, dict) else None
35
-
36
-
37
- def coordinator_metadata_ok(metadata: dict[str, Any] | None, pid: int) -> bool:
38
- return bool(
39
- metadata
40
- and metadata.get("pid") == pid
41
- and metadata.get("protocol_version") == COORDINATOR_PROTOCOL_VERSION
42
- and metadata.get("message_store_schema_version") == MessageStore.SCHEMA_VERSION
43
- )
44
-
45
-
46
- def write_coordinator_metadata(workspace: Path, pid: int, source: str) -> None:
47
- path = coordinator_meta_path(workspace)
48
- path.parent.mkdir(parents=True, exist_ok=True)
49
- path.write_text(
50
- json.dumps(
51
- {
52
- "pid": pid,
53
- "protocol_version": COORDINATOR_PROTOCOL_VERSION,
54
- "message_store_schema_version": MessageStore.SCHEMA_VERSION,
55
- "source": source,
56
- "updated_at": datetime.now(timezone.utc).isoformat(),
57
- },
58
- indent=2,
59
- ),
60
- encoding="utf-8",
61
- )
@@ -1,17 +0,0 @@
1
- from __future__ import annotations
2
-
3
- from pathlib import Path
4
-
5
- from team_agent.paths import runtime_dir
6
-
7
-
8
- def coordinator_pid_path(workspace: Path) -> Path:
9
- return runtime_dir(workspace) / "coordinator.pid"
10
-
11
-
12
- def coordinator_meta_path(workspace: Path) -> Path:
13
- return runtime_dir(workspace) / "coordinator.json"
14
-
15
-
16
- def coordinator_log_path(workspace: Path) -> Path:
17
- return runtime_dir(workspace) / "coordinator.log"
@@ -1,48 +0,0 @@
1
- from __future__ import annotations
2
-
3
- from team_agent.diagnose.checks import (
4
- compact_model_checks,
5
- format_model_check_failures,
6
- format_profile_check_failures,
7
- format_profile_smoke_failures,
8
- model_checks_for_agents,
9
- profile_checks_for_agents,
10
- profile_smoke_checks_for_agents,
11
- )
12
- from team_agent.diagnose.health import diagnose, doctor
13
- from team_agent.diagnose.preflight import (
14
- ensure_profiles_for_roles,
15
- preflight,
16
- preflight_blockers,
17
- preflight_next_actions,
18
- start,
19
- )
20
- from team_agent.diagnose.quick_start import (
21
- prepare_quick_start_team,
22
- quick_start,
23
- repair_state,
24
- settle,
25
- wait_ready,
26
- )
27
-
28
- __all__ = [
29
- "compact_model_checks",
30
- "diagnose",
31
- "doctor",
32
- "ensure_profiles_for_roles",
33
- "format_model_check_failures",
34
- "format_profile_check_failures",
35
- "format_profile_smoke_failures",
36
- "model_checks_for_agents",
37
- "prepare_quick_start_team",
38
- "preflight",
39
- "preflight_blockers",
40
- "preflight_next_actions",
41
- "profile_checks_for_agents",
42
- "profile_smoke_checks_for_agents",
43
- "quick_start",
44
- "repair_state",
45
- "settle",
46
- "start",
47
- "wait_ready",
48
- ]
@@ -1,101 +0,0 @@
1
- from __future__ import annotations
2
-
3
- from pathlib import Path
4
- from typing import Any
5
-
6
- from team_agent.profiles import effective_model, smoke_check_agent_profile, validate_agent_profile
7
-
8
-
9
- def profile_checks_for_agents(workspace: Path, agents: list[dict[str, Any]]) -> list[dict[str, Any]]:
10
- return [validate_agent_profile(workspace, agent) for agent in agents if not agent.get("paused")]
11
-
12
-
13
- def profile_smoke_checks_for_agents(workspace: Path, agents: list[dict[str, Any]]) -> list[dict[str, Any]]:
14
- return [smoke_check_agent_profile(workspace, agent) for agent in agents if not agent.get("paused")]
15
-
16
-
17
- def model_checks_for_agents(agents: list[dict[str, Any]], workspace: Path | None = None) -> list[dict[str, Any]]:
18
- from team_agent.runtime import get_adapter
19
- checks: list[dict[str, Any]] = []
20
- for agent in agents:
21
- if agent.get("paused"):
22
- continue
23
- if agent.get("auth_mode") == "compatible_api" and agent.get("provider") == "codex":
24
- checks.append(
25
- {
26
- "ok": True,
27
- "status": "profile_model_deferred_to_smoke",
28
- "provider": agent["provider"],
29
- "model": effective_model(agent, workspace),
30
- "agent_id": agent["id"],
31
- }
32
- )
33
- continue
34
- adapter = get_adapter(agent["provider"])
35
- validator = getattr(adapter, "validate_model", None)
36
- model = effective_model(agent, workspace)
37
- if not callable(validator):
38
- result = {"ok": True, "status": "not_checked", "provider": agent["provider"], "model": model}
39
- else:
40
- result = validator(model)
41
- if not isinstance(result, dict):
42
- result = {"ok": True, "status": "not_checked", "provider": agent["provider"], "model": model}
43
- result = dict(result)
44
- result.setdefault("provider", agent["provider"])
45
- result.setdefault("model", model)
46
- result["agent_id"] = agent["id"]
47
- checks.append(result)
48
- return checks
49
-
50
-
51
- def compact_model_checks(checks: list[dict[str, Any]]) -> list[dict[str, Any]]:
52
- compact: list[dict[str, Any]] = []
53
- for item in checks:
54
- compact.append(
55
- {
56
- key: item.get(key)
57
- for key in ["agent_id", "provider", "model", "ok", "status", "reason", "suggested_model", "command"]
58
- if key in item
59
- }
60
- )
61
- return compact
62
-
63
-
64
- def format_model_check_failures(failures: list[dict[str, Any]]) -> str:
65
- lines = ["model validation failed before starting worker windows:"]
66
- for item in failures:
67
- message = f"{item.get('agent_id')}: provider={item.get('provider')} model={item.get('model')!r}"
68
- if item.get("suggested_model"):
69
- message += f" is not an exact model id; use {item['suggested_model']!r}"
70
- else:
71
- message += f" is unsupported ({item.get('reason') or item.get('status')})"
72
- lines.append(message)
73
- return "\n".join(lines)
74
-
75
-
76
- def format_profile_check_failures(failures: list[dict[str, Any]]) -> str:
77
- lines = ["profile validation failed before starting worker windows:"]
78
- for item in failures:
79
- message = f"{item.get('agent_id')}: profile={item.get('profile')!r} auth_mode={item.get('auth_mode')}"
80
- if item.get("missing_required"):
81
- message += f" missing {', '.join(item['missing_required'])}"
82
- else:
83
- message += f" failed ({item.get('reason') or item.get('status')})"
84
- if item.get("suggestion"):
85
- message += f"; {item['suggestion']}"
86
- lines.append(message)
87
- return "\n".join(lines)
88
-
89
-
90
- def format_profile_smoke_failures(failures: list[dict[str, Any]]) -> str:
91
- lines = ["provider profile smoke check failed before starting worker windows:"]
92
- for item in failures:
93
- message = f"{item.get('agent_id')}: provider={item.get('provider')} profile={item.get('profile')!r}"
94
- message += f" status={item.get('status')} reason={item.get('reason') or 'unknown'}"
95
- if item.get("http_status"):
96
- message += f" http_status={item['http_status']}"
97
- if item.get("error"):
98
- message += f"; {item['error']}"
99
- message += "; fix the local profile file or model id, then start again"
100
- lines.append(message)
101
- return "\n".join(lines)