@team-agent/installer 0.2.11 → 0.3.1

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 +1204 -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 +1207 -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 +557 -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 +1084 -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 +526 -0
  59. package/crates/team-agent/src/leader/rediscover.rs +1101 -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 +237 -0
  64. package/crates/team-agent/src/leader/tests/identity.rs +206 -0
  65. package/crates/team-agent/src/leader/tests/idle.rs +272 -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 +410 -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 +489 -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 +2109 -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 +985 -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 +710 -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 +187 -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 +468 -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 +743 -0
  110. package/crates/team-agent/src/messaging/helpers.rs +209 -0
  111. package/crates/team-agent/src/messaging/leader_receiver.rs +329 -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 +553 -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 +578 -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 +659 -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 +765 -0
  172. package/crates/team-agent/src/tmux_backend.rs +810 -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 +118 -112
  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,448 +0,0 @@
1
- from __future__ import annotations
2
-
3
- import shutil
4
- import sqlite3
5
- import os
6
- from datetime import datetime, timezone
7
- from pathlib import Path
8
- from typing import Any, Callable
9
-
10
-
11
- MANAGED_TABLE_LAYOUTS: dict[str, tuple[str, ...]] = {
12
- "messages": (
13
- "message_id", "owner_team_id", "task_id", "sender", "recipient", "reply_to",
14
- "requires_ack", "status", "content", "artifact_refs", "created_at", "updated_at",
15
- "delivered_at", "acknowledged_at", "error", "delivery_attempts",
16
- ),
17
- "results": ("result_id", "owner_team_id", "task_id", "agent_id", "envelope", "status", "created_at"),
18
- "scheduled_events": (
19
- "id", "owner_team_id", "due_at", "target", "kind", "payload_json", "status",
20
- "created_at", "fired_at", "result_json",
21
- ),
22
- "delivery_tokens": (
23
- "message_id", "unique_token", "injected_at", "visible_at", "consumed_at",
24
- "failed_at", "failure_reason",
25
- ),
26
- "agent_health": (
27
- "owner_team_id", "agent_id", "status", "last_output_at", "context_usage_pct",
28
- "current_task_id", "updated_at",
29
- ),
30
- "peer_allowlist": ("a", "b", "created_at"),
31
- "result_watchers": (
32
- "watcher_id", "owner_team_id", "task_id", "agent_id", "message_id", "leader_id",
33
- "status", "created_at", "completed_at", "result_id", "notified_message_id", "error",
34
- ),
35
- "leader_notification_log": (
36
- "result_id", "owner_team_id", "owner_epoch", "leader_session_uuid",
37
- "notified_message_id", "notified_at", "leader_pane_id_at_notify", "envelope_content_hash",
38
- ),
39
- }
40
-
41
-
42
- CREATE_TABLE_SQL: dict[str, str] = {
43
- "messages": """
44
- create table if not exists {table} (
45
- message_id text primary key,
46
- owner_team_id text,
47
- task_id text,
48
- sender text,
49
- recipient text,
50
- reply_to text,
51
- requires_ack integer,
52
- status text,
53
- content text,
54
- artifact_refs text,
55
- created_at text,
56
- updated_at text,
57
- delivered_at text,
58
- acknowledged_at text,
59
- error text,
60
- delivery_attempts integer not null default 0
61
- )
62
- """,
63
- "results": """
64
- create table if not exists {table} (
65
- result_id text primary key,
66
- owner_team_id text,
67
- task_id text not null,
68
- agent_id text not null,
69
- envelope text not null,
70
- status text not null,
71
- created_at text not null
72
- )
73
- """,
74
- "scheduled_events": """
75
- create table if not exists {table} (
76
- id integer primary key,
77
- owner_team_id text,
78
- due_at text not null,
79
- target text not null,
80
- kind text not null,
81
- payload_json text not null,
82
- status text not null,
83
- created_at text not null,
84
- fired_at text,
85
- result_json text
86
- )
87
- """,
88
- "delivery_tokens": """
89
- create table if not exists {table} (
90
- message_id text primary key,
91
- unique_token text not null,
92
- injected_at text not null,
93
- visible_at text,
94
- consumed_at text,
95
- failed_at text,
96
- failure_reason text
97
- )
98
- """,
99
- "agent_health": """
100
- create table if not exists {table} (
101
- owner_team_id text,
102
- agent_id text not null,
103
- status text not null,
104
- last_output_at text,
105
- context_usage_pct integer,
106
- current_task_id text,
107
- updated_at text not null,
108
- unique(owner_team_id, agent_id)
109
- )
110
- """,
111
- "peer_allowlist": """
112
- create table if not exists {table} (
113
- a text not null,
114
- b text not null,
115
- created_at text not null,
116
- primary key (a, b)
117
- )
118
- """,
119
- "result_watchers": """
120
- create table if not exists {table} (
121
- watcher_id text primary key,
122
- owner_team_id text,
123
- task_id text,
124
- agent_id text,
125
- message_id text,
126
- leader_id text not null,
127
- status text not null,
128
- created_at text not null,
129
- completed_at text,
130
- result_id text,
131
- notified_message_id text,
132
- error text
133
- )
134
- """,
135
- "leader_notification_log": """
136
- create table if not exists {table} (
137
- result_id text not null,
138
- owner_team_id text not null default '',
139
- owner_epoch integer not null default 0,
140
- leader_session_uuid text,
141
- notified_message_id text not null,
142
- notified_at text not null,
143
- leader_pane_id_at_notify text,
144
- envelope_content_hash text,
145
- primary key (result_id, owner_team_id, owner_epoch)
146
- )
147
- """,
148
- }
149
-
150
-
151
- INDEX_SQL: tuple[str, ...] = (
152
- "create index if not exists idx_leader_notification_log_uuid on leader_notification_log(leader_session_uuid, notified_at)",
153
- "create index if not exists idx_leader_notification_log_team_epoch on leader_notification_log(owner_team_id, owner_epoch, notified_at)",
154
- "create index if not exists idx_messages_owner_team_id on messages(owner_team_id)",
155
- "create index if not exists idx_scheduled_events_owner_team_id on scheduled_events(owner_team_id)",
156
- "create index if not exists idx_agent_health_owner_team_id on agent_health(owner_team_id)",
157
- "create index if not exists idx_result_watchers_owner_team_id on result_watchers(owner_team_id)",
158
- )
159
-
160
-
161
- SCHEMA_MIGRATIONS: dict[int, Callable[[sqlite3.Connection], None]] = {
162
- 1: lambda _conn: None,
163
- 2: lambda _conn: None,
164
- 3: lambda _conn: None,
165
- }
166
-
167
-
168
- def table_layout(conn: sqlite3.Connection, table: str) -> tuple[str, ...]:
169
- return tuple(str(row["name"]) for row in conn.execute(f"pragma table_info({table})").fetchall())
170
-
171
-
172
- def ensure_schema_indexes(conn: sqlite3.Connection) -> None:
173
- for statement in INDEX_SQL:
174
- conn.execute(statement)
175
-
176
-
177
- def schema_diagnosis(workspace: Path, *, schema_version: int) -> dict[str, Any]:
178
- db_path = workspace / ".team" / "runtime" / "team.db"
179
- backup_path = _backup_path(db_path, _read_user_version(db_path))
180
- if not db_path.exists():
181
- return {
182
- "ok": True,
183
- "status": "missing",
184
- "db_path": str(db_path),
185
- "schema_version": schema_version,
186
- "user_version": 0,
187
- "layout_diffs": {},
188
- "recommended_action": "No team.db exists yet; initialize_schema will create it on first use.",
189
- "would_backup_path": str(backup_path),
190
- }
191
- conn = sqlite3.connect(db_path)
192
- conn.row_factory = sqlite3.Row
193
- try:
194
- user_version = _pragma_user_version(conn)
195
- diffs = _layout_diffs(conn)
196
- finally:
197
- conn.close()
198
- return {
199
- "ok": not diffs and user_version == schema_version,
200
- "status": "ok" if not diffs and user_version == schema_version else "schema_repair_available",
201
- "db_path": str(db_path),
202
- "schema_version": schema_version,
203
- "user_version": user_version,
204
- "layout_diffs": diffs,
205
- "recommended_action": "run team-agent doctor --fix-schema --json" if diffs else "none",
206
- "would_backup_path": str(backup_path),
207
- }
208
-
209
-
210
- def ensure_table_layout(
211
- conn: sqlite3.Connection,
212
- *,
213
- schema_version: int,
214
- db_path: Path | None = None,
215
- ) -> list[dict[str, Any]]:
216
- # 0.2.6 CI hotfix #3: hold the SQLite RESERVED lock across the diff
217
- # read AND the rebuild writes. Earlier code only acquired BEGIN
218
- # IMMEDIATE inside ``_rebuild_tables`` — so a concurrent writer
219
- # could squeeze a row in between ``_layout_diffs`` and the rebuild,
220
- # and the post-rebuild row-count drift check fired with
221
- # before != after even though no schema layout was clobbered.
222
- # Wrapping the whole sequence makes the drift check an invariant
223
- # (no writer can interleave once we hold the lock).
224
- conn.row_factory = sqlite3.Row
225
- _run_version_migrations(conn, schema_version)
226
- started_tx = False
227
- if not conn.in_transaction:
228
- conn.execute("BEGIN IMMEDIATE")
229
- started_tx = True
230
- try:
231
- diffs = _layout_diffs(conn)
232
- if not diffs:
233
- if started_tx:
234
- conn.execute("COMMIT")
235
- started_tx = False
236
- return []
237
- db_path = db_path or _db_path_from_conn(conn)
238
- if db_path is None:
239
- raise RuntimeError("cannot rebuild team.db layout without a database path")
240
- backup_path = _backup_path(db_path, _pragma_user_version(conn))
241
- backup_path.parent.mkdir(parents=True, exist_ok=True)
242
- shutil.copy2(db_path, backup_path)
243
- events = _rebuild_tables(conn, diffs, backup_path)
244
- if started_tx:
245
- conn.execute("COMMIT")
246
- started_tx = False
247
- except Exception:
248
- if started_tx and conn.in_transaction:
249
- try:
250
- conn.execute("ROLLBACK")
251
- except sqlite3.Error:
252
- pass
253
- raise
254
- _emit_rebuild_events(db_path, events)
255
- return events
256
-
257
-
258
- def fix_schema_layout(workspace: Path, *, schema_version: int) -> dict[str, Any]:
259
- db_path = workspace / ".team" / "runtime" / "team.db"
260
- if not db_path.exists():
261
- return schema_diagnosis(workspace, schema_version=schema_version)
262
- lock_check = _db_lock_status(db_path)
263
- if lock_check is not None:
264
- from team_agent.events import EventLog
265
- EventLog(workspace).write("schema.layout_rebuild_blocked", reason=lock_check, db_path=str(db_path))
266
- return {"ok": False, "status": "blocked", "reason": lock_check, "event": "schema.layout_rebuild_blocked", "db_path": str(db_path)}
267
- conn = sqlite3.connect(db_path, timeout=30.0, isolation_level=None)
268
- conn.row_factory = sqlite3.Row
269
- conn.execute("PRAGMA busy_timeout=30000")
270
- try:
271
- events = ensure_table_layout(conn, schema_version=schema_version, db_path=db_path)
272
- conn.execute(f"pragma user_version = {schema_version}")
273
- finally:
274
- conn.close()
275
- diagnosis = schema_diagnosis(workspace, schema_version=schema_version)
276
- diagnosis.update({"fixed": True, "rebuilds": events})
277
- return diagnosis
278
-
279
-
280
- def _run_version_migrations(conn: sqlite3.Connection, schema_version: int) -> None:
281
- current = _pragma_user_version(conn)
282
- for version in range(current, schema_version + 1):
283
- SCHEMA_MIGRATIONS.get(version, lambda _conn: None)(conn)
284
-
285
-
286
- def _layout_diffs(conn: sqlite3.Connection) -> dict[str, dict[str, Any]]:
287
- diffs: dict[str, dict[str, Any]] = {}
288
- if not any(_table_exists(conn, table) for table in MANAGED_TABLE_LAYOUTS):
289
- return diffs
290
- for table, expected in MANAGED_TABLE_LAYOUTS.items():
291
- if not _table_exists(conn, table):
292
- diffs[table] = {
293
- "expected": list(expected),
294
- "actual": [],
295
- "missing": True,
296
- }
297
- continue
298
- actual = table_layout(conn, table)
299
- if actual != expected:
300
- diffs[table] = {
301
- "expected": list(expected),
302
- "actual": list(actual),
303
- }
304
- return diffs
305
-
306
-
307
- def _rebuild_tables(
308
- conn: sqlite3.Connection,
309
- diffs: dict[str, dict[str, Any]],
310
- backup_path: Path,
311
- ) -> list[dict[str, Any]]:
312
- # Caller (``ensure_table_layout``) now holds the BEGIN IMMEDIATE for
313
- # the full diff+rebuild window, so the drift check between ``before``
314
- # and ``after`` is an invariant rather than a concurrency race. The
315
- # inner BEGIN/COMMIT/ROLLBACK was removed alongside that move (a
316
- # nested BEGIN raises in SQLite and would mask the outer lock).
317
- events: list[dict[str, Any]] = []
318
- for table, diff in diffs.items():
319
- expected = MANAGED_TABLE_LAYOUTS[table]
320
- actual = tuple(diff["actual"])
321
- before = 0 if diff.get("missing") else _table_count(conn, table)
322
- if diff.get("missing"):
323
- conn.execute(CREATE_TABLE_SQL[table].format(table=table))
324
- after = _table_count(conn, table)
325
- if after != before:
326
- raise RuntimeError(f"schema rebuild row count changed for {table}: {before} != {after}")
327
- events.append({
328
- "table": table,
329
- "from_layout_columns": [],
330
- "to_layout_columns": list(expected),
331
- "backup_path": str(backup_path),
332
- "row_count_before": before,
333
- "row_count_after": after,
334
- "missing": True,
335
- })
336
- continue
337
- temp = f"__team_agent_rebuild_{table}"
338
- old = f"__team_agent_old_{table}"
339
- conn.execute(f"drop table if exists {temp}")
340
- conn.execute(f"drop table if exists {old}")
341
- conn.execute(CREATE_TABLE_SQL[table].format(table=temp))
342
- common = [column for column in expected if column in actual]
343
- column_sql = ", ".join(common)
344
- conn.execute(f"insert into {temp}({column_sql}) select {column_sql} from {table}")
345
- _maybe_fault_after_insert()
346
- conn.execute(f"alter table {table} rename to {old}")
347
- conn.execute(f"alter table {temp} rename to {table}")
348
- conn.execute(f"drop table {old}")
349
- after = _table_count(conn, table)
350
- if before != after:
351
- raise RuntimeError(f"schema rebuild row count changed for {table}: {before} != {after}")
352
- events.append({
353
- "table": table,
354
- "from_layout_columns": list(actual),
355
- "to_layout_columns": list(expected),
356
- "backup_path": str(backup_path),
357
- "row_count_before": before,
358
- "row_count_after": after,
359
- })
360
- ensure_schema_indexes(conn)
361
- return events
362
-
363
-
364
- def _emit_rebuild_events(db_path: Path, events: list[dict[str, Any]]) -> None:
365
- workspace = _workspace_from_db_path(db_path)
366
- if workspace is None:
367
- return
368
- from team_agent.events import EventLog
369
- log = EventLog(workspace)
370
- for event in events:
371
- log.write("schema.layout_rebuild", **event)
372
-
373
-
374
- def _db_lock_status(db_path: Path) -> str | None:
375
- conn = sqlite3.connect(db_path, timeout=0.0, isolation_level=None)
376
- try:
377
- conn.execute("BEGIN IMMEDIATE")
378
- conn.execute("ROLLBACK")
379
- return None
380
- except sqlite3.OperationalError as exc:
381
- message = str(exc).lower()
382
- if "locked" in message or "busy" in message:
383
- return "active_lock"
384
- raise
385
- finally:
386
- conn.close()
387
-
388
-
389
- def _table_count(conn: sqlite3.Connection, table: str) -> int:
390
- row = conn.execute(f"select count(*) as n from {table}").fetchone()
391
- return int(row["n"])
392
-
393
-
394
- def _table_exists(conn: sqlite3.Connection, table: str) -> bool:
395
- row = conn.execute(
396
- "select name from sqlite_master where type = 'table' and name = ?",
397
- (table,),
398
- ).fetchone()
399
- return row is not None
400
-
401
-
402
- def _pragma_user_version(conn: sqlite3.Connection) -> int:
403
- row = conn.execute("pragma user_version").fetchone()
404
- return int(row["user_version"])
405
-
406
-
407
- def _read_user_version(db_path: Path) -> int:
408
- if not db_path.exists():
409
- return 0
410
- conn = sqlite3.connect(db_path)
411
- conn.row_factory = sqlite3.Row
412
- try:
413
- return _pragma_user_version(conn)
414
- finally:
415
- conn.close()
416
-
417
-
418
- def _db_path_from_conn(conn: sqlite3.Connection) -> Path | None:
419
- row = conn.execute("pragma database_list").fetchone()
420
- if not row:
421
- return None
422
- filename = str(row["file"])
423
- return Path(filename) if filename else None
424
-
425
-
426
- def _workspace_from_db_path(db_path: Path) -> Path | None:
427
- parts = db_path.parts
428
- if len(parts) >= 3 and parts[-3:] == (".team", "runtime", "team.db"):
429
- return db_path.parent.parent.parent
430
- return None
431
-
432
-
433
- def _backup_path(db_path: Path, user_version: int) -> Path:
434
- stamp = datetime.now(timezone.utc).strftime("%Y%m%dT%H%M%SZ")
435
- return db_path.with_name(f"team.db.pre-migration-{stamp}-from-v{user_version}.bak")
436
-
437
-
438
- def _maybe_fault_after_insert() -> None:
439
- allowed_keys = {
440
- "TEAM_AGENT_SCHEMA_MIGRATION_CRASH_AT",
441
- "GAP46_TEST_CRASH",
442
- "GAP46_TEST_PARTIAL_REBUILD",
443
- }
444
- allowed_values = {"1", "crash", "partial", "after_insert_before_rename"}
445
- for key in allowed_keys:
446
- value = os.environ.get(key)
447
- if value in allowed_values:
448
- os._exit(97)
@@ -1 +0,0 @@
1
- """Messaging/delivery/leader-receiver lane package."""