@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.
- package/Cargo.lock +8 -1
- package/Cargo.toml +1 -1
- package/crates/team-agent/Cargo.toml +6 -0
- package/crates/team-agent/src/cli/adapters.rs +6 -1
- package/crates/team-agent/src/cli/diagnose.rs +82 -0
- package/crates/team-agent/src/cli/emit.rs +3 -3
- package/crates/team-agent/src/cli/grok_slot.rs +299 -0
- package/crates/team-agent/src/cli/leader.rs +21 -7
- package/crates/team-agent/src/cli/leaders.rs +125 -1
- package/crates/team-agent/src/cli/mod.rs +20 -0
- package/crates/team-agent/src/cli/send/presentation.rs +7 -1
- package/crates/team-agent/src/cli/spec.rs +2 -0
- package/crates/team-agent/src/cli/status_port/compact.rs +28 -0
- package/crates/team-agent/src/cli/status_port/snapshot.rs +25 -1
- package/crates/team-agent/src/cli/tests/base.rs +26 -3
- package/crates/team-agent/src/cli/tests/compile.rs +1 -1
- package/crates/team-agent/src/cli/tests/missing_subcommands.rs +129 -19
- package/crates/team-agent/src/cli/tests/mod.rs +2 -2
- package/crates/team-agent/src/cli/tests/run_delegation.rs +1 -1
- package/crates/team-agent/src/cli/tests/shutdown_kill_plan.rs +387 -6
- package/crates/team-agent/src/cli/tests/status_send.rs +79 -10
- package/crates/team-agent/src/cli/tests/verb_validate.rs +1 -1
- package/crates/team-agent/src/communication_mode/mod.rs +6 -4
- package/crates/team-agent/src/compiler/tests.rs +23 -20
- package/crates/team-agent/src/compiler.rs +84 -5
- package/crates/team-agent/src/conpty/backend.rs +16 -0
- package/crates/team-agent/src/coordinator/backoff.rs +55 -0
- package/crates/team-agent/src/coordinator/conpty_shim.rs +82 -0
- package/crates/team-agent/src/coordinator/health.rs +173 -0
- package/crates/team-agent/src/coordinator/mod.rs +31 -0
- package/crates/team-agent/src/coordinator/orphan.rs +31 -0
- package/crates/team-agent/src/coordinator/runtime_detectors.rs +30 -0
- package/crates/team-agent/src/coordinator/runtime_observation.rs +25 -0
- package/crates/team-agent/src/coordinator/steps/abnormal.rs +59 -0
- package/crates/team-agent/src/coordinator/steps/delivery.rs +10 -0
- package/crates/team-agent/src/coordinator/steps/health_sync.rs +10 -0
- package/crates/team-agent/src/coordinator/steps/mod.rs +22 -0
- package/crates/team-agent/src/coordinator/steps/persist.rs +10 -0
- package/crates/team-agent/src/coordinator/steps/runtime_prompts.rs +10 -0
- package/crates/team-agent/src/coordinator/steps/session_gate.rs +10 -0
- package/crates/team-agent/src/coordinator/tick.rs +133 -22
- package/crates/team-agent/src/coordinator/types.rs +49 -0
- package/crates/team-agent/src/db/message_store.rs +39 -5
- package/crates/team-agent/src/layout/worker_env.rs +20 -3
- package/crates/team-agent/src/layout/worker_window_helpers.rs +2 -0
- package/crates/team-agent/src/leader/provider_attribution.rs +53 -0
- package/crates/team-agent/src/leader/registry.rs +65 -0
- package/crates/team-agent/src/leader/start.rs +1080 -58
- package/crates/team-agent/src/leader/tests/team_in_team_state_scope_red.rs +1 -1
- package/crates/team-agent/src/lifecycle/display.rs +56 -0
- package/crates/team-agent/src/lifecycle/helpers.rs +57 -0
- package/crates/team-agent/src/lifecycle/launch/add_agent.rs +332 -14
- package/crates/team-agent/src/lifecycle/launch/add_agent_state.rs +69 -2
- package/crates/team-agent/src/lifecycle/launch/agent_state.rs +196 -2
- package/crates/team-agent/src/lifecycle/launch/clone_agent.rs +101 -11
- package/crates/team-agent/src/lifecycle/launch/cursor_create_chat.rs +229 -0
- package/crates/team-agent/src/lifecycle/launch/cursor_mcp.rs +332 -0
- package/crates/team-agent/src/lifecycle/launch/fork_agent.rs +204 -457
- package/crates/team-agent/src/lifecycle/launch/fork_entry.rs +24 -0
- package/crates/team-agent/src/lifecycle/launch/grok_per_seat.rs +260 -0
- package/crates/team-agent/src/lifecycle/launch/identity.rs +146 -0
- package/crates/team-agent/src/lifecycle/launch/layout.rs +60 -0
- package/crates/team-agent/src/lifecycle/launch/leader_context.rs +112 -0
- package/crates/team-agent/src/lifecycle/launch/mcp_config.rs +530 -0
- package/crates/team-agent/src/lifecycle/launch/ownership.rs +40 -0
- package/crates/team-agent/src/lifecycle/launch/plan.rs +31 -0
- package/crates/team-agent/src/lifecycle/launch/quick_start.rs +66 -0
- package/crates/team-agent/src/lifecycle/launch/quick_start_transport.rs +78 -0
- package/crates/team-agent/src/lifecycle/launch/readiness.rs +85 -38
- package/crates/team-agent/src/lifecycle/launch/role_source.rs +44 -44
- package/crates/team-agent/src/lifecycle/launch/spawn.rs +101 -4
- package/crates/team-agent/src/lifecycle/launch/spec_state.rs +244 -48
- package/crates/team-agent/src/lifecycle/launch/state_projection.rs +109 -2
- package/crates/team-agent/src/lifecycle/launch/worker_env.rs +214 -1
- package/crates/team-agent/src/lifecycle/launch.rs +209 -43
- package/crates/team-agent/src/lifecycle/lock.rs +42 -1
- package/crates/team-agent/src/lifecycle/mod.rs +11 -0
- package/crates/team-agent/src/lifecycle/pane_input_lock.rs +161 -0
- package/crates/team-agent/src/lifecycle/profile_launch.rs +98 -0
- package/crates/team-agent/src/lifecycle/profile_smoke.rs +51 -1
- package/crates/team-agent/src/lifecycle/restart/agent.rs +213 -3
- package/crates/team-agent/src/lifecycle/restart/common.rs +373 -18
- package/crates/team-agent/src/lifecycle/restart/orchestrator.rs +27 -0
- package/crates/team-agent/src/lifecycle/restart/preflight.rs +25 -0
- package/crates/team-agent/src/lifecycle/restart/rebuild.rs +165 -15
- package/crates/team-agent/src/lifecycle/restart/remove.rs +196 -5
- package/crates/team-agent/src/lifecycle/restart/selection.rs +72 -0
- package/crates/team-agent/src/lifecycle/restart/team_state.rs +22 -0
- package/crates/team-agent/src/lifecycle/restart.rs +29 -0
- package/crates/team-agent/src/lifecycle/tests/acceptance_b_batch_red.rs +1 -1
- package/crates/team-agent/src/lifecycle/tests/agent_ops.rs +3 -4
- package/crates/team-agent/src/lifecycle/tests/behavioral_diff_264_red.rs +1 -1
- package/crates/team-agent/src/lifecycle/tests/claude_compatible_config_red.rs +2 -2
- package/crates/team-agent/src/lifecycle/tests/claude_profile_launch_red.rs +4 -4
- package/crates/team-agent/src/lifecycle/tests/clone_agent_preserves_source_tools.rs +309 -0
- package/crates/team-agent/src/lifecycle/tests/clone_fork_copilot_perms_red.rs +159 -174
- package/crates/team-agent/src/lifecycle/tests/communication_mode_runtime_contract_red.rs +2 -2
- package/crates/team-agent/src/lifecycle/tests/copilot_provider_red.rs +15 -13
- package/crates/team-agent/src/lifecycle/tests/core.rs +4 -18
- package/crates/team-agent/src/lifecycle/tests/core_034_real_red.rs +1 -1
- package/crates/team-agent/src/lifecycle/tests/cursor_mcp_overlay.rs +287 -0
- package/crates/team-agent/src/lifecycle/tests/cursor_require_explicit_model_red.rs +229 -0
- package/crates/team-agent/src/lifecycle/tests/cursor_restart_resume_red.rs +353 -0
- package/crates/team-agent/src/lifecycle/tests/display_adaptive_red.rs +1 -1
- package/crates/team-agent/src/lifecycle/tests/f032_startup_prompt_best_effort_red.rs +1 -1
- package/crates/team-agent/src/lifecycle/tests/g1_silent_faces.rs +784 -0
- package/crates/team-agent/src/lifecycle/tests/gate_fixtures.rs +562 -0
- package/crates/team-agent/src/lifecycle/tests/grok_effort_argv_red.rs +239 -0
- package/crates/team-agent/src/lifecycle/tests/grok_mcp_overlay_red.rs +498 -0
- package/crates/team-agent/src/lifecycle/tests/grok_require_explicit_model_red.rs +250 -0
- package/crates/team-agent/src/lifecycle/tests/grok_restart_resume_red.rs +293 -0
- package/crates/team-agent/src/lifecycle/tests/harvest2_a_batch_red.rs +3 -0
- package/crates/team-agent/src/lifecycle/tests/host_cotenant_death_p0_contract.rs +3 -3
- package/crates/team-agent/src/lifecycle/tests/lane_ops.rs +65 -40
- package/crates/team-agent/src/lifecycle/tests/launch_spawn.rs +20 -32
- package/crates/team-agent/src/lifecycle/tests/lifecycle_rollback_red.rs +17 -9
- package/crates/team-agent/src/lifecycle/tests/mcp_tool_name_format_red.rs +69 -0
- package/crates/team-agent/src/lifecycle/tests/phase_b_contracts.rs +24 -23
- package/crates/team-agent/src/lifecycle/tests/phase_golden.rs +98 -62
- package/crates/team-agent/src/lifecycle/tests/quick_start_worker_readiness_red.rs +2 -2
- package/crates/team-agent/src/lifecycle/tests/restart_build_before_destroy_0540_contract.rs +1 -1
- package/crates/team-agent/src/lifecycle/tests/restart_liveness_red.rs +1 -1
- package/crates/team-agent/src/lifecycle/tests/restart_rebind_hotfix_252_red.rs +3 -1
- package/crates/team-agent/src/lifecycle/tests/restart_session_capture_red.rs +2 -2
- package/crates/team-agent/src/lifecycle/tests/resume_recover_red.rs +1 -1
- package/crates/team-agent/src/lifecycle/tests/stale_team_saveconflict_contract.rs +1 -1
- package/crates/team-agent/src/lifecycle/tests/startup_latency_contract.rs +41 -8
- package/crates/team-agent/src/lifecycle/tests/status_credential_redaction_contract.rs +3 -3
- package/crates/team-agent/src/lifecycle/tests/subprep_codex_trust_roundtrip_red.rs +1 -1
- package/crates/team-agent/src/lifecycle/tests/swallow_batch4_semantics_red.rs +1 -1
- package/crates/team-agent/src/lifecycle/tests/team_in_team_identity_scope_red.rs +1 -1
- package/crates/team-agent/src/lifecycle/tests/team_in_team_sibling_quick_start_red.rs +1 -1
- package/crates/team-agent/src/lifecycle/tests/team_in_team_state_scope_red.rs +1 -1
- package/crates/team-agent/src/lifecycle/tests/team_key_retirement_txn_red.rs +1 -1
- package/crates/team-agent/src/lifecycle/tests/test_isolation_escape_contract.rs +60 -2
- package/crates/team-agent/src/lifecycle/tests/upgrade_compat_0211_red.rs +1 -1
- package/crates/team-agent/src/lifecycle/tests/verify_rs031_window_consistency_red.rs +2 -2
- package/crates/team-agent/src/lifecycle/tests/worker_spawn_env_red.rs +69 -26
- package/crates/team-agent/src/lifecycle/tests.rs +23 -15
- package/crates/team-agent/src/lifecycle/types.rs +61 -2
- package/crates/team-agent/src/lifecycle/worker_command_context.rs +200 -33
- package/crates/team-agent/src/mcp_server/tests/scoped.rs +100 -1
- package/crates/team-agent/src/mcp_server/tests.rs +196 -2
- package/crates/team-agent/src/messaging/delivery.rs +405 -40
- package/crates/team-agent/src/messaging/helpers.rs +2 -0
- package/crates/team-agent/src/messaging/leader_receiver.rs +53 -1
- package/crates/team-agent/src/messaging/results.rs +4 -0
- package/crates/team-agent/src/messaging/send.rs +34 -0
- package/crates/team-agent/src/messaging/tests/dup_inject.rs +406 -0
- package/crates/team-agent/src/messaging/tests/e23.rs +9 -0
- package/crates/team-agent/src/messaging/tests/leader_inject_acceptance.rs +66 -0
- package/crates/team-agent/src/messaging/tests/main_preserved.rs +1 -1
- package/crates/team-agent/src/messaging/tests/mod.rs +1 -0
- package/crates/team-agent/src/messaging/types.rs +4 -1
- package/crates/team-agent/src/model/enums.rs +14 -5
- package/crates/team-agent/src/model/permissions.rs +3 -0
- package/crates/team-agent/src/model/spec.rs +129 -6
- package/crates/team-agent/src/model/testdata/spec_invalid_a.yaml +3 -1
- package/crates/team-agent/src/model/testdata/team.spec.golden.yaml +3 -1
- package/crates/team-agent/src/model/testdata/team.spec.yaml +3 -1
- package/crates/team-agent/src/os_probe.rs +73 -2
- package/crates/team-agent/src/provider/adapter.rs +231 -4
- package/crates/team-agent/src/provider/adapters/claude.rs +5 -2
- package/crates/team-agent/src/provider/adapters/codex.rs +5 -2
- package/crates/team-agent/src/provider/adapters/copilot.rs +5 -2
- package/crates/team-agent/src/provider/adapters/cursor_agent.rs +86 -0
- package/crates/team-agent/src/provider/adapters/grok.rs +157 -0
- package/crates/team-agent/src/provider/adapters/mod.rs +2 -0
- package/crates/team-agent/src/provider/bypass_flags.rs +124 -0
- package/crates/team-agent/src/provider/classify.rs +4 -2
- package/crates/team-agent/src/provider/faults.rs +2 -1
- package/crates/team-agent/src/provider/mod.rs +13 -0
- package/crates/team-agent/src/provider/session/capture.rs +158 -20
- package/crates/team-agent/src/provider/session/context_fork/claude.rs +38 -1
- package/crates/team-agent/src/provider/session/context_fork/codex.rs +72 -1
- package/crates/team-agent/src/provider/session/context_fork/outcome.rs +57 -1
- package/crates/team-agent/src/provider/session/context_fork.rs +77 -3
- package/crates/team-agent/src/provider/session/mod.rs +18 -0
- package/crates/team-agent/src/provider/session/resume.rs +57 -0
- package/crates/team-agent/src/provider/session_scan/claude.rs +125 -1
- package/crates/team-agent/src/provider/session_scan/codex.rs +94 -1
- package/crates/team-agent/src/provider/session_scan/common.rs +204 -2
- package/crates/team-agent/src/provider/session_scan/copilot.rs +33 -1
- package/crates/team-agent/src/provider/session_scan/cursor.rs +538 -0
- package/crates/team-agent/src/provider/session_scan/grok.rs +288 -0
- package/crates/team-agent/src/provider/session_scan.rs +8 -0
- package/crates/team-agent/src/provider/submit_now.rs +94 -0
- package/crates/team-agent/src/provider/tests/adapter.rs +304 -0
- package/crates/team-agent/src/provider/types.rs +4 -2
- package/crates/team-agent/src/provider/wire.rs +23 -1
- package/crates/team-agent/src/state/persist.rs +301 -8
- package/crates/team-agent/src/state/repository.rs +5 -0
- package/crates/team-agent/src/tmux_backend/tests.rs +1737 -42
- package/crates/team-agent/src/tmux_backend.rs +1083 -75
- package/crates/team-agent/src/transport/test_support.rs +20 -0
- package/crates/team-agent/src/transport/tests/wire.rs +28 -2
- package/crates/team-agent/src/transport.rs +265 -1
- package/npm/install.mjs +129 -73
- package/package.json +4 -4
- package/skills/team-agent/SKILL.md +33 -238
- package/skills/team-agent/command-coverage.json +31 -0
- package/crates/team-agent/src/lifecycle/launch/approval.rs +0 -134
- package/crates/team-agent/src/lifecycle/launch/fork_agent/completion.rs +0 -59
- package/crates/team-agent/src/lifecycle/launch/fork_finalize.rs +0 -483
- package/crates/team-agent/src/lifecycle/launch/fork_pending.rs +0 -109
- package/crates/team-agent/src/lifecycle/launch/fork_state.rs +0 -447
- package/crates/team-agent/src/lifecycle/tests/codex_mcp_approval_inheritance_red.rs +0 -1187
- 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
|
-
|
|
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
|
-
|
|
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
|
|
1472
|
+
fn lifecycle_uses_in_window_fork_not_session_file_materialization() {
|
|
1253
1473
|
let source = include_str!("../lifecycle/launch/fork_agent.rs");
|
|
1254
|
-
assert!(
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
+
}
|