@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,46 +0,0 @@
1
- from __future__ import annotations
2
-
3
- from pathlib import Path
4
- from typing import Any
5
-
6
- from team_agent.messaging.deps import (
7
- EventLog,
8
- _runtime_lock,
9
- load_spec,
10
- select_runtime_state,
11
- team_state_key,
12
- )
13
- from team_agent.messaging.send import _send_single_message_unlocked
14
-
15
-
16
- def deliver_stored_message(
17
- workspace: Path,
18
- target: str | None,
19
- content: str,
20
- *,
21
- task_id: str | None = None,
22
- sender: str = "coordinator",
23
- requires_ack: bool = False,
24
- wait_visible: bool = False,
25
- timeout: float = 30.0,
26
- team: str | None = None,
27
- ) -> dict[str, Any]:
28
- with _runtime_lock(workspace, "send"):
29
- state = select_runtime_state(workspace, team)
30
- spec_path = Path(state.get("spec_path", workspace / "team.spec.yaml"))
31
- spec = load_spec(spec_path)
32
- return _send_single_message_unlocked(
33
- workspace,
34
- state,
35
- spec,
36
- EventLog(workspace),
37
- target,
38
- content,
39
- task_id=task_id,
40
- sender=sender,
41
- requires_ack=requires_ack,
42
- wait_visible=wait_visible,
43
- timeout=timeout,
44
- route_task_id=False,
45
- owner_team_id=team_state_key(state),
46
- )
@@ -1,497 +0,0 @@
1
- from __future__ import annotations
2
-
3
- import hashlib
4
-
5
- from team_agent.messaging.deps import (
6
- EventLog,
7
- MessageStore,
8
- _choose_leader_submit_key,
9
- _leader_id,
10
- _rediscover_leader_receiver,
11
- _tmux_inject_text,
12
- _validate_leader_receiver,
13
- core_render_message,
14
- json,
15
- os,
16
- runtime_dir,
17
- save_runtime_state,
18
- team_state_key,
19
- time,
20
- )
21
-
22
- from pathlib import Path
23
- from typing import Any
24
-
25
- def allow_peer_talk(workspace: Path, agent_a: str, agent_b: str) -> dict[str, Any]:
26
- MessageStore(workspace).allow_peer(agent_a, agent_b)
27
- EventLog(workspace).write("communication.peer_allowed", a=agent_a, b=agent_b)
28
- return {"ok": True, "a": agent_a, "b": agent_b, "status": "compat_noop", "reason": "team_scoped_peer_messages_enabled"}
29
-
30
-
31
- def _mirror_peer_message_to_leader(
32
- workspace: Path,
33
- state: dict[str, Any],
34
- sender: str,
35
- target: str,
36
- content: str,
37
- task_id: str | None,
38
- event_log: EventLog,
39
- ) -> None:
40
- leader_id = _leader_id(state, {})
41
- mirror = f"Team Agent peer message from {sender} to {target}"
42
- if task_id:
43
- mirror += f" for {task_id}"
44
- mirror += f":\n\n{content}"
45
- try:
46
- result = _send_to_leader_receiver(workspace, state, leader_id, mirror, task_id, sender, False, event_log)
47
- event_log.write("communication.peer_mirrored", sender=sender, target=target, ok=result.get("ok"))
48
- except Exception as exc:
49
- event_log.write("communication.peer_mirror_failed", sender=sender, target=target, error=str(exc))
50
-
51
-
52
- def _leader_inbox_path(workspace: Path) -> Path:
53
- return runtime_dir(workspace) / "leader-inbox.log"
54
-
55
-
56
- def _extract_result_id_from_content(content: str) -> str | None:
57
- """Stage 12: result-notification messages embed a `Result id: <id>` line; the gate
58
- parses it from content so callers that did NOT plumb the result_id kwarg through
59
- still consult the dedupe gate. Format mirrors _format_report_result_notification and
60
- format_result_watcher_notification."""
61
- if not content:
62
- return None
63
- for line in content.splitlines():
64
- if line.startswith("Result id: "):
65
- return line.removeprefix("Result id: ").strip() or None
66
- return None
67
-
68
-
69
- def _send_to_leader_receiver(
70
- workspace: Path,
71
- state: dict[str, Any],
72
- leader_id: str,
73
- content: str,
74
- task_id: str | None,
75
- sender: str,
76
- requires_ack: bool,
77
- event_log: EventLog,
78
- *,
79
- result_id: str | None = None,
80
- ) -> dict[str, Any]:
81
- store = MessageStore(workspace)
82
- message_id = store.create_message(task_id, sender, leader_id, content, requires_ack=False)
83
- if requires_ack:
84
- event_log.write("leader_receiver.no_ack_forced", message_id=message_id, requested_requires_ack=True)
85
- row = _message_by_id(store, message_id)
86
- if not row:
87
- return {"ok": False, "message_id": message_id, "status": "failed", "to": leader_id, "reason": "message_missing"}
88
- if not store.claim_for_delivery(message_id):
89
- current = _message_by_id(store, message_id)
90
- status = current["status"] if current else "missing"
91
- event_log.write("leader_receiver.delivery_claim_skipped", message_id=message_id, status=status)
92
- return {
93
- "ok": status in {"submitted", "visible", "delivered", "acknowledged"},
94
- "message_id": message_id,
95
- "status": status,
96
- "to": leader_id,
97
- "channel": "direct_tmux",
98
- "reason": "message_already_claimed",
99
- }
100
- payload = _message_payload(row)
101
- rendered = core_render_message(payload)
102
- text = rendered["text"]
103
- receiver = state.get("leader_receiver", {})
104
- if not _leader_receiver_is_direct(receiver):
105
- return _fail_leader_delivery(
106
- workspace,
107
- state,
108
- store,
109
- message_id,
110
- payload,
111
- event_log,
112
- reason="leader_not_attached",
113
- error="No direct leader tmux pane is attached. Run team-agent attach-leader.",
114
- )
115
-
116
- owner_identity = state.get("team_owner") or None
117
- side_pane_refusal = _side_pane_owner_refusal(state, owner_identity)
118
- if side_pane_refusal:
119
- event_log.write("leader_receiver.side_pane_refused", **side_pane_refusal)
120
- return {
121
- "ok": False,
122
- "message_id": message_id,
123
- "status": "refused",
124
- "to": leader_id,
125
- "channel": "direct_tmux",
126
- **side_pane_refusal,
127
- }
128
- receiver_for_validation = dict(receiver)
129
- if owner_identity and owner_identity.get("leader_session_uuid") and not receiver_for_validation.get("leader_session_uuid"):
130
- receiver_for_validation["leader_session_uuid"] = owner_identity["leader_session_uuid"]
131
- validation = _validate_leader_receiver(receiver_for_validation)
132
- if not validation["ok"]:
133
- rediscovery = _rediscover_leader_receiver(
134
- receiver_for_validation,
135
- event_log,
136
- owner_identity,
137
- invalidation_reason=validation.get("reason"),
138
- team_id=team_state_key(state),
139
- )
140
- if rediscovery.get("status") == "updated":
141
- state["leader_receiver"].update(rediscovery["receiver"])
142
- receiver = state["leader_receiver"]
143
- validation = _validate_leader_receiver(receiver)
144
- elif rediscovery.get("status") == "ambiguous":
145
- return _fail_leader_delivery(
146
- workspace,
147
- state,
148
- store,
149
- message_id,
150
- payload,
151
- event_log,
152
- reason="ambiguous",
153
- error="multiple possible leader panes found; run team-agent claim-leader --confirm from the intended pane",
154
- message_status="ambiguous",
155
- )
156
- if not validation["ok"]:
157
- return _fail_leader_delivery(
158
- workspace,
159
- state,
160
- store,
161
- message_id,
162
- payload,
163
- event_log,
164
- reason=validation["reason"],
165
- error=validation.get("error"),
166
- )
167
- state["leader_receiver"].update(validation["pane"])
168
- submit_key, submit_reason = _choose_leader_submit_key(receiver.get("provider", "codex"), validation.get("capture", ""))
169
- target = receiver["pane_id"]
170
- # Stage 12 (Gap 26 ∩ Gap 32 roundtable 2026-05-26) — injection-boundary dedupe gate.
171
- # Result-notification injections route through claim_leader_notification_delivery; the
172
- # gate suppresses a second inject for the same (result_id, leader_session_uuid).
173
- # Non-result messages (peer mirror, idle reminder, ambiguous-prompt) lack a "Result id:"
174
- # line in their text and bypass the gate.
175
- effective_result_id = result_id or _extract_result_id_from_content(content)
176
- leader_uuid_for_gate = str(
177
- (state.get("team_owner") or {}).get("leader_session_uuid")
178
- or (state.get("leader_receiver") or {}).get("leader_session_uuid")
179
- or ""
180
- )
181
- owner_epoch_for_gate = int(
182
- (state.get("team_owner") or {}).get("owner_epoch")
183
- or (state.get("leader_receiver") or {}).get("owner_epoch")
184
- or 0
185
- )
186
- if effective_result_id:
187
- from team_agent.message_store.leader_notification_log import claim_leader_notification_delivery
188
- envelope_hash = hashlib.sha256(content.encode("utf-8", errors="ignore")).hexdigest()[:16]
189
- claim = claim_leader_notification_delivery(
190
- store,
191
- result_id=effective_result_id,
192
- leader_session_uuid=leader_uuid_for_gate,
193
- owner_epoch=owner_epoch_for_gate,
194
- proposed_message_id=message_id,
195
- envelope_hash=envelope_hash,
196
- owner_team_id=team_state_key(state),
197
- pane_id=target,
198
- )
199
- if claim["status"] == "already_notified_by":
200
- prev_msg = claim.get("notified_message_id")
201
- prev_hash = claim.get("envelope_content_hash")
202
- if envelope_hash == prev_hash:
203
- event_log.write(
204
- "leader_notification.dedupe_skip",
205
- result_id=effective_result_id,
206
- leader_session_uuid=leader_uuid_for_gate,
207
- prev_message_id=prev_msg,
208
- this_message_id=message_id,
209
- prev_ts=claim.get("notified_at"),
210
- pane_id=target,
211
- team_id=team_state_key(state),
212
- )
213
- else:
214
- event_log.write(
215
- "leader_notification.legitimate_duplicate_suspected",
216
- result_id=effective_result_id,
217
- leader_session_uuid=leader_uuid_for_gate,
218
- prev_message_id=prev_msg,
219
- this_message_id=message_id,
220
- prev_envelope_hash=prev_hash,
221
- this_envelope_hash=envelope_hash,
222
- pane_id=target,
223
- team_id=team_state_key(state),
224
- )
225
- store.mark(message_id, "submitted", "dedupe_suppressed_by_leader_notification_log")
226
- save_runtime_state(workspace, state)
227
- return {
228
- "ok": True,
229
- "message_id": message_id,
230
- "status": "submitted",
231
- "to": leader_id,
232
- "channel": "direct_tmux",
233
- "leader_receiver": state["leader_receiver"],
234
- "visible": False,
235
- "submitted": False,
236
- "deduped": True,
237
- "canonical_message_id": prev_msg,
238
- }
239
- event_log.write(
240
- "leader_receiver.deliver_attempt",
241
- message_id=message_id,
242
- target=target,
243
- provider=receiver.get("provider"),
244
- submit_key=submit_key,
245
- submit_reason=submit_reason,
246
- render_engine=rendered.get("engine"),
247
- visible_token=rendered.get("token"),
248
- payload=payload,
249
- warning=validation.get("warning"),
250
- result_id=effective_result_id,
251
- leader_session_uuid=leader_uuid_for_gate or None,
252
- )
253
- injection = _tmux_inject_text(
254
- target,
255
- text,
256
- submit_key,
257
- f"team-agent-leader-receiver-{message_id}",
258
- provider=receiver.get("provider", "codex"),
259
- )
260
- if not injection.get("ok") and injection.get("detected") == "codex_trust_prompt":
261
- from team_agent.messaging.trust_auto_answer import retry_injection_after_trust_auto_answer
262
- injection = retry_injection_after_trust_auto_answer(
263
- workspace,
264
- state,
265
- event_log,
266
- injection,
267
- target,
268
- text,
269
- submit_key,
270
- f"team-agent-leader-receiver-{message_id}-trust-retry",
271
- receiver.get("provider", "codex"),
272
- )
273
- if injection["ok"]:
274
- store.mark(message_id, "submitted")
275
- event_log.write(
276
- "leader_receiver.submitted",
277
- message_id=message_id,
278
- sender=sender,
279
- task_id=task_id,
280
- target=target,
281
- provider=receiver.get("provider"),
282
- submit_key=submit_key,
283
- submit_reason=submit_reason,
284
- visible=True,
285
- submitted=True,
286
- visible_token=rendered.get("token"),
287
- verification=injection.get("verification"),
288
- submit_verification=injection.get("submit_verification"),
289
- turn_verification=injection.get("turn_verification"),
290
- attempts=injection.get("attempts"),
291
- submit_attempts=injection.get("submit_attempts"),
292
- )
293
- save_runtime_state(workspace, state)
294
- return {
295
- "ok": True,
296
- "message_id": message_id,
297
- "status": "submitted",
298
- "to": leader_id,
299
- "channel": "direct_tmux",
300
- "leader_receiver": state["leader_receiver"],
301
- "submit_key": submit_key,
302
- "visible": True,
303
- "submitted": True,
304
- "visible_token": rendered.get("token"),
305
- "verification": injection.get("verification"),
306
- "submit_verification": injection.get("submit_verification"),
307
- "turn_verification": injection.get("turn_verification"),
308
- "attempts": injection.get("attempts"),
309
- "submit_attempts": injection.get("submit_attempts"),
310
- "warning": "leader messages are no-ack; requires_ack was forced false" if requires_ack else None,
311
- }
312
- return _fail_leader_delivery(
313
- workspace,
314
- state,
315
- store,
316
- message_id,
317
- payload,
318
- event_log,
319
- reason="tmux_injection_failed",
320
- error=injection.get("error"),
321
- stage=injection.get("stage"),
322
- attempts=injection.get("attempts"),
323
- submit_attempts=injection.get("submit_attempts"),
324
- )
325
-
326
-
327
- def _side_pane_owner_refusal(state: dict[str, Any], owner_identity: dict[str, Any] | None) -> dict[str, Any] | None:
328
- owner_uuid = str((owner_identity or {}).get("leader_session_uuid") or "")
329
- caller_uuid = os.environ.get("TEAM_AGENT_LEADER_SESSION_UUID") or os.environ.get("TEAM_AGENT_LEADER_SESSION_UUID_OVERRIDE") or ""
330
- if not owner_uuid or not caller_uuid or caller_uuid == owner_uuid:
331
- return None
332
- bound_pane = (state.get("leader_receiver") or {}).get("pane_id") or (owner_identity or {}).get("pane_id")
333
- team_id = team_state_key(state)
334
- return {
335
- "reason": "team_owner_mismatch",
336
- "error": (
337
- f"This workspace's team `{team_id}` is already bound to pane `{bound_pane}`. "
338
- "To work in this window either start a new team with a different team_id, operate through the bound pane, "
339
- "or run `team-agent claim-leader --confirm` only if you intend to forcibly take over."
340
- ),
341
- "bound_pane_id": bound_pane,
342
- "caller_uuid_prefix": caller_uuid[:8],
343
- "uuid_prefix": owner_uuid[:8],
344
- "action": "team-agent claim-leader --confirm",
345
- }
346
-
347
-
348
- def claim_leader_receiver(
349
- workspace: Path,
350
- state: dict[str, Any],
351
- candidate: dict[str, Any],
352
- event_log: EventLog,
353
- *,
354
- confirm: bool,
355
- expected_epoch: int | None = None,
356
- ) -> dict[str, Any]:
357
- from team_agent.messaging.leader_panes import _leader_command_looks_usable, _receiver_from_target, _target_matches_owner_identity, _uuid_prefix
358
- if not confirm:
359
- return {"ok": False, "status": "refused", "reason": "confirm_required", "action": "team-agent claim-leader --confirm"}
360
- owner = state.setdefault("team_owner", {})
361
- receiver = state.get("leader_receiver") or {}
362
- current_epoch = int(owner.get("owner_epoch") or receiver.get("owner_epoch") or 0)
363
- if expected_epoch is not None and current_epoch != expected_epoch:
364
- event_log.write("leader_receiver.claim_refused", reason="owner_epoch_advanced", owner_epoch=current_epoch, bound_pane_id=receiver.get("pane_id"))
365
- return {"ok": False, "status": "refused", "reason": "owner_epoch_advanced", "owner_epoch": current_epoch, "bound_pane_id": receiver.get("pane_id")}
366
- if receiver.get("pane_id") == candidate.get("pane_id"):
367
- return {"ok": True, "status": "already_bound", "leader_receiver": receiver, "owner_epoch": current_epoch}
368
- owner_pane = str(owner.get("pane_id") or "")
369
- if (
370
- owner_pane
371
- and str(candidate.get("pane_id") or "") != owner_pane
372
- and not _target_matches_owner_identity(candidate, owner)
373
- ):
374
- event_log.write("leader_receiver.claim_refused", reason="owner_pane_mismatch", candidate_pane_id=candidate.get("pane_id"), owner_pane_id=owner_pane)
375
- return {"ok": False, "status": "refused", "reason": "owner_pane_mismatch"}
376
- if not owner_pane and not _target_matches_owner_identity(candidate, owner):
377
- event_log.write("leader_receiver.claim_refused", reason="uuid_mismatch", candidate_pane_id=candidate.get("pane_id"))
378
- return {"ok": False, "status": "refused", "reason": "uuid_mismatch"}
379
- provider = str(candidate.get("provider") or receiver.get("provider") or "codex")
380
- if not _leader_command_looks_usable(str(candidate.get("pane_current_command", "")), provider):
381
- return {"ok": False, "status": "refused", "reason": "wrong_command", "candidate_pane_id": candidate.get("pane_id")}
382
- next_epoch = current_epoch + 1
383
- new_receiver = _receiver_from_target(candidate, provider, owner.get("leader_session_uuid"), next_epoch)
384
- owner["owner_epoch"] = next_epoch
385
- state["leader_receiver"] = new_receiver
386
- from team_agent.leader import _write_lease_dual_state
387
- from team_agent.runtime import _runtime_lock
388
- with _runtime_lock(workspace, "leader_receiver"):
389
- _write_lease_dual_state(workspace, state)
390
- event_log.write("leader_receiver.claimed", pane_id=new_receiver["pane_id"], owner_epoch=next_epoch, uuid_prefix=_uuid_prefix(owner))
391
- return {"ok": True, "status": "claimed", "leader_receiver": new_receiver, "owner_epoch": next_epoch}
392
-
393
-
394
- def _fail_leader_delivery(
395
- workspace: Path,
396
- state: dict[str, Any],
397
- store: MessageStore,
398
- message_id: str,
399
- payload: dict[str, Any],
400
- event_log: EventLog,
401
- reason: str,
402
- error: str | None = None,
403
- stage: str | None = None,
404
- message_status: str = "failed",
405
- attempts: list[dict[str, Any]] | None = None,
406
- submit_attempts: list[dict[str, Any]] | None = None,
407
- ) -> dict[str, Any]:
408
- store.mark(message_id, message_status, error or reason)
409
- fallback_path = _write_leader_fallback_audit(workspace, payload, reason, error)
410
- event_log.write(
411
- "leader_receiver.delivery_failed",
412
- message_id=message_id,
413
- target=state.get("leader_receiver", {}).get("pane_id"),
414
- reason=reason,
415
- error=error,
416
- stage=stage,
417
- attempts=attempts,
418
- submit_attempts=submit_attempts,
419
- fallback_path=str(fallback_path),
420
- suggestion="Run team-agent attach-leader --workspace . --provider codex, or pass --pane <pane_id>.",
421
- )
422
- save_runtime_state(workspace, state)
423
- return {
424
- "ok": True,
425
- "message_id": message_id,
426
- "status": "fallback_log",
427
- "message_status": message_status,
428
- "to": payload["to"],
429
- "channel": "fallback_inbox",
430
- "reason": reason,
431
- "error": error,
432
- "attempts": attempts,
433
- "submit_attempts": submit_attempts,
434
- "fallback_path": str(fallback_path),
435
- "suggestion": "Run team-agent attach-leader --workspace . --provider codex, or pass --pane <pane_id>.",
436
- }
437
-
438
-
439
- def _write_leader_fallback_audit(workspace: Path, payload: dict[str, Any], reason: str, error: str | None) -> Path:
440
- inbox_path = _leader_inbox_path(workspace)
441
- inbox_path.parent.mkdir(parents=True, exist_ok=True)
442
- stamp = time.strftime("%Y-%m-%d %H:%M:%S")
443
- text = core_render_message(payload)["text"]
444
- with inbox_path.open("a", encoding="utf-8") as inbox:
445
- inbox.write(f"\n[{stamp}] fallback reason={reason} error={error or '-'}\n{text}\n")
446
- return inbox_path
447
-
448
-
449
- def _leader_receiver_is_direct(receiver: dict[str, Any] | None) -> bool:
450
- return bool(receiver and receiver.get("mode") == "direct_tmux" and receiver.get("pane_id"))
451
-
452
-
453
- def _message_by_id(store: MessageStore, message_id: str) -> dict[str, Any] | None:
454
- return next((m for m in store.messages() if m["message_id"] == message_id), None)
455
-
456
-
457
- def _message_payload(row: dict[str, Any]) -> dict[str, Any]:
458
- return {
459
- "message_id": row["message_id"],
460
- "task_id": row["task_id"],
461
- "from": row["sender"],
462
- "to": row["recipient"],
463
- "reply_to": row["reply_to"],
464
- "requires_ack": bool(row["requires_ack"]),
465
- "artifact_refs": json.loads(row["artifact_refs"] or "[]"),
466
- "content": row["content"],
467
- }
468
-
469
-
470
- def _format_team_agent_message(payload: dict[str, Any]) -> str:
471
- return core_render_message(payload)["text"]
472
-
473
-
474
-
475
-
476
-
477
-
478
-
479
-
480
-
481
-
482
-
483
-
484
-
485
-
486
-
487
-
488
-
489
-
490
-
491
-
492
-
493
-
494
-
495
-
496
-
497
-