@team-agent/installer 0.5.65 → 0.5.68

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 (208) hide show
  1. package/Cargo.lock +8 -1
  2. package/Cargo.toml +1 -1
  3. package/crates/team-agent/Cargo.toml +6 -0
  4. package/crates/team-agent/src/cli/adapters.rs +6 -1
  5. package/crates/team-agent/src/cli/diagnose.rs +82 -0
  6. package/crates/team-agent/src/cli/emit.rs +3 -3
  7. package/crates/team-agent/src/cli/grok_slot.rs +299 -0
  8. package/crates/team-agent/src/cli/leader.rs +21 -7
  9. package/crates/team-agent/src/cli/leaders.rs +125 -1
  10. package/crates/team-agent/src/cli/mod.rs +20 -0
  11. package/crates/team-agent/src/cli/send/presentation.rs +7 -1
  12. package/crates/team-agent/src/cli/spec.rs +2 -0
  13. package/crates/team-agent/src/cli/status_port/compact.rs +28 -0
  14. package/crates/team-agent/src/cli/status_port/snapshot.rs +25 -1
  15. package/crates/team-agent/src/cli/tests/base.rs +26 -3
  16. package/crates/team-agent/src/cli/tests/compile.rs +1 -1
  17. package/crates/team-agent/src/cli/tests/missing_subcommands.rs +129 -19
  18. package/crates/team-agent/src/cli/tests/mod.rs +2 -2
  19. package/crates/team-agent/src/cli/tests/run_delegation.rs +1 -1
  20. package/crates/team-agent/src/cli/tests/shutdown_kill_plan.rs +387 -6
  21. package/crates/team-agent/src/cli/tests/status_send.rs +79 -10
  22. package/crates/team-agent/src/cli/tests/verb_validate.rs +1 -1
  23. package/crates/team-agent/src/communication_mode/mod.rs +6 -4
  24. package/crates/team-agent/src/compiler/tests.rs +23 -20
  25. package/crates/team-agent/src/compiler.rs +84 -5
  26. package/crates/team-agent/src/conpty/backend.rs +16 -0
  27. package/crates/team-agent/src/coordinator/backoff.rs +55 -0
  28. package/crates/team-agent/src/coordinator/conpty_shim.rs +82 -0
  29. package/crates/team-agent/src/coordinator/health.rs +173 -0
  30. package/crates/team-agent/src/coordinator/mod.rs +31 -0
  31. package/crates/team-agent/src/coordinator/orphan.rs +31 -0
  32. package/crates/team-agent/src/coordinator/runtime_detectors.rs +30 -0
  33. package/crates/team-agent/src/coordinator/runtime_observation.rs +25 -0
  34. package/crates/team-agent/src/coordinator/steps/abnormal.rs +59 -0
  35. package/crates/team-agent/src/coordinator/steps/delivery.rs +10 -0
  36. package/crates/team-agent/src/coordinator/steps/health_sync.rs +10 -0
  37. package/crates/team-agent/src/coordinator/steps/mod.rs +22 -0
  38. package/crates/team-agent/src/coordinator/steps/persist.rs +10 -0
  39. package/crates/team-agent/src/coordinator/steps/runtime_prompts.rs +10 -0
  40. package/crates/team-agent/src/coordinator/steps/session_gate.rs +10 -0
  41. package/crates/team-agent/src/coordinator/tick.rs +133 -22
  42. package/crates/team-agent/src/coordinator/types.rs +49 -0
  43. package/crates/team-agent/src/db/message_store.rs +39 -5
  44. package/crates/team-agent/src/layout/worker_env.rs +20 -3
  45. package/crates/team-agent/src/layout/worker_window_helpers.rs +2 -0
  46. package/crates/team-agent/src/leader/provider_attribution.rs +53 -0
  47. package/crates/team-agent/src/leader/registry.rs +65 -0
  48. package/crates/team-agent/src/leader/start.rs +1080 -58
  49. package/crates/team-agent/src/leader/tests/team_in_team_state_scope_red.rs +1 -1
  50. package/crates/team-agent/src/lifecycle/display.rs +56 -0
  51. package/crates/team-agent/src/lifecycle/helpers.rs +57 -0
  52. package/crates/team-agent/src/lifecycle/launch/add_agent.rs +332 -14
  53. package/crates/team-agent/src/lifecycle/launch/add_agent_state.rs +69 -2
  54. package/crates/team-agent/src/lifecycle/launch/agent_state.rs +196 -2
  55. package/crates/team-agent/src/lifecycle/launch/clone_agent.rs +101 -11
  56. package/crates/team-agent/src/lifecycle/launch/cursor_create_chat.rs +229 -0
  57. package/crates/team-agent/src/lifecycle/launch/cursor_mcp.rs +332 -0
  58. package/crates/team-agent/src/lifecycle/launch/fork_agent.rs +204 -457
  59. package/crates/team-agent/src/lifecycle/launch/fork_entry.rs +24 -0
  60. package/crates/team-agent/src/lifecycle/launch/grok_per_seat.rs +260 -0
  61. package/crates/team-agent/src/lifecycle/launch/identity.rs +146 -0
  62. package/crates/team-agent/src/lifecycle/launch/layout.rs +60 -0
  63. package/crates/team-agent/src/lifecycle/launch/leader_context.rs +112 -0
  64. package/crates/team-agent/src/lifecycle/launch/mcp_config.rs +530 -0
  65. package/crates/team-agent/src/lifecycle/launch/ownership.rs +40 -0
  66. package/crates/team-agent/src/lifecycle/launch/plan.rs +31 -0
  67. package/crates/team-agent/src/lifecycle/launch/quick_start.rs +66 -0
  68. package/crates/team-agent/src/lifecycle/launch/quick_start_transport.rs +78 -0
  69. package/crates/team-agent/src/lifecycle/launch/readiness.rs +85 -38
  70. package/crates/team-agent/src/lifecycle/launch/role_source.rs +44 -44
  71. package/crates/team-agent/src/lifecycle/launch/spawn.rs +101 -4
  72. package/crates/team-agent/src/lifecycle/launch/spec_state.rs +244 -48
  73. package/crates/team-agent/src/lifecycle/launch/state_projection.rs +109 -2
  74. package/crates/team-agent/src/lifecycle/launch/worker_env.rs +214 -1
  75. package/crates/team-agent/src/lifecycle/launch.rs +209 -43
  76. package/crates/team-agent/src/lifecycle/lock.rs +42 -1
  77. package/crates/team-agent/src/lifecycle/mod.rs +11 -0
  78. package/crates/team-agent/src/lifecycle/pane_input_lock.rs +161 -0
  79. package/crates/team-agent/src/lifecycle/profile_launch.rs +98 -0
  80. package/crates/team-agent/src/lifecycle/profile_smoke.rs +51 -1
  81. package/crates/team-agent/src/lifecycle/restart/agent.rs +213 -3
  82. package/crates/team-agent/src/lifecycle/restart/common.rs +373 -18
  83. package/crates/team-agent/src/lifecycle/restart/orchestrator.rs +27 -0
  84. package/crates/team-agent/src/lifecycle/restart/preflight.rs +25 -0
  85. package/crates/team-agent/src/lifecycle/restart/rebuild.rs +165 -15
  86. package/crates/team-agent/src/lifecycle/restart/remove.rs +196 -5
  87. package/crates/team-agent/src/lifecycle/restart/selection.rs +72 -0
  88. package/crates/team-agent/src/lifecycle/restart/team_state.rs +22 -0
  89. package/crates/team-agent/src/lifecycle/restart.rs +29 -0
  90. package/crates/team-agent/src/lifecycle/tests/acceptance_b_batch_red.rs +1 -1
  91. package/crates/team-agent/src/lifecycle/tests/agent_ops.rs +3 -4
  92. package/crates/team-agent/src/lifecycle/tests/behavioral_diff_264_red.rs +1 -1
  93. package/crates/team-agent/src/lifecycle/tests/claude_compatible_config_red.rs +2 -2
  94. package/crates/team-agent/src/lifecycle/tests/claude_profile_launch_red.rs +4 -4
  95. package/crates/team-agent/src/lifecycle/tests/clone_agent_preserves_source_tools.rs +309 -0
  96. package/crates/team-agent/src/lifecycle/tests/clone_fork_copilot_perms_red.rs +159 -174
  97. package/crates/team-agent/src/lifecycle/tests/communication_mode_runtime_contract_red.rs +2 -2
  98. package/crates/team-agent/src/lifecycle/tests/copilot_provider_red.rs +15 -13
  99. package/crates/team-agent/src/lifecycle/tests/core.rs +4 -18
  100. package/crates/team-agent/src/lifecycle/tests/core_034_real_red.rs +1 -1
  101. package/crates/team-agent/src/lifecycle/tests/cursor_mcp_overlay.rs +287 -0
  102. package/crates/team-agent/src/lifecycle/tests/cursor_require_explicit_model_red.rs +229 -0
  103. package/crates/team-agent/src/lifecycle/tests/cursor_restart_resume_red.rs +353 -0
  104. package/crates/team-agent/src/lifecycle/tests/display_adaptive_red.rs +1 -1
  105. package/crates/team-agent/src/lifecycle/tests/f032_startup_prompt_best_effort_red.rs +1 -1
  106. package/crates/team-agent/src/lifecycle/tests/g1_silent_faces.rs +784 -0
  107. package/crates/team-agent/src/lifecycle/tests/gate_fixtures.rs +562 -0
  108. package/crates/team-agent/src/lifecycle/tests/grok_effort_argv_red.rs +239 -0
  109. package/crates/team-agent/src/lifecycle/tests/grok_mcp_overlay_red.rs +498 -0
  110. package/crates/team-agent/src/lifecycle/tests/grok_require_explicit_model_red.rs +250 -0
  111. package/crates/team-agent/src/lifecycle/tests/grok_restart_resume_red.rs +293 -0
  112. package/crates/team-agent/src/lifecycle/tests/harvest2_a_batch_red.rs +3 -0
  113. package/crates/team-agent/src/lifecycle/tests/host_cotenant_death_p0_contract.rs +3 -3
  114. package/crates/team-agent/src/lifecycle/tests/lane_ops.rs +65 -40
  115. package/crates/team-agent/src/lifecycle/tests/launch_spawn.rs +20 -32
  116. package/crates/team-agent/src/lifecycle/tests/lifecycle_rollback_red.rs +17 -9
  117. package/crates/team-agent/src/lifecycle/tests/mcp_tool_name_format_red.rs +69 -0
  118. package/crates/team-agent/src/lifecycle/tests/phase_b_contracts.rs +24 -23
  119. package/crates/team-agent/src/lifecycle/tests/phase_golden.rs +98 -62
  120. package/crates/team-agent/src/lifecycle/tests/quick_start_worker_readiness_red.rs +2 -2
  121. package/crates/team-agent/src/lifecycle/tests/restart_build_before_destroy_0540_contract.rs +1 -1
  122. package/crates/team-agent/src/lifecycle/tests/restart_liveness_red.rs +1 -1
  123. package/crates/team-agent/src/lifecycle/tests/restart_rebind_hotfix_252_red.rs +3 -1
  124. package/crates/team-agent/src/lifecycle/tests/restart_session_capture_red.rs +2 -2
  125. package/crates/team-agent/src/lifecycle/tests/resume_recover_red.rs +1 -1
  126. package/crates/team-agent/src/lifecycle/tests/stale_team_saveconflict_contract.rs +1 -1
  127. package/crates/team-agent/src/lifecycle/tests/startup_latency_contract.rs +41 -8
  128. package/crates/team-agent/src/lifecycle/tests/status_credential_redaction_contract.rs +3 -3
  129. package/crates/team-agent/src/lifecycle/tests/subprep_codex_trust_roundtrip_red.rs +1 -1
  130. package/crates/team-agent/src/lifecycle/tests/swallow_batch4_semantics_red.rs +1 -1
  131. package/crates/team-agent/src/lifecycle/tests/team_in_team_identity_scope_red.rs +1 -1
  132. package/crates/team-agent/src/lifecycle/tests/team_in_team_sibling_quick_start_red.rs +1 -1
  133. package/crates/team-agent/src/lifecycle/tests/team_in_team_state_scope_red.rs +1 -1
  134. package/crates/team-agent/src/lifecycle/tests/team_key_retirement_txn_red.rs +1 -1
  135. package/crates/team-agent/src/lifecycle/tests/test_isolation_escape_contract.rs +60 -2
  136. package/crates/team-agent/src/lifecycle/tests/upgrade_compat_0211_red.rs +1 -1
  137. package/crates/team-agent/src/lifecycle/tests/verify_rs031_window_consistency_red.rs +2 -2
  138. package/crates/team-agent/src/lifecycle/tests/worker_spawn_env_red.rs +69 -26
  139. package/crates/team-agent/src/lifecycle/tests.rs +23 -15
  140. package/crates/team-agent/src/lifecycle/types.rs +61 -2
  141. package/crates/team-agent/src/lifecycle/worker_command_context.rs +200 -33
  142. package/crates/team-agent/src/mcp_server/tests/scoped.rs +100 -1
  143. package/crates/team-agent/src/mcp_server/tests.rs +196 -2
  144. package/crates/team-agent/src/messaging/delivery.rs +405 -40
  145. package/crates/team-agent/src/messaging/helpers.rs +2 -0
  146. package/crates/team-agent/src/messaging/leader_receiver.rs +53 -1
  147. package/crates/team-agent/src/messaging/results.rs +4 -0
  148. package/crates/team-agent/src/messaging/send.rs +34 -0
  149. package/crates/team-agent/src/messaging/tests/dup_inject.rs +406 -0
  150. package/crates/team-agent/src/messaging/tests/e23.rs +9 -0
  151. package/crates/team-agent/src/messaging/tests/leader_inject_acceptance.rs +66 -0
  152. package/crates/team-agent/src/messaging/tests/main_preserved.rs +1 -1
  153. package/crates/team-agent/src/messaging/tests/mod.rs +1 -0
  154. package/crates/team-agent/src/messaging/types.rs +4 -1
  155. package/crates/team-agent/src/model/enums.rs +14 -5
  156. package/crates/team-agent/src/model/permissions.rs +3 -0
  157. package/crates/team-agent/src/model/spec.rs +129 -6
  158. package/crates/team-agent/src/model/testdata/spec_invalid_a.yaml +3 -1
  159. package/crates/team-agent/src/model/testdata/team.spec.golden.yaml +3 -1
  160. package/crates/team-agent/src/model/testdata/team.spec.yaml +3 -1
  161. package/crates/team-agent/src/os_probe.rs +73 -2
  162. package/crates/team-agent/src/provider/adapter.rs +231 -4
  163. package/crates/team-agent/src/provider/adapters/claude.rs +5 -2
  164. package/crates/team-agent/src/provider/adapters/codex.rs +5 -2
  165. package/crates/team-agent/src/provider/adapters/copilot.rs +5 -2
  166. package/crates/team-agent/src/provider/adapters/cursor_agent.rs +86 -0
  167. package/crates/team-agent/src/provider/adapters/grok.rs +157 -0
  168. package/crates/team-agent/src/provider/adapters/mod.rs +2 -0
  169. package/crates/team-agent/src/provider/bypass_flags.rs +124 -0
  170. package/crates/team-agent/src/provider/classify.rs +4 -2
  171. package/crates/team-agent/src/provider/faults.rs +2 -1
  172. package/crates/team-agent/src/provider/mod.rs +13 -0
  173. package/crates/team-agent/src/provider/session/capture.rs +158 -20
  174. package/crates/team-agent/src/provider/session/context_fork/claude.rs +38 -1
  175. package/crates/team-agent/src/provider/session/context_fork/codex.rs +72 -1
  176. package/crates/team-agent/src/provider/session/context_fork/outcome.rs +57 -1
  177. package/crates/team-agent/src/provider/session/context_fork.rs +77 -3
  178. package/crates/team-agent/src/provider/session/mod.rs +18 -0
  179. package/crates/team-agent/src/provider/session/resume.rs +57 -0
  180. package/crates/team-agent/src/provider/session_scan/claude.rs +125 -1
  181. package/crates/team-agent/src/provider/session_scan/codex.rs +94 -1
  182. package/crates/team-agent/src/provider/session_scan/common.rs +204 -2
  183. package/crates/team-agent/src/provider/session_scan/copilot.rs +33 -1
  184. package/crates/team-agent/src/provider/session_scan/cursor.rs +538 -0
  185. package/crates/team-agent/src/provider/session_scan/grok.rs +288 -0
  186. package/crates/team-agent/src/provider/session_scan.rs +8 -0
  187. package/crates/team-agent/src/provider/submit_now.rs +94 -0
  188. package/crates/team-agent/src/provider/tests/adapter.rs +304 -0
  189. package/crates/team-agent/src/provider/types.rs +4 -2
  190. package/crates/team-agent/src/provider/wire.rs +23 -1
  191. package/crates/team-agent/src/state/persist.rs +301 -8
  192. package/crates/team-agent/src/state/repository.rs +5 -0
  193. package/crates/team-agent/src/tmux_backend/tests.rs +1737 -42
  194. package/crates/team-agent/src/tmux_backend.rs +1083 -75
  195. package/crates/team-agent/src/transport/test_support.rs +20 -0
  196. package/crates/team-agent/src/transport/tests/wire.rs +28 -2
  197. package/crates/team-agent/src/transport.rs +265 -1
  198. package/npm/install.mjs +129 -73
  199. package/package.json +4 -4
  200. package/skills/team-agent/SKILL.md +33 -238
  201. package/skills/team-agent/command-coverage.json +31 -0
  202. package/crates/team-agent/src/lifecycle/launch/approval.rs +0 -134
  203. package/crates/team-agent/src/lifecycle/launch/fork_agent/completion.rs +0 -59
  204. package/crates/team-agent/src/lifecycle/launch/fork_finalize.rs +0 -483
  205. package/crates/team-agent/src/lifecycle/launch/fork_pending.rs +0 -109
  206. package/crates/team-agent/src/lifecycle/launch/fork_state.rs +0 -447
  207. package/crates/team-agent/src/lifecycle/tests/codex_mcp_approval_inheritance_red.rs +0 -1187
  208. package/crates/team-agent/src/lifecycle/tests/worker_dangerous_bypass_argv_red.rs +0 -327
@@ -342,6 +342,22 @@ impl ProviderAdapter for BasicProviderAdapter {
342
342
  native_mcp_config: false,
343
343
  writes_global_settings: true,
344
344
  },
345
+ // Grok: --resume/--fork-session 齐全 → resume/fork true; 无原生
346
+ // --mcp-config flag → native_mcp_config false (MCP 走 .grok/config.toml)。
347
+ Provider::Grok => ProviderCaps {
348
+ resume: true,
349
+ fork: true,
350
+ native_mcp_config: false,
351
+ writes_global_settings: false,
352
+ },
353
+ // Cursor agent: --resume [chatId] 有 → resume true; 无 fork flag →
354
+ // fork false; 无 --mcp-config → native_mcp_config false。
355
+ Provider::CursorAgent => ProviderCaps {
356
+ resume: true,
357
+ fork: false,
358
+ native_mcp_config: false,
359
+ writes_global_settings: false,
360
+ },
345
361
  Provider::Fake => ProviderCaps {
346
362
  resume: false,
347
363
  fork: false,
@@ -389,6 +405,9 @@ impl ProviderAdapter for BasicProviderAdapter {
389
405
  // 标"weak / no auth-status command available";Compatible/Official 走 BYOK
390
406
  // 路径,有 COPILOT_PROVIDER_BASE_URL 时已脱离 GitHub 登录通道。
391
407
  Provider::Copilot => copilot_auth_hint(auth_mode),
408
+ // Cursor: 登录探测未接。U-17 前不得把未观测写成 Present(shim 对
409
+ // `cursor-agent status` 会假绿 Logged in)。缺键 ≠ 已知未登录,故不用 Missing。
410
+ Provider::CursorAgent => AuthHintStatus::Unknown,
392
411
  _ => match auth_mode {
393
412
  AuthMode::Subscription => AuthHintStatus::Present,
394
413
  AuthMode::OfficialApi | AuthMode::CompatibleApi => AuthHintStatus::MissingOrUnknown,
@@ -454,6 +473,24 @@ impl ProviderAdapter for BasicProviderAdapter {
454
473
  }
455
474
  Ok(argv)
456
475
  }
476
+ Provider::Grok => Ok(grok_launch_command(
477
+ self,
478
+ auth_mode,
479
+ mcp_config,
480
+ system_prompt,
481
+ model,
482
+ tools,
483
+ )?),
484
+ Provider::CursorAgent => Ok(cursor_agent_base_command(
485
+ self,
486
+ auth_mode,
487
+ mcp_config,
488
+ system_prompt,
489
+ model,
490
+ tools,
491
+ false,
492
+ None,
493
+ )?),
457
494
  Provider::Fake => Ok(fake_worker_command()),
458
495
  }
459
496
  }
@@ -543,6 +580,32 @@ impl ProviderAdapter for BasicProviderAdapter {
543
580
  // * `-C <workspace>`(双保险,即便 spawn cwd 漂移也能锚定)
544
581
  // mcp_config inline 形态由 build_command 写入,launch 路径会用
545
582
  // point_native_mcp_config_at_file 重写为 @<file> 形(§C1 note)。
583
+ Provider::Grok => {
584
+ // Align with Claude/Copilot: the UUID on `--session-id` is
585
+ // also the capture hint. `CommandPlan::argv_only` used to
586
+ // drop expected_session_id, so `_pending_session_id` was
587
+ // never written and restart could not resume.
588
+ let expected = next_session_token();
589
+ let mut argv = grok_base_command(
590
+ self,
591
+ ctx.auth_mode,
592
+ ctx.mcp_config,
593
+ ctx.system_prompt,
594
+ ctx.model,
595
+ ctx.tools,
596
+ ctx.profile_launch
597
+ .is_some_and(|profile| profile.managed_mcp_config),
598
+ ctx.effort,
599
+ )?;
600
+ argv.push("--session-id".to_string());
601
+ argv.push(expected.clone());
602
+ Ok(CommandPlan {
603
+ argv,
604
+ expected_session_id: Some(SessionId::new(expected)),
605
+ provider_projects_root: None,
606
+ managed_mcp_config: false,
607
+ })
608
+ }
546
609
  Provider::Copilot => {
547
610
  let expected = next_session_token();
548
611
  let mut argv = copilot_base_command(
@@ -561,6 +624,27 @@ impl ProviderAdapter for BasicProviderAdapter {
561
624
  managed_mcp_config: false,
562
625
  })
563
626
  }
627
+ Provider::CursorAgent => {
628
+ // U-01 create-chat 无登录超时;禁止发明 --session-id。
629
+ // pending 只能是 CLI chatId,本拍不造假 uuid。
630
+ let argv = cursor_agent_base_command(
631
+ self,
632
+ ctx.auth_mode,
633
+ ctx.mcp_config,
634
+ ctx.system_prompt,
635
+ ctx.model,
636
+ ctx.tools,
637
+ ctx.profile_launch
638
+ .is_some_and(|profile| profile.managed_mcp_config),
639
+ ctx.effort,
640
+ )?;
641
+ Ok(CommandPlan {
642
+ argv,
643
+ expected_session_id: None,
644
+ provider_projects_root: None,
645
+ managed_mcp_config: false,
646
+ })
647
+ }
564
648
  _ => self
565
649
  .build_command_with_tools(
566
650
  ctx.auth_mode,
@@ -725,6 +809,40 @@ impl ProviderAdapter for BasicProviderAdapter {
725
809
  argv.push(session_id.as_str().to_string());
726
810
  Ok(argv)
727
811
  }
812
+ // Grok resume: base + `--resume <id>` (grok -r/--resume 接受 id|title)。
813
+ Provider::Grok => {
814
+ let mut argv = grok_base_command(
815
+ self,
816
+ auth_mode,
817
+ mcp_config,
818
+ system_prompt,
819
+ model,
820
+ tools,
821
+ false,
822
+ None,
823
+ )?;
824
+ argv.push("--resume".to_string());
825
+ argv.push(session_id.as_str().to_string());
826
+ Ok(argv)
827
+ }
828
+ // Cursor resume: base + `--resume <chatId>`。
829
+ Provider::CursorAgent => {
830
+ let mut argv = cursor_agent_base_command(
831
+ self,
832
+ auth_mode,
833
+ mcp_config,
834
+ system_prompt,
835
+ model,
836
+ tools,
837
+ false,
838
+ None,
839
+ )?;
840
+ // Put --resume immediately after `agent` so the CLI treats it as
841
+ // the session mode rather than a trailing flag after --workspace.
842
+ argv.insert(1, "--resume".to_string());
843
+ argv.insert(2, session_id.as_str().to_string());
844
+ Ok(argv)
845
+ }
728
846
  Provider::GeminiCli | Provider::Fake => Err(ProviderError::ResumeUnavailable(format!(
729
847
  "{} resume requires session_id",
730
848
  provider_wire(self.provider)
@@ -801,6 +919,54 @@ impl ProviderAdapter for BasicProviderAdapter {
801
919
  argv.push(session_id.as_str().to_string());
802
920
  Ok(CommandPlan::argv_only(argv))
803
921
  }
922
+ Provider::Grok => {
923
+ let Some(session_id) = session_id else {
924
+ return Err(ProviderError::ResumeUnavailable(
925
+ "resume requires session_id".to_string(),
926
+ ));
927
+ };
928
+ let mut argv = grok_base_command(
929
+ self,
930
+ ctx.auth_mode,
931
+ ctx.mcp_config,
932
+ ctx.system_prompt,
933
+ ctx.model,
934
+ ctx.tools,
935
+ ctx.profile_launch
936
+ .is_some_and(|profile| profile.managed_mcp_config),
937
+ ctx.effort,
938
+ )?;
939
+ argv.push("--resume".to_string());
940
+ argv.push(session_id.as_str().to_string());
941
+ Ok(CommandPlan::argv_only(argv))
942
+ }
943
+ Provider::CursorAgent => {
944
+ let Some(session_id) = session_id else {
945
+ return Err(ProviderError::ResumeUnavailable(
946
+ "cursor_agent resume requires chatId; empty --resume is forbidden (picker)".to_string(),
947
+ ));
948
+ };
949
+ let raw = session_id.as_str();
950
+ if raw.is_empty() || raw.contains('/') || raw.contains('\\') || raw.contains('\0') {
951
+ return Err(ProviderError::ResumeUnavailable(
952
+ "cursor_agent resume rejected forged or empty chatId".to_string(),
953
+ ));
954
+ }
955
+ let mut argv = cursor_agent_base_command(
956
+ self,
957
+ ctx.auth_mode,
958
+ ctx.mcp_config,
959
+ ctx.system_prompt,
960
+ ctx.model,
961
+ ctx.tools,
962
+ ctx.profile_launch
963
+ .is_some_and(|profile| profile.managed_mcp_config),
964
+ ctx.effort,
965
+ )?;
966
+ argv.push("--resume".to_string());
967
+ argv.push(raw.to_string());
968
+ Ok(CommandPlan::argv_only(argv))
969
+ }
804
970
  _ => self
805
971
  .build_resume_command_with_context(
806
972
  session_id,
@@ -882,7 +1048,27 @@ impl ProviderAdapter for BasicProviderAdapter {
882
1048
  Provider::Copilot => Err(ProviderError::CapabilityUnsupported(
883
1049
  "copilot CLI 无 fork 旗标,session-store 不支持 branched continuation".to_string(),
884
1050
  )),
885
- Provider::GeminiCli | Provider::Fake => {
1051
+ // Grok fork: base + 新 `--session-id` + `--resume <src>` + `--fork-session`
1052
+ // (grok help: --fork-session 需配合 --resume/--continue)。
1053
+ Provider::Grok => {
1054
+ let mut argv = grok_base_command(
1055
+ self,
1056
+ auth_mode,
1057
+ mcp_config,
1058
+ system_prompt,
1059
+ model,
1060
+ tools,
1061
+ false,
1062
+ None,
1063
+ )?;
1064
+ argv.push("--session-id".to_string());
1065
+ argv.push(next_session_token());
1066
+ argv.push("--resume".to_string());
1067
+ argv.push(session_id.as_str().to_string());
1068
+ argv.push("--fork-session".to_string());
1069
+ Ok(argv)
1070
+ }
1071
+ Provider::CursorAgent | Provider::GeminiCli | Provider::Fake => {
886
1072
  Err(ProviderError::CapabilityUnsupported(format!(
887
1073
  "{} does not support native session fork",
888
1074
  provider_wire(self.provider)
@@ -1006,6 +1192,30 @@ impl ProviderAdapter for BasicProviderAdapter {
1006
1192
  managed_mcp_config: profile.managed_mcp_config,
1007
1193
  })
1008
1194
  }
1195
+ Provider::Grok => {
1196
+ let Some(session_id) = session_id else {
1197
+ return Err(ProviderError::ResumeUnavailable(
1198
+ "fork requires session_id".to_string(),
1199
+ ));
1200
+ };
1201
+ let mut argv = grok_base_command(
1202
+ self,
1203
+ ctx.auth_mode,
1204
+ ctx.mcp_config,
1205
+ ctx.system_prompt,
1206
+ ctx.model,
1207
+ ctx.tools,
1208
+ ctx.profile_launch
1209
+ .is_some_and(|profile| profile.managed_mcp_config),
1210
+ ctx.effort,
1211
+ )?;
1212
+ argv.push("--session-id".to_string());
1213
+ argv.push(next_session_token());
1214
+ argv.push("--resume".to_string());
1215
+ argv.push(session_id.as_str().to_string());
1216
+ argv.push("--fork-session".to_string());
1217
+ Ok(CommandPlan::argv_only(argv))
1218
+ }
1009
1219
  _ => self
1010
1220
  .fork_with_context(
1011
1221
  session_id,
@@ -1061,9 +1271,17 @@ impl ProviderAdapter for BasicProviderAdapter {
1061
1271
  r"working|processing",
1062
1272
  r"Error|panic",
1063
1273
  ),
1064
- Provider::GeminiCli | Provider::Fake => {
1274
+ // Grok: 暂无专有 status 正则, 沿用 generic。
1275
+ Provider::Grok | Provider::GeminiCli | Provider::Fake => {
1065
1276
  patterns(r">", r"working|processing", r"Error|Traceback")
1066
1277
  }
1278
+ // Cursor: U-15 未过前不得用 generic `>` 单独判已证实 idle。
1279
+ // 字面量 `cursor-idle-unset-until-u15` 不会出现在屏上。
1280
+ Provider::CursorAgent => patterns(
1281
+ r"cursor-idle-unset-until-u15",
1282
+ r"cursor-busy-unset-until-u15",
1283
+ r"Error|Traceback",
1284
+ ),
1067
1285
  }
1068
1286
  }
1069
1287
 
@@ -1164,7 +1382,9 @@ pub(crate) fn json_inline(value: &serde_json::Value) -> String {
1164
1382
  use super::adapters::claude::{claude_base_command, claude_launch_command};
1165
1383
  use super::adapters::codex::codex_base_command;
1166
1384
  use super::adapters::copilot::{copilot_base_command, copilot_base_command_resume};
1385
+ use super::adapters::cursor_agent::cursor_agent_base_command;
1167
1386
  use super::adapters::fake::fake_worker_command;
1387
+ use super::adapters::grok::{grok_base_command, grok_launch_command};
1168
1388
 
1169
1389
  /// Contract C / MUST-8: the per-worker Team Agent MCP server config used by Claude
1170
1390
  /// (`--mcp-config`) and Codex (`-c mcp_servers.*` injection). Placeholders
@@ -1249,9 +1469,16 @@ pub(crate) fn next_session_token() -> String {
1249
1469
  #[cfg(test)]
1250
1470
  mod fork_materialization_source_guard {
1251
1471
  #[test]
1252
- fn lifecycle_uses_provider_neutral_fork_materialization_dispatch() {
1472
+ fn lifecycle_uses_in_window_fork_not_session_file_materialization() {
1253
1473
  let source = include_str!("../lifecycle/launch/fork_agent.rs");
1254
- assert!(source.contains(".materialize_fork_backing("));
1474
+ assert!(
1475
+ source.contains("in_window_fork(") && source.contains("inject_clean_command"),
1476
+ "fork must stay on the shared in-window inject path"
1477
+ );
1478
+ assert!(
1479
+ !source.contains(".materialize_fork_backing("),
1480
+ "session-file fork materialization must stay gone"
1481
+ );
1255
1482
  assert!(!source.contains("materialize_codex_fork"));
1256
1483
  assert!(!source.contains("codex_fork"));
1257
1484
  }
@@ -8,7 +8,7 @@
8
8
  //! resolver (`claude_context_model`) stay in `adapter.rs`; capture scanning
9
9
  //! helpers now live under `provider/session_scan/claude.rs`.
10
10
 
11
- use crate::model::enums::AuthMode;
11
+ use crate::model::enums::{AuthMode, Provider};
12
12
  use crate::provider::adapter::{next_session_token, prompt_needs_native_mcp, BasicProviderAdapter};
13
13
  use crate::provider::{McpConfig, ProviderAdapter, ProviderError};
14
14
 
@@ -49,7 +49,10 @@ pub(crate) fn claude_base_command(
49
49
  ) -> Result<Vec<String>, ProviderError> {
50
50
  let mut argv = vec!["claude".to_string()];
51
51
  if claude_dangerous_auto_approve(tools) {
52
- argv.push("--dangerously-skip-permissions".to_string());
52
+ // 0.5.66 bypass 单源:flag 由 provider_bypass_flag 表供给(单源)
53
+ let flag = crate::provider::bypass_flags::provider_bypass_flag(Provider::Claude)
54
+ .expect("claude provider must define a bypass flag");
55
+ argv.push(flag.to_string());
53
56
  } else {
54
57
  argv.push("--permission-mode".to_string());
55
58
  argv.push("default".to_string());
@@ -6,7 +6,7 @@
6
6
  //! `json_inline` stays in `adapter.rs` because it is also used by other
7
7
  //! sites; this file reaches it via `super::*`.
8
8
 
9
- use crate::model::enums::AuthMode;
9
+ use crate::model::enums::{AuthMode, Provider};
10
10
  use crate::provider::adapter::json_inline;
11
11
  use crate::provider::{McpConfig, ProviderCommandOverrides};
12
12
 
@@ -41,7 +41,10 @@ pub(crate) fn codex_base_command(
41
41
  argv.push(profile.to_string());
42
42
  }
43
43
  if codex_dangerous_auto_approve(tools) {
44
- argv.push("--dangerously-bypass-approvals-and-sandbox".to_string());
44
+ // 0.5.66 bypass 单源:flag 由 provider_bypass_flag 表供给。
45
+ let flag = crate::provider::bypass_flags::provider_bypass_flag(Provider::Codex)
46
+ .expect("codex provider must define a bypass flag");
47
+ argv.push(flag.to_string());
45
48
  } else {
46
49
  argv.push("--sandbox".to_string());
47
50
  argv.push(codex_sandbox_mode(tools).to_string());
@@ -7,7 +7,7 @@
7
7
  //! translation. Auth hint (`copilot_auth_hint`) stays in `adapter.rs`;
8
8
  //! session-store scanning lives under `provider/session_scan/copilot.rs`.
9
9
 
10
- use crate::model::enums::AuthMode;
10
+ use crate::model::enums::{AuthMode, Provider};
11
11
  use crate::provider::McpConfig;
12
12
 
13
13
  pub(crate) fn copilot_base_command(
@@ -29,7 +29,10 @@ pub(crate) fn copilot_base_command(
29
29
  "--disable-builtin-mcps".to_string(),
30
30
  ];
31
31
  if copilot_dangerous_auto_approve(tools) {
32
- argv.push("--allow-all".to_string());
32
+ // 0.5.66 bypass 单源:flag 由 provider_bypass_flag 表供给。
33
+ let flag = crate::provider::bypass_flags::provider_bypass_flag(Provider::Copilot)
34
+ .expect("copilot provider must define a bypass flag");
35
+ argv.push(flag.to_string());
33
36
  } else {
34
37
  for flag in copilot_permission_flags(tools) {
35
38
  argv.push(flag);
@@ -0,0 +1,86 @@
1
+ //! ---
2
+ //! purpose: Cursor agent CLI argv;role 走 .cursor/rules,MCP 走 mcp.json overlay
3
+ //! contract:
4
+ //! provides:
5
+ //! - name: cursor_agent_base_command
6
+ //! what: 只组已实测文档化 flag;mcp_config 不入 argv,由 launch overlay 写盘
7
+ //! boundary:
8
+ //! - 不调未文档化 flag(--system-prompt / --allowed-tools)
9
+ //! - 不写 grok 那种 cwd 独占闸
10
+ //! - 不打印代理值
11
+ //! maturity: wired
12
+ //! ---
13
+ //!
14
+ //! Cursor `agent` CLI(与 `cursor-agent` 同二进制)。主路径与
15
+ //! `.team/scripts/cursor_seat.sh` 实测一致:
16
+ //! `--trust --sandbox disabled --workspace <物理路径> [--force] [--model]`
17
+ //! Role 不入 argv,写 `<workspace>/.cursor/rules/*.mdc` + `alwaysApply: true`。
18
+ //! MCP 无 `--mcp-config`;身份必须写进 `.cursor/mcp.json` 的 env 表
19
+ //! (cursor 不把父进程 TEAM_AGENT_* 传给 MCP 子进程)。
20
+ //!
21
+ //! 隐藏 flag `--system-prompt` / `--allowed-tools` 实测存在但 help 未列,
22
+ //! 随时可能消失。可以在注释里记录,代码里不许调。
23
+ //! `--allowed-tools` 正反行为未验证,不写「支持工具白名单」。
24
+
25
+ use crate::model::enums::AuthMode;
26
+ use crate::provider::adapter::BasicProviderAdapter;
27
+ use crate::provider::{McpConfig, ProviderError};
28
+
29
+ pub(crate) fn cursor_agent_launch_command(
30
+ adapter: &BasicProviderAdapter,
31
+ auth_mode: AuthMode,
32
+ mcp_config: Option<&McpConfig>,
33
+ system_prompt: Option<&str>,
34
+ model: Option<&str>,
35
+ tools: &[&str],
36
+ ) -> Result<Vec<String>, ProviderError> {
37
+ cursor_agent_base_command(
38
+ adapter,
39
+ auth_mode,
40
+ mcp_config,
41
+ system_prompt,
42
+ model,
43
+ tools,
44
+ false,
45
+ None,
46
+ )
47
+ }
48
+
49
+ pub(crate) fn cursor_agent_base_command(
50
+ adapter: &BasicProviderAdapter,
51
+ auth_mode: AuthMode,
52
+ mcp_config: Option<&McpConfig>,
53
+ system_prompt: Option<&str>,
54
+ model: Option<&str>,
55
+ tools: &[&str],
56
+ managed_mcp_config: bool,
57
+ effort: Option<crate::model::enums::ProviderEffort>,
58
+ ) -> Result<Vec<String>, ProviderError> {
59
+ let mut argv = vec!["agent".to_string()];
60
+ // --trust 跳过 Workspace Trust 闸(已实测)。无此 flag 会停在 Do you trust。
61
+ argv.push("--trust".to_string());
62
+ if cursor_agent_dangerous_auto_approve(tools) {
63
+ argv.push("--force".to_string());
64
+ }
65
+ // 与 cursor_seat.sh 主路径一致。沙箱实际隔离面未再拆,但 flag 本身已实测。
66
+ argv.push("--sandbox".to_string());
67
+ argv.push("disabled".to_string());
68
+ if let Some(model) = model {
69
+ argv.push("--model".to_string());
70
+ argv.push(model.to_string());
71
+ }
72
+ // Cursor `--effort` flag 不存在;框架在调用方丢掉 effort。绝不发明 flag。
73
+ let _ = effort;
74
+ // system_prompt 不入 argv(help 无 --rules / --append-system-prompt)。
75
+ // launch 写 `<workspace>/.cursor/rules/team-agent-role-<agent_id>.mdc`。
76
+ // mcp_config 也不入 argv(无 --mcp-config)。launch 写 `.cursor/mcp.json`
77
+ // 并 `agent mcp enable team_orchestrator`。这里收下以免静默丢弃。
78
+ let _ = (adapter, auth_mode, mcp_config, managed_mcp_config, system_prompt);
79
+ argv.push("--workspace".to_string());
80
+ argv.push("{workspace}".to_string());
81
+ Ok(argv)
82
+ }
83
+
84
+ pub(crate) fn cursor_agent_dangerous_auto_approve(tools: &[&str]) -> bool {
85
+ tools.contains(&"dangerous_auto_approve")
86
+ }
@@ -0,0 +1,157 @@
1
+ //!
2
+ //! purpose: Grok CLI argv + permission deny 映射;MCP 不走 CLI flag
3
+ //! contract: launch 写 `<cwd>/.grok/config.toml`;未登录 / 目录未信任必须拒绝启动。
4
+ //! 角色缺 model 必须拒绝启动(禁止内建 / team / CLI 任何隐式默认)。
5
+ //! 未知工具映射记成 Unsupported,不发明 deny 名
6
+ //! mcp_injection: dir_scoped —— 每席必须独立工作目录;同 cwd 多席会静默串台,故拒绝。
7
+ //! 对照 claude/codex 是 argv 作用域(`--mcp-config`),同目录多席没有这个问题。
8
+ //! 本版 exclusive 检查不读 per-agent cwd,一个 workspace 只支持一个 grok 席。
9
+ //! 这是 Provider::Grok 的能力边界,不是框架对所有 provider 的限制。
10
+ //! boundary: 只服务 Provider::Grok。不改 claude/codex/copilot 路径
11
+ //!
12
+ //! Grok CLI provider-local command builders + permission helpers.
13
+ //!
14
+ //! Mirrors `adapters/claude.rs` (0.5.67 provider-adapter step). Pure
15
+ //! flag-name adaptation over the claude skeleton — no new abstraction
16
+ //! layers, no public-API changes outside the provider dispatch.
17
+ //!
18
+ //! Grok CLI flag map (亲核 attest 0.5.67 + grok-full-help.txt):
19
+ //! bypass → `--always-approve` ("Auto-approve all tool executions")
20
+ //! system → `--rules <RULES>` ("Extra rules to append to the system prompt")
21
+ //! model → `-m, --model <MODEL>`
22
+ //! session → `-s, --session-id <SESSION_ID>` (fresh spawn)
23
+ //! resume → `-r, --resume [<ID_OR_TITLE>]` / `-c, --continue`
24
+ //! fork → `--fork-session` (with --resume)
25
+ //! effort → `--effort <level>` (alias of `--reasoning-effort`)
26
+ //! grok accepts low|medium|high|xhigh; CLI rejects `max`
27
+ //! deny → `--disallowed-tools` (compat alias `--disallowedTools`)
28
+ //! cwd → `--cwd <CWD>` / `-w, --worktree [<WORKTREE>]`
29
+ //!
30
+ //! No native `--mcp-config` flag on the Grok CLI (`grok mcp` is a subcommand)
31
+ //! → `native_mcp_config: false`; MCP reaches the worker via launch-path
32
+ //! `<cwd>/.grok/config.toml` (`apply_grok_mcp_overlay`).
33
+
34
+ use crate::model::enums::AuthMode;
35
+ use crate::provider::adapter::{next_session_token, BasicProviderAdapter};
36
+ use crate::provider::{McpConfig, ProviderError};
37
+
38
+ pub(crate) fn grok_launch_command(
39
+ adapter: &BasicProviderAdapter,
40
+ auth_mode: AuthMode,
41
+ mcp_config: Option<&McpConfig>,
42
+ system_prompt: Option<&str>,
43
+ model: Option<&str>,
44
+ tools: &[&str],
45
+ ) -> Result<Vec<String>, ProviderError> {
46
+ let mut argv = grok_base_command(
47
+ adapter,
48
+ auth_mode,
49
+ mcp_config,
50
+ system_prompt,
51
+ model,
52
+ tools,
53
+ false,
54
+ None,
55
+ )?;
56
+ argv.push("--session-id".to_string());
57
+ argv.push(next_session_token());
58
+ Ok(argv)
59
+ }
60
+
61
+ pub(crate) fn grok_base_command(
62
+ adapter: &BasicProviderAdapter,
63
+ auth_mode: AuthMode,
64
+ mcp_config: Option<&McpConfig>,
65
+ system_prompt: Option<&str>,
66
+ model: Option<&str>,
67
+ tools: &[&str],
68
+ managed_mcp_config: bool,
69
+ effort: Option<crate::model::enums::ProviderEffort>,
70
+ ) -> Result<Vec<String>, ProviderError> {
71
+ let mut argv = vec!["grok".to_string()];
72
+ if grok_dangerous_auto_approve(tools) {
73
+ argv.push("--always-approve".to_string());
74
+ }
75
+ let model = match model.map(str::trim).filter(|value| !value.is_empty()) {
76
+ Some(model) => model,
77
+ None => {
78
+ return Err(ProviderError::Command(
79
+ "grok launch requires an explicit model. \
80
+ Without an explicit model the framework fills a built-in default (grok-4 for grok), \
81
+ so the seat silently gets a model and context window that are not in the role file, \
82
+ while argv still looks normal. The role file must name the model itself; \
83
+ built-in defaults, team-level defaults, and the Grok CLI global default are all implicit sources. \
84
+ Set the role front-matter field, for example:\n\
85
+ model: grok-4.6"
86
+ .to_string(),
87
+ ));
88
+ }
89
+ };
90
+ argv.push("--model".to_string());
91
+ argv.push(model.to_string());
92
+ if let Some(effort) = effort {
93
+ // Grok accepts `--effort` as alias for `--reasoning-effort`.
94
+ argv.push("--effort".to_string());
95
+ argv.push(effort.as_str().to_string());
96
+ }
97
+ if let Some(prompt) = system_prompt {
98
+ argv.push("--rules".to_string());
99
+ argv.push(prompt.to_string());
100
+ }
101
+ // Grok CLI has no `--mcp-config` flag — the claude inline-MCP block is
102
+ // intentionally absent. Launch writes `<cwd>/.grok/config.toml`.
103
+ let _ = (adapter, auth_mode, mcp_config, managed_mcp_config);
104
+ for tool in grok_disallowed_tools(tools) {
105
+ argv.push("--disallowedTools".to_string());
106
+ argv.push(tool.to_string());
107
+ }
108
+ Ok(argv)
109
+ }
110
+
111
+ pub(crate) fn grok_dangerous_auto_approve(tools: &[&str]) -> bool {
112
+ tools.contains(&"dangerous_auto_approve")
113
+ }
114
+
115
+ pub(crate) fn grok_disallowed_tools(tools: &[&str]) -> Vec<&'static str> {
116
+ let mut disallowed = Vec::new();
117
+ for tool in [
118
+ "execute_bash",
119
+ "fs_read",
120
+ "fs_write",
121
+ "fs_list",
122
+ "network",
123
+ "git_diff",
124
+ "mcp_team",
125
+ "provider_builtin",
126
+ ] {
127
+ if tools.contains(&tool) {
128
+ continue;
129
+ }
130
+ match grok_tool_mapping(tool) {
131
+ GrokToolMapping::Deny(names) => disallowed.extend(names),
132
+ GrokToolMapping::Unsupported | GrokToolMapping::Bypass => {}
133
+ }
134
+ }
135
+ disallowed
136
+ }
137
+
138
+ /// Canonical tool → grok CLI deny names. Unknown tools stay Unsupported
139
+ /// (no invented `--disallowedTools` token).
140
+ pub(crate) fn grok_tool_mapping(tool: &str) -> GrokToolMapping {
141
+ match tool {
142
+ "execute_bash" => GrokToolMapping::Deny(&["Bash"]),
143
+ "fs_read" => GrokToolMapping::Deny(&["Read"]),
144
+ "fs_write" => GrokToolMapping::Deny(&["Edit", "Write", "MultiEdit", "NotebookEdit"]),
145
+ "fs_list" => GrokToolMapping::Deny(&["Glob", "Grep"]),
146
+ "dangerous_auto_approve" => GrokToolMapping::Bypass,
147
+ "network" | "git_diff" | "mcp_team" | "provider_builtin" => GrokToolMapping::Unsupported,
148
+ _ => GrokToolMapping::Unsupported,
149
+ }
150
+ }
151
+
152
+ #[derive(Debug, Clone, Copy, PartialEq, Eq)]
153
+ pub(crate) enum GrokToolMapping {
154
+ Deny(&'static [&'static str]),
155
+ Bypass,
156
+ Unsupported,
157
+ }
@@ -28,3 +28,5 @@ pub(crate) mod codex;
28
28
  pub(crate) mod copilot;
29
29
  pub(crate) mod copilot_fork;
30
30
  pub(crate) mod fake;
31
+ pub(crate) mod grok;
32
+ pub(crate) mod cursor_agent;