@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,338 +0,0 @@
1
- from __future__ import annotations
2
-
3
- from team_agent.messaging.deps import (
4
- DELIVERY_CAPTURE_LINES,
5
- PASTED_CONTENT_PROMPT_RE,
6
- TMUX_SUBMIT_MIN_SETTLE_TIMEOUT,
7
- re,
8
- run_cmd,
9
- time,
10
- )
11
-
12
- from pathlib import Path
13
- from typing import Any
14
-
15
-
16
- _ANSI_ESCAPE_RE = re.compile(r"\x1b\[[0-?]*[ -/]*[@-~]")
17
-
18
-
19
- def detect_non_input_scrollback(capture_tail: str) -> str | None:
20
- nonempty = _non_input_scrollback_lines(capture_tail)
21
- tail_text = "\n".join(nonempty)
22
- lower = tail_text.lower()
23
- stale_before_input = _stale_non_input_before_ready_prompt(nonempty)
24
- if re.search(r"do\s+you\s+trust\s+the\s+contents\s+of\s+this\s+directory", lower):
25
- if stale_before_input:
26
- return None
27
- return "codex_trust_prompt"
28
- if "press enter to log in" in lower or "press enter to login" in lower:
29
- if stale_before_input:
30
- return None
31
- return "codex_first_run_auth"
32
- if "capability may degrade" in lower:
33
- if stale_before_input:
34
- return None
35
- return "codex_compaction_warning"
36
- if re.search(r"press\s+(enter|return)\s+to\s+continue", lower):
37
- if stale_before_input:
38
- return None
39
- return "generic_press_enter"
40
- if re.search(r"press\s+any\s+key", lower):
41
- if stale_before_input:
42
- return None
43
- return "generic_press_enter"
44
- if re.search(r"(\(y/n\)|\([yY]/n\)|\[y/N\]|\[Y/n\]|\[y/n\])", tail_text):
45
- if stale_before_input:
46
- return None
47
- return "y_n_confirm"
48
- for first, second in zip(nonempty, nonempty[1:]):
49
- if _starts_numbered_choice(first, "1") and _starts_numbered_choice(second, "2"):
50
- if not _numbered_menu_shape(nonempty):
51
- continue
52
- if stale_before_input:
53
- return None
54
- return "numbered_menu"
55
- if nonempty:
56
- last = nonempty[-1]
57
- if re.search(r"(^|[\s~/.\w-])[$%]\s*$", last):
58
- return "shell_prompt_cli_dead"
59
- return None
60
-
61
-
62
- def non_input_scrollback_window(capture_tail: str, limit: int = 15) -> str:
63
- return "\n".join(_non_input_scrollback_lines(capture_tail, limit=limit))
64
-
65
-
66
- def _non_input_scrollback_lines(capture_tail: str, limit: int = 15) -> list[str]:
67
- lines = [_ANSI_ESCAPE_RE.sub("", line).rstrip() for line in capture_tail.splitlines()]
68
- while lines and not lines[-1].strip():
69
- lines.pop()
70
- return [line for line in lines if line.strip()][-limit:]
71
-
72
-
73
- def _starts_numbered_choice(line: str, number: str) -> bool:
74
- return bool(re.match(rf"^\s*(?:[›❯>]\s*)?{number}\.\s+", line))
75
-
76
-
77
- def _numbered_menu_shape(lines: list[str]) -> bool:
78
- tail_text = "\n".join(lines)
79
- if any(re.match(r"^\s*[›❯>]\s*\d+\.\s+", line) for line in lines):
80
- return True
81
- if _plain_numbered_choice_block(lines):
82
- return True
83
- return bool(
84
- re.search(r"\b(enter|return)\b.*\b(confirm|select|continue)\b", tail_text, re.IGNORECASE)
85
- or re.search(r"\b(confirm|select|continue)\b.*\b(enter|return)\b", tail_text, re.IGNORECASE)
86
- or re.search(r"\besc\b.*\b(cancel|back|quit)\b", tail_text, re.IGNORECASE)
87
- )
88
-
89
-
90
- def _plain_numbered_choice_block(lines: list[str]) -> bool:
91
- choices = [line.strip() for line in lines if re.match(r"^\s*\d+\.\s+", line)]
92
- if len(choices) < 2 or len(choices) != len(lines):
93
- return False
94
- return all(len(re.sub(r"^\d+\.\s+", "", choice).strip()) <= 32 for choice in choices)
95
-
96
-
97
- def _stale_non_input_before_ready_prompt(lines: list[str]) -> bool:
98
- latest_non_input = -1
99
- latest_ready = -1
100
- for index, line in enumerate(lines):
101
- lower = line.lower()
102
- if (
103
- "do you trust the contents of this directory" in lower
104
- or re.search(r"press\s+(enter|return)\s+to\s+continue", lower)
105
- or re.search(r"press\s+any\s+key", lower)
106
- or _starts_numbered_choice(line, "1")
107
- or _starts_numbered_choice(line, "2")
108
- ):
109
- latest_non_input = index
110
- if _is_input_ready_prompt(line):
111
- latest_ready = index
112
- return latest_non_input >= 0 and latest_ready > latest_non_input
113
-
114
-
115
- def _is_input_ready_prompt(line: str) -> bool:
116
- if _starts_numbered_choice(line, "1") or _starts_numbered_choice(line, "2"):
117
- return False
118
- value = line.strip()
119
- if re.match(r"^[›❯>]\s+\S", value):
120
- return True
121
- return bool(re.search(r"\b(codex|claude)\s*[>›❯]\s*$", value, re.IGNORECASE))
122
-
123
-
124
- def _enable_codex_fast_mode(session_name: str, window_name: str) -> dict[str, Any]:
125
- target = f"{session_name}:{window_name}"
126
- proc = run_cmd(["tmux", "send-keys", "-t", target, "/fast", "Enter"], timeout=10)
127
- if proc.returncode != 0:
128
- return {"ok": False, "error": proc.stderr.strip() or "tmux send-keys failed"}
129
- return {"ok": True, "target": target}
130
-
131
-
132
- def _wait_for_visible_token(target: str, token: str, timeout: float) -> tuple[bool, str]:
133
- deadline = time.monotonic() + max(timeout, 0.0)
134
- last = "not_checked"
135
- while True:
136
- capture = _capture_tmux_pane_text(target)
137
- if capture["ok"]:
138
- if token in capture["capture"] or f"[team-agent-token:{token}]" in capture["capture"]:
139
- return True, "capture_contains_token"
140
- last = "capture_missing_token"
141
- else:
142
- last = f"capture_failed: {capture.get('error')}"
143
- if time.monotonic() >= deadline:
144
- return False, last
145
- time.sleep(0.1)
146
-
147
-
148
- def _capture_tmux_pane_text(target: str) -> dict[str, Any]:
149
- capture = run_cmd(["tmux", "capture-pane", "-p", "-S", f"-{DELIVERY_CAPTURE_LINES}", "-t", target], timeout=5)
150
- if capture.returncode != 0:
151
- return {"ok": False, "capture": "", "error": capture.stderr.strip() or "tmux capture-pane failed"}
152
- return {"ok": True, "capture": capture.stdout}
153
-
154
-
155
- def _wait_for_message_ready(
156
- target: str,
157
- message_id: str,
158
- timeout: float,
159
- expected_text: str = "",
160
- allow_pasted_prompt: bool = True,
161
- baseline_capture: str = "",
162
- ) -> tuple[bool, str, str]:
163
- deadline = time.monotonic() + max(timeout, 0.0)
164
- last = "not_checked"
165
- last_capture = ""
166
- baseline_had_pasted_prompt = _capture_has_pasted_content_prompt(baseline_capture)
167
- while True:
168
- capture = _capture_tmux_pane_text(target)
169
- if capture["ok"]:
170
- capture_text = capture["capture"]
171
- last_capture = capture_text
172
- if message_id in capture_text or f"[team-agent-token:{message_id}]" in capture_text:
173
- return True, "capture_contains_token", capture_text
174
- if expected_text and _capture_contains_message_fragment(capture_text, expected_text):
175
- return True, "capture_contains_message_fragment", capture_text
176
- if allow_pasted_prompt and _capture_has_pasted_content_prompt(capture_text) and not baseline_had_pasted_prompt:
177
- return True, "capture_contains_new_pasted_content_prompt", capture_text
178
- last = "capture_missing_token"
179
- else:
180
- last = f"capture_failed: {capture.get('error')}"
181
- if time.monotonic() >= deadline:
182
- return False, last, last_capture
183
- time.sleep(0.1)
184
-
185
-
186
- def _wait_for_worker_message_ready(target: str, message_id: str, timeout: float, expected_text: str = "") -> tuple[bool, str, str]:
187
- return _wait_for_message_ready(target, message_id, timeout, expected_text=expected_text)
188
-
189
-
190
- def _capture_has_pasted_content_prompt(text: str) -> bool:
191
- lines = [line.rstrip() for line in text.splitlines() if line.strip()]
192
- if not lines:
193
- return False
194
- tail = [line.strip() for line in lines[-12:]]
195
- tail_text = " ".join(tail)
196
- if not PASTED_CONTENT_PROMPT_RE.search(tail_text):
197
- return False
198
- prompt_markers = ("›", "❯", ">")
199
- if PASTED_CONTENT_PROMPT_RE.search(tail[-1]):
200
- return True
201
- if tail[-1].endswith(("chars]", "line]", "lines]")):
202
- return True
203
- if any(line.startswith(prompt_markers) for line in tail):
204
- return True
205
- if re.search(r"\b(codex|claude)\s*[>›❯]", tail_text, re.IGNORECASE):
206
- return True
207
- return False
208
-
209
-
210
- def _capture_contains_message_fragment(capture_text: str, expected_text: str) -> bool:
211
- haystack = _compact_visible_text(capture_text)
212
- if not haystack:
213
- return False
214
- fragments = _message_fragment_candidates(expected_text)
215
- if not fragments:
216
- return False
217
- return any(fragment in haystack for fragment in fragments)
218
-
219
-
220
- def _message_fragment_candidates(text: str) -> list[str]:
221
- sanitized = re.sub(r"\[team-agent-token:[^\]]+\]", "", text)
222
- fragments: list[str] = []
223
- for line in _message_content_lines(sanitized):
224
- compact = _compact_visible_text(line)
225
- if not _is_strong_message_fragment(compact):
226
- continue
227
- if len(compact) <= 72:
228
- fragments.append(compact)
229
- continue
230
- midpoint = len(compact) // 2
231
- fragments.extend(
232
- [
233
- compact[:36],
234
- compact[max(0, midpoint - 18) : midpoint + 18],
235
- compact[-36:],
236
- ]
237
- )
238
- unique: list[str] = []
239
- seen: set[str] = set()
240
- for fragment in fragments:
241
- if fragment in seen:
242
- continue
243
- seen.add(fragment)
244
- unique.append(fragment)
245
- return unique
246
-
247
-
248
- def _message_content_lines(text: str) -> list[str]:
249
- lines = text.splitlines()
250
- if lines and lines[0].strip().startswith("Team Agent message from "):
251
- lines = lines[1:]
252
- return [line for line in lines if line.strip()]
253
-
254
-
255
- def _is_strong_message_fragment(compact: str) -> bool:
256
- if not compact:
257
- return False
258
- generic_prefixes = (
259
- "TeamAgentmessagefrom",
260
- "TeamAgentpeermessagefrom",
261
- "TeamAgentstoredthisresult",
262
- "TeamAgenthascollectedthisresult",
263
- "Nomanualpolling",
264
- )
265
- if compact.startswith(generic_prefixes):
266
- return False
267
- if re.fullmatch(r"[-::>›❯]+", compact):
268
- return False
269
- if re.search(r"(msg|res)_[0-9A-Fa-f]{8,}", compact):
270
- return True
271
- cjk_count = len(re.findall(r"[\u4e00-\u9fff]", compact))
272
- if cjk_count >= 4 and len(compact) >= 6:
273
- return True
274
- return len(compact) >= 18
275
-
276
-
277
- def _compact_visible_text(text: str) -> str:
278
- return re.sub(r"\s+", "", text)
279
-
280
-
281
- def _submit_worker_prompt(
282
- target: str,
283
- before_capture: str,
284
- submit_key: str = "Enter",
285
- attempts: int = 3,
286
- settle_timeout: float = TMUX_SUBMIT_MIN_SETTLE_TIMEOUT,
287
- ) -> dict[str, Any]:
288
- verify_pasted_prompt = _capture_has_pasted_content_prompt(before_capture)
289
- attempt_log: list[dict[str, Any]] = []
290
- for attempt in range(1, max(attempts, 1) + 1):
291
- proc = run_cmd(["tmux", "send-keys", "-t", target, submit_key], timeout=10)
292
- if proc.returncode != 0:
293
- return {
294
- "ok": False,
295
- "stage": "send-keys",
296
- "verification": "send_keys_failed",
297
- "error": proc.stderr.strip(),
298
- "attempts": attempt_log,
299
- }
300
- if not verify_pasted_prompt:
301
- return {
302
- "ok": True,
303
- "stage": "submitted",
304
- "verification": "enter_sent_without_placeholder_check",
305
- "attempts": attempt_log + [{"attempt": attempt, "submitted": True, "verification": "not_required"}],
306
- }
307
- cleared, verification = _wait_for_pasted_prompt_cleared(target, settle_timeout)
308
- attempt_log.append({"attempt": attempt, "submitted": True, "verification": verification})
309
- if cleared:
310
- return {
311
- "ok": True,
312
- "stage": "submitted",
313
- "verification": "pasted_content_prompt_absent_after_submit",
314
- "attempts": attempt_log,
315
- }
316
- return {
317
- "ok": False,
318
- "stage": "submit-verification",
319
- "verification": "pasted_content_prompt_still_present_after_retries",
320
- "error": "pasted content prompt still present after Enter retries",
321
- "attempts": attempt_log,
322
- }
323
-
324
-
325
- def _wait_for_pasted_prompt_cleared(target: str, timeout: float) -> tuple[bool, str]:
326
- polls = max(1, int(max(timeout, 0.0) / 0.1) + 1)
327
- last = "pasted_content_prompt_still_present"
328
- for poll in range(polls):
329
- capture = run_cmd(["tmux", "capture-pane", "-p", "-S", f"-{DELIVERY_CAPTURE_LINES}", "-t", target], timeout=5)
330
- if capture.returncode != 0:
331
- last = "capture_failed"
332
- elif not _capture_has_pasted_content_prompt(capture.stdout):
333
- return True, "pasted_content_prompt_absent"
334
- else:
335
- last = "pasted_content_prompt_still_present"
336
- if poll < polls - 1:
337
- time.sleep(0.1)
338
- return False, last
@@ -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.events import EventLog
7
- from team_agent.messaging.deps import _tmux_inject_text
8
-
9
-
10
- def retry_injection_after_trust_auto_answer(
11
- workspace: Path,
12
- state: dict[str, Any],
13
- event_log: EventLog,
14
- injection: dict[str, Any],
15
- target: str,
16
- text: str,
17
- submit_key: str,
18
- buffer_name: str,
19
- provider: str,
20
- ) -> dict[str, Any]:
21
- from team_agent.messaging.delivery import _tmux_pane_width, _wait_for_trust_prompt_dismissal
22
- from team_agent.messaging.leader_panes import attempt_trust_auto_answer
23
- pane_target = injection.get("pane_id") or target
24
- # Live wiring: query tmux pane width now and pass via state["pane_width"]
25
- # (symmetric with _deliver_pending_message). Fail-safe on query failure —
26
- # leave pane_width absent so the matcher falls back to exact equality.
27
- width_query = _tmux_pane_width(pane_target)
28
- trust_state = dict(state) if isinstance(state, dict) else {}
29
- if width_query.get("ok"):
30
- trust_state["pane_width"] = width_query["pane_width"]
31
- answer = attempt_trust_auto_answer(
32
- workspace,
33
- pane_target,
34
- injection.get("pane_capture_tail") or "",
35
- event_log,
36
- state=trust_state,
37
- )
38
- if not answer.get("answered"):
39
- return injection
40
- if not _wait_for_trust_prompt_dismissal(injection.get("pane_id") or target, timeout=3.0):
41
- retry_blocked = dict(injection)
42
- retry_blocked["error"] = "trust_prompt_not_dismissed_after_answer"
43
- retry_blocked["verification"] = "trust_prompt_not_dismissed_after_answer"
44
- retry_blocked["stage"] = "trust_auto_answer_dismissal_wait"
45
- return retry_blocked
46
- return _tmux_inject_text(
47
- target,
48
- text,
49
- submit_key,
50
- buffer_name,
51
- provider=provider,
52
- )