@team-agent/installer 0.2.10 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (326) hide show
  1. package/Cargo.lock +744 -0
  2. package/Cargo.toml +34 -0
  3. package/crates/team-agent/Cargo.toml +33 -0
  4. package/crates/team-agent/src/cli/adapters.rs +1343 -0
  5. package/crates/team-agent/src/cli/diagnose.rs +554 -0
  6. package/crates/team-agent/src/cli/emit.rs +1077 -0
  7. package/crates/team-agent/src/cli/helpers.rs +88 -0
  8. package/crates/team-agent/src/cli/leader.rs +216 -0
  9. package/crates/team-agent/src/cli/mod.rs +1141 -0
  10. package/crates/team-agent/src/cli/profile.rs +306 -0
  11. package/crates/team-agent/src/cli/send.rs +215 -0
  12. package/crates/team-agent/src/cli/status.rs +179 -0
  13. package/crates/team-agent/src/cli/status_port.rs +502 -0
  14. package/crates/team-agent/src/cli/tests/base.rs +616 -0
  15. package/crates/team-agent/src/cli/tests/compile.rs +96 -0
  16. package/crates/team-agent/src/cli/tests/divergence.rs +509 -0
  17. package/crates/team-agent/src/cli/tests/lane_c.rs +333 -0
  18. package/crates/team-agent/src/cli/tests/leader_watch.rs +395 -0
  19. package/crates/team-agent/src/cli/tests/main_preserved.rs +675 -0
  20. package/crates/team-agent/src/cli/tests/missing_subcommands.rs +390 -0
  21. package/crates/team-agent/src/cli/tests/mod.rs +97 -0
  22. package/crates/team-agent/src/cli/tests/peer_allow.rs +137 -0
  23. package/crates/team-agent/src/cli/tests/repair_state_byte_lock.rs +302 -0
  24. package/crates/team-agent/src/cli/tests/run_delegation.rs +305 -0
  25. package/crates/team-agent/src/cli/tests/status_send.rs +385 -0
  26. package/crates/team-agent/src/cli/tests/verb_profile.rs +182 -0
  27. package/crates/team-agent/src/cli/tests/verb_settle.rs +236 -0
  28. package/crates/team-agent/src/cli/tests/verb_validate.rs +184 -0
  29. package/crates/team-agent/src/cli/types.rs +605 -0
  30. package/crates/team-agent/src/compiler/tests.rs +701 -0
  31. package/crates/team-agent/src/compiler.rs +489 -0
  32. package/crates/team-agent/src/coordinator/backoff.rs +153 -0
  33. package/crates/team-agent/src/coordinator/health.rs +436 -0
  34. package/crates/team-agent/src/coordinator/mod.rs +80 -0
  35. package/crates/team-agent/src/coordinator/orphan.rs +179 -0
  36. package/crates/team-agent/src/coordinator/tests/abnormal.rs +255 -0
  37. package/crates/team-agent/src/coordinator/tests/basics.rs +262 -0
  38. package/crates/team-agent/src/coordinator/tests/daemon.rs +323 -0
  39. package/crates/team-agent/src/coordinator/tests/health_sync.rs +263 -0
  40. package/crates/team-agent/src/coordinator/tests/main_preserved.rs +136 -0
  41. package/crates/team-agent/src/coordinator/tests/mod.rs +310 -0
  42. package/crates/team-agent/src/coordinator/tests/spine.rs +261 -0
  43. package/crates/team-agent/src/coordinator/tests/takeover.rs +227 -0
  44. package/crates/team-agent/src/coordinator/tests/tick_core.rs +256 -0
  45. package/crates/team-agent/src/coordinator/tests/watch.rs +167 -0
  46. package/crates/team-agent/src/coordinator/tick.rs +2032 -0
  47. package/crates/team-agent/src/coordinator/types.rs +584 -0
  48. package/crates/team-agent/src/db/migration.rs +716 -0
  49. package/crates/team-agent/src/db/mod.rs +23 -0
  50. package/crates/team-agent/src/db/schema.rs +378 -0
  51. package/crates/team-agent/src/event_log.rs +375 -0
  52. package/crates/team-agent/src/fake_worker.rs +253 -0
  53. package/crates/team-agent/src/leader/helpers.rs +190 -0
  54. package/crates/team-agent/src/leader/inject.rs +33 -0
  55. package/crates/team-agent/src/leader/lease.rs +1063 -0
  56. package/crates/team-agent/src/leader/mod.rs +99 -0
  57. package/crates/team-agent/src/leader/owner_bind.rs +292 -0
  58. package/crates/team-agent/src/leader/rediscover/tests.rs +525 -0
  59. package/crates/team-agent/src/leader/rediscover.rs +1099 -0
  60. package/crates/team-agent/src/leader/start.rs +273 -0
  61. package/crates/team-agent/src/leader/takeover.rs +235 -0
  62. package/crates/team-agent/src/leader/tests/basics.rs +183 -0
  63. package/crates/team-agent/src/leader/tests/byte_findings.rs +234 -0
  64. package/crates/team-agent/src/leader/tests/identity.rs +206 -0
  65. package/crates/team-agent/src/leader/tests/idle.rs +271 -0
  66. package/crates/team-agent/src/leader/tests/lease_api.rs +225 -0
  67. package/crates/team-agent/src/leader/tests/lease_claim.rs +253 -0
  68. package/crates/team-agent/src/leader/tests/mod.rs +125 -0
  69. package/crates/team-agent/src/leader/tests/rediscover.rs +351 -0
  70. package/crates/team-agent/src/leader/tests/wake_start_owner.rs +204 -0
  71. package/crates/team-agent/src/leader/types.rs +487 -0
  72. package/crates/team-agent/src/lib.rs +85 -0
  73. package/crates/team-agent/src/lifecycle/display.rs +228 -0
  74. package/crates/team-agent/src/lifecycle/helpers.rs +112 -0
  75. package/crates/team-agent/src/lifecycle/launch/plan.rs +227 -0
  76. package/crates/team-agent/src/lifecycle/launch.rs +1833 -0
  77. package/crates/team-agent/src/lifecycle/mod.rs +62 -0
  78. package/crates/team-agent/src/lifecycle/restart/agent.rs +533 -0
  79. package/crates/team-agent/src/lifecycle/restart/common.rs +517 -0
  80. package/crates/team-agent/src/lifecycle/restart/orchestrator.rs +41 -0
  81. package/crates/team-agent/src/lifecycle/restart/rebuild.rs +268 -0
  82. package/crates/team-agent/src/lifecycle/restart/remove.rs +780 -0
  83. package/crates/team-agent/src/lifecycle/restart/selection.rs +208 -0
  84. package/crates/team-agent/src/lifecycle/restart/team_state.rs +242 -0
  85. package/crates/team-agent/src/lifecycle/restart.rs +76 -0
  86. package/crates/team-agent/src/lifecycle/tests/agent_ops.rs +455 -0
  87. package/crates/team-agent/src/lifecycle/tests/core.rs +989 -0
  88. package/crates/team-agent/src/lifecycle/tests/lane_ops.rs +583 -0
  89. package/crates/team-agent/src/lifecycle/tests/launch_spawn.rs +933 -0
  90. package/crates/team-agent/src/lifecycle/tests/main_preserved.rs +265 -0
  91. package/crates/team-agent/src/lifecycle/tests.rs +27 -0
  92. package/crates/team-agent/src/lifecycle/types.rs +685 -0
  93. package/crates/team-agent/src/main.rs +41 -0
  94. package/crates/team-agent/src/mcp_server/helpers.rs +228 -0
  95. package/crates/team-agent/src/mcp_server/mod.rs +183 -0
  96. package/crates/team-agent/src/mcp_server/normalize.rs +312 -0
  97. package/crates/team-agent/src/mcp_server/tests/golden.rs +283 -0
  98. package/crates/team-agent/src/mcp_server/tests/normalize.rs +244 -0
  99. package/crates/team-agent/src/mcp_server/tests/scoped.rs +189 -0
  100. package/crates/team-agent/src/mcp_server/tests/send.rs +222 -0
  101. package/crates/team-agent/src/mcp_server/tests/tools.rs +158 -0
  102. package/crates/team-agent/src/mcp_server/tests/wire.rs +159 -0
  103. package/crates/team-agent/src/mcp_server/tests.rs +38 -0
  104. package/crates/team-agent/src/mcp_server/tools.rs +603 -0
  105. package/crates/team-agent/src/mcp_server/types.rs +421 -0
  106. package/crates/team-agent/src/mcp_server/wire.rs +388 -0
  107. package/crates/team-agent/src/message_store.rs +767 -0
  108. package/crates/team-agent/src/messaging/activity.rs +433 -0
  109. package/crates/team-agent/src/messaging/delivery.rs +542 -0
  110. package/crates/team-agent/src/messaging/helpers.rs +209 -0
  111. package/crates/team-agent/src/messaging/leader_receiver.rs +340 -0
  112. package/crates/team-agent/src/messaging/mod.rs +147 -0
  113. package/crates/team-agent/src/messaging/peers.rs +32 -0
  114. package/crates/team-agent/src/messaging/results.rs +537 -0
  115. package/crates/team-agent/src/messaging/scheduler.rs +344 -0
  116. package/crates/team-agent/src/messaging/selftest.rs +100 -0
  117. package/crates/team-agent/src/messaging/send.rs +582 -0
  118. package/crates/team-agent/src/messaging/tests/basic.rs +357 -0
  119. package/crates/team-agent/src/messaging/tests/main_preserved.rs +122 -0
  120. package/crates/team-agent/src/messaging/tests/mod.rs +293 -0
  121. package/crates/team-agent/src/messaging/tests/runtime.rs +1422 -0
  122. package/crates/team-agent/src/messaging/tests/spine.rs +437 -0
  123. package/crates/team-agent/src/messaging/trust.rs +192 -0
  124. package/crates/team-agent/src/messaging/types.rs +355 -0
  125. package/crates/team-agent/src/messaging/watchers.rs +591 -0
  126. package/crates/team-agent/src/model/enums.rs +311 -0
  127. package/crates/team-agent/src/model/errors.rs +17 -0
  128. package/crates/team-agent/src/model/ids.rs +155 -0
  129. package/crates/team-agent/src/model/mod.rs +22 -0
  130. package/crates/team-agent/src/model/paths.rs +228 -0
  131. package/crates/team-agent/src/model/permissions.rs +567 -0
  132. package/crates/team-agent/src/model/routing.rs +340 -0
  133. package/crates/team-agent/src/model/spec.rs +680 -0
  134. package/crates/team-agent/src/model/task_graph.rs +380 -0
  135. package/crates/team-agent/src/model/testdata/fuzz.golden.yaml +43 -0
  136. package/crates/team-agent/src/model/testdata/fuzz.yaml +43 -0
  137. package/crates/team-agent/src/model/testdata/spec_invalid_a.yaml +207 -0
  138. package/crates/team-agent/src/model/testdata/team.spec.golden.yaml +206 -0
  139. package/crates/team-agent/src/model/testdata/team.spec.yaml +206 -0
  140. package/crates/team-agent/src/model/yaml/tests.rs +288 -0
  141. package/crates/team-agent/src/model/yaml.rs +800 -0
  142. package/crates/team-agent/src/packaging/install.rs +305 -0
  143. package/crates/team-agent/src/packaging/migrate.rs +30 -0
  144. package/crates/team-agent/src/packaging/mod.rs +82 -0
  145. package/crates/team-agent/src/packaging/repair.rs +24 -0
  146. package/crates/team-agent/src/packaging/tests.rs +829 -0
  147. package/crates/team-agent/src/packaging/types.rs +369 -0
  148. package/crates/team-agent/src/provider/adapter.rs +801 -0
  149. package/crates/team-agent/src/provider/approvals/mod.rs +2 -0
  150. package/crates/team-agent/src/provider/approvals/parsing.rs +452 -0
  151. package/crates/team-agent/src/provider/approvals/runtime_prompts.rs +163 -0
  152. package/crates/team-agent/src/provider/classify.rs +456 -0
  153. package/crates/team-agent/src/provider/faults.rs +136 -0
  154. package/crates/team-agent/src/provider/helpers.rs +41 -0
  155. package/crates/team-agent/src/provider/mod.rs +53 -0
  156. package/crates/team-agent/src/provider/startup_prompt.rs +423 -0
  157. package/crates/team-agent/src/provider/tests/adapter.rs +239 -0
  158. package/crates/team-agent/src/provider/tests/classify.rs +240 -0
  159. package/crates/team-agent/src/provider/tests/faults.rs +120 -0
  160. package/crates/team-agent/src/provider/tests/idle.rs +208 -0
  161. package/crates/team-agent/src/provider/tests/wire.rs +213 -0
  162. package/crates/team-agent/src/provider/tests.rs +31 -0
  163. package/crates/team-agent/src/provider/types.rs +424 -0
  164. package/crates/team-agent/src/state/identity.rs +656 -0
  165. package/crates/team-agent/src/state/mod.rs +58 -0
  166. package/crates/team-agent/src/state/owner_gate.rs +423 -0
  167. package/crates/team-agent/src/state/persist.rs +712 -0
  168. package/crates/team-agent/src/state/projection.rs +657 -0
  169. package/crates/team-agent/src/state/selector.rs +105 -0
  170. package/crates/team-agent/src/state/testdata/state-rich.canonical.json +133 -0
  171. package/crates/team-agent/src/tmux_backend/tests.rs +586 -0
  172. package/crates/team-agent/src/tmux_backend.rs +758 -0
  173. package/crates/team-agent/src/transport/test_support.rs +252 -0
  174. package/crates/team-agent/src/transport/tests/behavior.rs +327 -0
  175. package/crates/team-agent/src/transport/tests/mod.rs +199 -0
  176. package/crates/team-agent/src/transport/tests/wire.rs +527 -0
  177. package/crates/team-agent/src/transport.rs +774 -0
  178. package/npm/install.mjs +90 -106
  179. package/package.json +15 -13
  180. package/crates/team-agent-core/Cargo.toml +0 -12
  181. package/crates/team-agent-core/src/lib.rs +0 -332
  182. package/crates/team-agent-core/src/main.rs +0 -152
  183. package/pyproject.toml +0 -18
  184. package/scripts/install.py +0 -88
  185. package/scripts/run_regression_tests.py +0 -83
  186. package/src/team_agent/__init__.py +0 -3
  187. package/src/team_agent/__main__.py +0 -5
  188. package/src/team_agent/_legacy_pane_discovery.py +0 -186
  189. package/src/team_agent/abnormal_track.py +0 -253
  190. package/src/team_agent/approvals/__init__.py +0 -65
  191. package/src/team_agent/approvals/constants.py +0 -6
  192. package/src/team_agent/approvals/parsing.py +0 -176
  193. package/src/team_agent/approvals/runtime_prompts.py +0 -171
  194. package/src/team_agent/approvals/status.py +0 -176
  195. package/src/team_agent/cli/__init__.py +0 -137
  196. package/src/team_agent/cli/commands.py +0 -481
  197. package/src/team_agent/cli/e2e.py +0 -202
  198. package/src/team_agent/cli/helpers.py +0 -226
  199. package/src/team_agent/cli/parser.py +0 -540
  200. package/src/team_agent/compiler.py +0 -334
  201. package/src/team_agent/coordinator/__init__.py +0 -53
  202. package/src/team_agent/coordinator/__main__.py +0 -83
  203. package/src/team_agent/coordinator/lifecycle.py +0 -363
  204. package/src/team_agent/coordinator/metadata.py +0 -61
  205. package/src/team_agent/coordinator/paths.py +0 -17
  206. package/src/team_agent/diagnose/__init__.py +0 -48
  207. package/src/team_agent/diagnose/checks.py +0 -101
  208. package/src/team_agent/diagnose/comms.py +0 -213
  209. package/src/team_agent/diagnose/health.py +0 -241
  210. package/src/team_agent/diagnose/orphan_cleanup.py +0 -364
  211. package/src/team_agent/diagnose/preflight.py +0 -194
  212. package/src/team_agent/diagnose/quick_start.py +0 -324
  213. package/src/team_agent/display/__init__.py +0 -92
  214. package/src/team_agent/display/adaptive.py +0 -511
  215. package/src/team_agent/display/backend.py +0 -46
  216. package/src/team_agent/display/close.py +0 -154
  217. package/src/team_agent/display/ghostty.py +0 -77
  218. package/src/team_agent/display/rebuild.py +0 -102
  219. package/src/team_agent/display/tiling.py +0 -156
  220. package/src/team_agent/display/worker_window.py +0 -114
  221. package/src/team_agent/display/workspace.py +0 -382
  222. package/src/team_agent/errors.py +0 -10
  223. package/src/team_agent/events.py +0 -84
  224. package/src/team_agent/fake_worker.py +0 -80
  225. package/src/team_agent/idle_predicate.py +0 -200
  226. package/src/team_agent/idle_takeover.py +0 -59
  227. package/src/team_agent/idle_takeover_wiring.py +0 -111
  228. package/src/team_agent/launch/__init__.py +0 -41
  229. package/src/team_agent/launch/bootstrap.py +0 -85
  230. package/src/team_agent/launch/config.py +0 -106
  231. package/src/team_agent/launch/core.py +0 -301
  232. package/src/team_agent/launch/requirements.py +0 -57
  233. package/src/team_agent/leader/__init__.py +0 -926
  234. package/src/team_agent/leader_binding.py +0 -183
  235. package/src/team_agent/lifecycle/__init__.py +0 -5
  236. package/src/team_agent/lifecycle/agents.py +0 -278
  237. package/src/team_agent/lifecycle/operations.py +0 -411
  238. package/src/team_agent/lifecycle/paste_buffer_hygiene.py +0 -39
  239. package/src/team_agent/lifecycle/start.py +0 -363
  240. package/src/team_agent/mcp_server/__init__.py +0 -42
  241. package/src/team_agent/mcp_server/__main__.py +0 -7
  242. package/src/team_agent/mcp_server/contracts.py +0 -148
  243. package/src/team_agent/mcp_server/normalize.py +0 -257
  244. package/src/team_agent/mcp_server/server.py +0 -150
  245. package/src/team_agent/mcp_server/tools.py +0 -352
  246. package/src/team_agent/message_store/__init__.py +0 -23
  247. package/src/team_agent/message_store/agent_health.py +0 -113
  248. package/src/team_agent/message_store/core.py +0 -497
  249. package/src/team_agent/message_store/leader_notification_log.py +0 -198
  250. package/src/team_agent/message_store/result_watchers.py +0 -251
  251. package/src/team_agent/message_store/schema.py +0 -308
  252. package/src/team_agent/message_store/schema_migration.py +0 -448
  253. package/src/team_agent/messaging/__init__.py +0 -1
  254. package/src/team_agent/messaging/activity_detector.py +0 -254
  255. package/src/team_agent/messaging/delivery.py +0 -473
  256. package/src/team_agent/messaging/deps.py +0 -247
  257. package/src/team_agent/messaging/idle_alerts.py +0 -423
  258. package/src/team_agent/messaging/internal_delivery.py +0 -46
  259. package/src/team_agent/messaging/leader.py +0 -497
  260. package/src/team_agent/messaging/leader_api_errors.py +0 -216
  261. package/src/team_agent/messaging/leader_panes.py +0 -673
  262. package/src/team_agent/messaging/owner_bypass.py +0 -29
  263. package/src/team_agent/messaging/result_delivery.py +0 -539
  264. package/src/team_agent/messaging/results.py +0 -447
  265. package/src/team_agent/messaging/scheduler.py +0 -450
  266. package/src/team_agent/messaging/send.py +0 -532
  267. package/src/team_agent/messaging/session_drift.py +0 -94
  268. package/src/team_agent/messaging/tmux_io.py +0 -506
  269. package/src/team_agent/messaging/tmux_prompt.py +0 -338
  270. package/src/team_agent/messaging/trust_auto_answer.py +0 -52
  271. package/src/team_agent/orchestrator/__init__.py +0 -376
  272. package/src/team_agent/orchestrator/plan.py +0 -122
  273. package/src/team_agent/orchestrator/state.py +0 -128
  274. package/src/team_agent/paths.py +0 -45
  275. package/src/team_agent/permissions.py +0 -123
  276. package/src/team_agent/profiles/__init__.py +0 -82
  277. package/src/team_agent/profiles/constants.py +0 -19
  278. package/src/team_agent/profiles/core.py +0 -407
  279. package/src/team_agent/profiles/helpers.py +0 -69
  280. package/src/team_agent/profiles/provider_env.py +0 -188
  281. package/src/team_agent/profiles/smoke.py +0 -201
  282. package/src/team_agent/provider_cli/__init__.py +0 -43
  283. package/src/team_agent/provider_cli/adapter.py +0 -172
  284. package/src/team_agent/provider_cli/base.py +0 -48
  285. package/src/team_agent/provider_cli/claude.py +0 -457
  286. package/src/team_agent/provider_cli/codex.py +0 -336
  287. package/src/team_agent/provider_cli/copilot.py +0 -8
  288. package/src/team_agent/provider_cli/fake.py +0 -39
  289. package/src/team_agent/provider_cli/gemini.py +0 -95
  290. package/src/team_agent/provider_cli/opencode.py +0 -8
  291. package/src/team_agent/provider_cli/prompt.py +0 -62
  292. package/src/team_agent/provider_cli/registry.py +0 -18
  293. package/src/team_agent/provider_cli/unsupported.py +0 -32
  294. package/src/team_agent/provider_state/README.md +0 -78
  295. package/src/team_agent/provider_state/__init__.py +0 -86
  296. package/src/team_agent/provider_state/claude.py +0 -86
  297. package/src/team_agent/provider_state/codex.py +0 -84
  298. package/src/team_agent/provider_state/common.py +0 -207
  299. package/src/team_agent/provider_state/registry.py +0 -118
  300. package/src/team_agent/providers.py +0 -163
  301. package/src/team_agent/quality_gates.py +0 -104
  302. package/src/team_agent/restart/__init__.py +0 -34
  303. package/src/team_agent/restart/orchestration.py +0 -554
  304. package/src/team_agent/restart/selection.py +0 -89
  305. package/src/team_agent/restart/snapshot.py +0 -70
  306. package/src/team_agent/routing.py +0 -84
  307. package/src/team_agent/runtime.py +0 -1239
  308. package/src/team_agent/rust_core.py +0 -327
  309. package/src/team_agent/sessions/__init__.py +0 -25
  310. package/src/team_agent/sessions/capture.py +0 -143
  311. package/src/team_agent/sessions/inventory.py +0 -44
  312. package/src/team_agent/sessions/resume.py +0 -135
  313. package/src/team_agent/simple_yaml.py +0 -236
  314. package/src/team_agent/spec.py +0 -370
  315. package/src/team_agent/state.py +0 -602
  316. package/src/team_agent/status/__init__.py +0 -63
  317. package/src/team_agent/status/approvals.py +0 -52
  318. package/src/team_agent/status/compact.py +0 -158
  319. package/src/team_agent/status/constants.py +0 -18
  320. package/src/team_agent/status/inbox.py +0 -58
  321. package/src/team_agent/status/peek.py +0 -117
  322. package/src/team_agent/status/queries.py +0 -199
  323. package/src/team_agent/task_graph.py +0 -80
  324. package/src/team_agent/terminal.py +0 -57
  325. package/src/team_agent/wake.py +0 -58
  326. package/src/team_agent/watch/__init__.py +0 -145
@@ -1,48 +0,0 @@
1
- from __future__ import annotations
2
-
3
- from dataclasses import dataclass, field
4
- from pathlib import Path
5
- from typing import Any, Protocol, runtime_checkable
6
-
7
-
8
- @dataclass(frozen=True)
9
- class ProviderStartupInput:
10
- agent_id: str
11
- provider: str
12
- model: str | None
13
- workspace: Path
14
- system_prompt: str
15
- mcp_config: dict[str, Any] = field(default_factory=dict)
16
- profile: dict[str, Any] = field(default_factory=dict)
17
- permission_mode: str | None = None
18
- runtime_flags: dict[str, Any] = field(default_factory=dict)
19
- previous_session: dict[str, Any] = field(default_factory=dict)
20
-
21
-
22
- class ProviderCapabilityError(RuntimeError):
23
- def __init__(self, provider: str, capability: str, reason: str) -> None:
24
- self.provider = provider
25
- self.capability = capability
26
- self.reason = reason
27
- super().__init__(f"{provider} provider does not support {capability}: {reason}")
28
-
29
-
30
- @runtime_checkable
31
- class ProviderCliSocket(Protocol):
32
- provider: str
33
- command_name: str
34
-
35
- def build_command(self, startup: ProviderStartupInput) -> list[str]:
36
- ...
37
-
38
- def build_resume_command(self, startup: ProviderStartupInput) -> list[str]:
39
- ...
40
-
41
- def build_fork_command(self, startup: ProviderStartupInput, source_session_id: str) -> list[str]:
42
- ...
43
-
44
- def capture_session_id(self, startup: ProviderStartupInput, timeout_s: float = 3.0) -> dict[str, Any] | None:
45
- ...
46
-
47
- def cleanup(self, startup: ProviderStartupInput) -> None:
48
- ...
@@ -1,457 +0,0 @@
1
- from __future__ import annotations
2
-
3
- import json
4
- import re
5
- import subprocess
6
- import time
7
- import uuid
8
- from datetime import datetime, timedelta, timezone
9
- from pathlib import Path
10
- from typing import Any
11
-
12
- from team_agent.permissions import resolve_permissions
13
- from team_agent.provider_cli.adapter import (
14
- ProviderAdapter,
15
- ResumeUnavailable,
16
- agent_model,
17
- parse_time,
18
- )
19
- from team_agent.provider_cli.prompt import compile_system_prompt
20
-
21
-
22
- class ClaudeCodeAdapter(ProviderAdapter):
23
- provider = "claude_code"
24
- command_name = "claude"
25
-
26
- def build_command(self, agent: dict[str, Any], workspace: Path, mcp_config: dict[str, Any]) -> list[str]:
27
- session_id = agent.get("_session_id") or str(uuid.uuid4())
28
- agent["_session_id"] = session_id
29
- cmd = self._base_command(agent, mcp_config)
30
- cmd.extend(["--session-id", session_id])
31
- return cmd
32
-
33
- def build_resume_command(
34
- self,
35
- agent_state: dict[str, Any],
36
- workspace: Path,
37
- mcp_config: dict[str, Any] | None = None,
38
- ) -> list[str]:
39
- _ = workspace
40
- session_id = agent_state.get("session_id")
41
- if not session_id:
42
- raise ResumeUnavailable("claude resume requires session_id")
43
- if not self.session_is_resumable(agent_state, workspace):
44
- diagnostics = self.session_lookup_diagnostics(agent_state, workspace)
45
- raise ResumeUnavailable(
46
- "claude resume transcript not found "
47
- f"for session_id {session_id}; diagnostics={json.dumps(diagnostics, sort_keys=True)}"
48
- )
49
- agent = dict(agent_state.get("_agent_spec") or agent_state)
50
- cmd = self._base_command(agent, mcp_config or {})
51
- cmd.extend(["--resume", str(session_id)])
52
- return cmd
53
-
54
- def supports_session_fork(self, agent: dict[str, Any] | None = None) -> bool:
55
- return not agent or agent.get("auth_mode") != "compatible_api"
56
-
57
- def build_fork_command(
58
- self,
59
- agent: dict[str, Any],
60
- source_session_id: str,
61
- workspace: Path,
62
- mcp_config: dict[str, Any],
63
- ) -> list[str]:
64
- _ = workspace
65
- if not source_session_id:
66
- raise ResumeUnavailable("claude fork requires source session_id")
67
- session_id = agent.get("_session_id") or str(uuid.uuid4())
68
- agent["_session_id"] = session_id
69
- cmd = self._base_command(agent, mcp_config)
70
- cmd.extend(["--session-id", session_id, "--resume", str(source_session_id), "--fork-session"])
71
- return cmd
72
-
73
- def capture_session_id(
74
- self,
75
- agent_id: str,
76
- spawn_context: dict[str, Any],
77
- timeout_s: float = 3.0,
78
- ) -> dict[str, Any] | None:
79
- cwd = spawn_context.get("cwd")
80
- if not cwd:
81
- return None
82
- start = parse_time(spawn_context.get("spawn_time")) or datetime.now(timezone.utc)
83
- root = Path(spawn_context.get("claude_projects_root") or Path.home() / ".claude" / "projects")
84
- deadline = time.monotonic() + max(timeout_s, 0.0)
85
- exclude = {str(item) for item in spawn_context.get("exclude_session_ids", []) if item}
86
- predetermined = spawn_context.get("predetermined_session_id")
87
- allow_older = bool(spawn_context.get("allow_older"))
88
- while True:
89
- match = find_claude_transcript(
90
- root,
91
- Path(str(cwd)),
92
- start,
93
- agent_id=agent_id,
94
- predetermined_session_id=str(predetermined) if predetermined else None,
95
- exclude_session_ids=exclude,
96
- allow_older=allow_older,
97
- )
98
- if match:
99
- return {
100
- "session_id": match["session_id"],
101
- "rollout_path": match["rollout_path"],
102
- "captured_at": datetime.now(timezone.utc).isoformat(),
103
- "captured_via": match["captured_via"],
104
- "attribution_confidence": match["confidence"],
105
- "spawn_cwd": str(cwd),
106
- }
107
- if time.monotonic() >= deadline:
108
- return None
109
- time.sleep(0.2)
110
-
111
- def session_is_resumable(self, agent_state: dict[str, Any], workspace: Path) -> bool:
112
- session_id = agent_state.get("session_id")
113
- if not session_id:
114
- return False
115
- cwd = Path(str(agent_state.get("spawn_cwd") or workspace))
116
- root = Path(agent_state.get("claude_projects_root") or Path.home() / ".claude" / "projects")
117
- for path in claude_transcript_paths(root, cwd, str(session_id)):
118
- meta = read_claude_transcript_meta(path, cwd)
119
- if meta and meta.get("same_cwd") and meta.get("has_user_message"):
120
- return True
121
- return False
122
-
123
- def session_lookup_diagnostics(self, agent_state: dict[str, Any], workspace: Path) -> dict[str, Any]:
124
- session_id = str(agent_state.get("session_id") or "")
125
- cwd = Path(str(agent_state.get("spawn_cwd") or workspace))
126
- root = Path(agent_state.get("claude_projects_root") or Path.home() / ".claude" / "projects")
127
- paths = claude_transcript_paths(root, cwd, session_id) if session_id else []
128
- return {
129
- "provider": self.provider,
130
- "expected_session_id": session_id,
131
- "spawn_cwd": str(cwd),
132
- "claude_projects_root": str(root),
133
- "encoded_dir_claude_actual": claude_project_dir(root, cwd).name,
134
- "encoded_dir_team_agent_legacy": claude_legacy_project_dir(root, cwd).name,
135
- "transcript_paths_checked": [str(path) for path in paths],
136
- "path_exists": {str(path): path.exists() for path in paths},
137
- }
138
-
139
- def recover_session_id(
140
- self,
141
- agent_id: str,
142
- agent_state: dict[str, Any],
143
- workspace: Path,
144
- exclude_session_ids: set[str] | None = None,
145
- ) -> dict[str, Any] | None:
146
- cwd = Path(str(agent_state.get("spawn_cwd") or workspace))
147
- root = Path(agent_state.get("claude_projects_root") or Path.home() / ".claude" / "projects")
148
- pending_session_id = agent_state.get("_pending_session_id")
149
- match = find_claude_transcript(
150
- root,
151
- cwd,
152
- parse_time(agent_state.get("spawned_at")) or datetime.fromtimestamp(0, timezone.utc),
153
- agent_id=agent_id,
154
- predetermined_session_id=str(pending_session_id) if pending_session_id else None,
155
- exclude_session_ids=exclude_session_ids or set(),
156
- allow_older=True,
157
- require_agent_match=True,
158
- require_cwd=True,
159
- )
160
- if not match:
161
- return None
162
- return {
163
- "session_id": match["session_id"],
164
- "rollout_path": match["rollout_path"],
165
- "captured_at": datetime.now(timezone.utc).isoformat(),
166
- "captured_via": "fs_repair",
167
- "attribution_confidence": match["confidence"],
168
- "spawn_cwd": str(cwd),
169
- }
170
-
171
- def _base_command(self, agent: dict[str, Any], mcp_config: dict[str, Any]) -> list[str]:
172
- prompt = compile_system_prompt(agent)
173
- cmd = ["claude"]
174
- if agent.get("_runtime", {}).get("dangerous_auto_approve"):
175
- cmd.append("--dangerously-skip-permissions")
176
- else:
177
- cmd.extend(["--permission-mode", "default"])
178
- model = agent_model(agent)
179
- if model:
180
- cmd.extend(["--model", model])
181
- if prompt:
182
- cmd.extend(["--append-system-prompt", prompt])
183
- if mcp_config:
184
- managed_compatible_config = (
185
- agent.get("auth_mode") == "compatible_api"
186
- and bool(agent.get("_provider_profile", {}).get("claude_projects_root"))
187
- )
188
- if not managed_compatible_config:
189
- cmd.extend(["--mcp-config", json.dumps({"mcpServers": mcp_config})])
190
- cmd.append("--strict-mcp-config")
191
- allowed = set(resolve_permissions(agent)["tools"])
192
- disallowed = claude_disallowed_tools(allowed)
193
- for tool in disallowed:
194
- cmd.extend(["--disallowedTools", tool])
195
- return cmd
196
-
197
- def auth_hint(self) -> dict[str, Any]:
198
- if not self.is_installed():
199
- return {"status": "missing", "detail": "claude command not found"}
200
- try:
201
- proc = subprocess.run(
202
- ["claude", "auth", "status"],
203
- text=True,
204
- capture_output=True,
205
- timeout=8,
206
- check=False,
207
- )
208
- except (OSError, subprocess.TimeoutExpired) as exc:
209
- return {"status": "missing_or_unknown", "detail": f"claude auth status failed: {exc}"}
210
- text = (proc.stdout or proc.stderr).strip()
211
- try:
212
- status = json.loads(text) if text else {}
213
- except json.JSONDecodeError:
214
- status = {}
215
- if status.get("loggedIn") is True or proc.returncode == 0:
216
- method = status.get("authMethod") or "configured"
217
- return {"status": "present", "detail": f"claude auth status ok: {method}"}
218
- return {"status": "missing", "detail": text or "run claude auth login or claude setup-token"}
219
-
220
- def status_patterns(self) -> dict[str, str]:
221
- return {"idle": r"[>❯]\s", "processing": r"[✶✢✽✻✳·].*…", "error": "Error|Traceback"}
222
-
223
- def handle_startup_prompts(
224
- self,
225
- session_name: str,
226
- window_name: str,
227
- checks: int = 30,
228
- sleep_s: float = 0.5,
229
- ) -> list[dict[str, Any]]:
230
- handled: list[dict[str, Any]] = []
231
- target = f"{session_name}:{window_name}"
232
- for _ in range(max(checks, 0)):
233
- proc = subprocess.run(
234
- ["tmux", "capture-pane", "-p", "-S", "-", "-t", target],
235
- text=True,
236
- capture_output=True,
237
- timeout=5,
238
- check=False,
239
- )
240
- output = proc.stdout if proc.returncode == 0 else ""
241
- if "Quick safety check" in output or "Yes, I trust this folder" in output:
242
- subprocess.run(["tmux", "send-keys", "-t", target, "Enter"], check=False)
243
- handled.append({"prompt": "claude_workspace_trust", "action": "sent_enter"})
244
- break
245
- if "Claude Code" in output and ("❯" in output or ">" in output):
246
- break
247
- if sleep_s > 0:
248
- time.sleep(sleep_s)
249
- return handled
250
-
251
-
252
- def claude_disallowed_tools(allowed: set[str]) -> list[str]:
253
- mapping = {
254
- "execute_bash": ["Bash"],
255
- "fs_read": ["Read"],
256
- "fs_write": ["Edit", "Write", "MultiEdit", "NotebookEdit"],
257
- "fs_list": ["Glob", "Grep"],
258
- }
259
- disallowed: list[str] = []
260
- for canonical, native in mapping.items():
261
- if canonical not in allowed:
262
- disallowed.extend(native)
263
- return disallowed
264
-
265
-
266
- def find_claude_transcript(
267
- root: Path,
268
- cwd: Path,
269
- spawn_time: datetime,
270
- *,
271
- agent_id: str,
272
- predetermined_session_id: str | None,
273
- exclude_session_ids: set[str] | None = None,
274
- allow_older: bool = False,
275
- require_agent_match: bool = False,
276
- require_cwd: bool = True,
277
- ) -> dict[str, Any] | None:
278
- if not root.exists():
279
- return None
280
- exclude_session_ids = exclude_session_ids or set()
281
- if predetermined_session_id and predetermined_session_id not in exclude_session_ids:
282
- for path in claude_transcript_paths(root, cwd, predetermined_session_id):
283
- meta = read_claude_transcript_meta(path, cwd)
284
- if meta and (not require_cwd or meta.get("same_cwd")) and meta.get("has_user_message"):
285
- return {
286
- "session_id": str(predetermined_session_id),
287
- "rollout_path": str(path),
288
- "timestamp": meta.get("timestamp") or datetime.fromtimestamp(path.stat().st_mtime, timezone.utc),
289
- "captured_via": "fs_watch",
290
- "confidence": "high",
291
- }
292
- lower_bound = spawn_time - timedelta(seconds=2)
293
- upper_bound = datetime.now(timezone.utc) + timedelta(seconds=5)
294
- candidates: list[dict[str, Any]] = []
295
- for directory in claude_project_dirs(root, cwd):
296
- for path in sorted(directory.glob("*.jsonl"), key=lambda p: p.stat().st_mtime, reverse=True)[:300]:
297
- meta = read_claude_transcript_meta(path, cwd)
298
- if not meta or not meta.get("has_user_message"):
299
- continue
300
- if require_cwd and not meta.get("same_cwd"):
301
- continue
302
- session_id = str(meta.get("session_id") or path.stem)
303
- if session_id in exclude_session_ids:
304
- continue
305
- ts = meta.get("timestamp") or datetime.fromtimestamp(path.stat().st_mtime, timezone.utc)
306
- if not allow_older and (ts < lower_bound or ts > upper_bound):
307
- continue
308
- text = str(meta.get("text") or "")
309
- score = claude_agent_match_score(agent_id, text)
310
- if require_agent_match and score < 2:
311
- continue
312
- if score <= 0 and not allow_older:
313
- continue
314
- candidates.append(
315
- {
316
- "session_id": session_id,
317
- "rollout_path": str(path),
318
- "timestamp": ts,
319
- "captured_via": "fs_watch",
320
- "confidence": "high" if score >= 2 else "medium",
321
- "score": score,
322
- }
323
- )
324
- if not candidates:
325
- return None
326
- candidates.sort(key=lambda item: (item["score"], item["timestamp"]), reverse=True)
327
- return candidates[0]
328
-
329
-
330
- def claude_project_dirs(root: Path, cwd: Path) -> list[Path]:
331
- return [directory for directory in _unique_paths([claude_project_dir(root, cwd), claude_legacy_project_dir(root, cwd)]) if directory.exists()]
332
-
333
-
334
- def claude_project_dir(root: Path, cwd: Path) -> Path:
335
- try:
336
- cwd_text = str(cwd.resolve())
337
- except OSError:
338
- cwd_text = str(cwd)
339
- return root / re.sub(r"[^A-Za-z0-9.-]", "-", cwd_text)
340
-
341
-
342
- def claude_legacy_project_dir(root: Path, cwd: Path) -> Path:
343
- try:
344
- cwd_text = str(cwd.resolve())
345
- except OSError:
346
- cwd_text = str(cwd)
347
- return root / re.sub(r"[^A-Za-z0-9._-]", "-", cwd_text)
348
-
349
-
350
- def claude_transcript_path(root: Path, cwd: Path, session_id: str) -> Path:
351
- return claude_project_dir(root, cwd) / f"{session_id}.jsonl"
352
-
353
-
354
- def claude_transcript_paths(root: Path, cwd: Path, session_id: str) -> list[Path]:
355
- if not session_id:
356
- return []
357
- return _unique_paths(
358
- [
359
- claude_project_dir(root, cwd) / f"{session_id}.jsonl",
360
- claude_legacy_project_dir(root, cwd) / f"{session_id}.jsonl",
361
- ]
362
- )
363
-
364
-
365
- def _unique_paths(paths: list[Path]) -> list[Path]:
366
- seen: set[str] = set()
367
- result: list[Path] = []
368
- for path in paths:
369
- key = str(path)
370
- if key in seen:
371
- continue
372
- seen.add(key)
373
- result.append(path)
374
- return result
375
-
376
-
377
- def read_claude_transcript_meta(path: Path, cwd: Path | None = None) -> dict[str, Any] | None:
378
- if not path.exists():
379
- return None
380
- session_id: str | None = None
381
- transcript_cwd: str | None = None
382
- timestamp: datetime | None = None
383
- has_user_message = False
384
- text_parts: list[str] = []
385
- try:
386
- with path.open(encoding="utf-8") as handle:
387
- for index, line in enumerate(handle):
388
- if index >= 200:
389
- break
390
- try:
391
- data = json.loads(line)
392
- except json.JSONDecodeError:
393
- continue
394
- if not session_id and data.get("sessionId"):
395
- session_id = str(data.get("sessionId"))
396
- if not transcript_cwd and data.get("cwd"):
397
- transcript_cwd = str(data.get("cwd"))
398
- timestamp = timestamp or parse_time(data.get("timestamp"))
399
- if data.get("type") == "user":
400
- text = claude_message_text(data.get("message", {}).get("content"))
401
- if text.strip():
402
- has_user_message = True
403
- if sum(len(part) for part in text_parts) < 8000:
404
- text_parts.append(text[:4000])
405
- except OSError:
406
- return None
407
- same_cwd = True
408
- if cwd is not None:
409
- same_cwd = _same_path(transcript_cwd, cwd)
410
- return {
411
- "session_id": session_id or path.stem,
412
- "cwd": transcript_cwd,
413
- "same_cwd": same_cwd,
414
- "timestamp": timestamp,
415
- "has_user_message": has_user_message,
416
- "text": "\n".join(text_parts),
417
- }
418
-
419
-
420
- def claude_message_text(content: Any) -> str:
421
- if isinstance(content, str):
422
- return content
423
- if isinstance(content, list):
424
- parts: list[str] = []
425
- for item in content:
426
- if isinstance(item, dict) and isinstance(item.get("text"), str):
427
- parts.append(item["text"])
428
- elif isinstance(item, dict) and isinstance(item.get("content"), str):
429
- parts.append(item["content"])
430
- return "\n".join(parts)
431
- return ""
432
-
433
-
434
- def claude_agent_match_score(agent_id: str, text: str) -> int:
435
- if not agent_id:
436
- return 0
437
- lowered = text.lower()
438
- agent = agent_id.lower()
439
- score = 0
440
- if f"agents/{agent}.md" in lowered or f"agents\\/{agent}.md" in lowered:
441
- score += 1
442
- if f"team_agent_id={agent}" in lowered or f"team_agent_id={agent_id}" in text:
443
- score += 2
444
- if f"your agent id: {agent}" in lowered:
445
- score += 2
446
- if f"team agent worker {agent}" in lowered or f"worker `{agent}`" in lowered:
447
- score += 2
448
- return score
449
-
450
-
451
- def _same_path(value: str | None, path: Path) -> bool:
452
- if not value:
453
- return True
454
- try:
455
- return Path(value).resolve() == path.resolve()
456
- except OSError:
457
- return str(value) == str(path)