@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
|
@@ -261,3 +261,307 @@ fn unsupported_provider_capability_error_message_shape() {
|
|
|
261
261
|
// ═══════════════ P2 FIX-LOOP RED (复绿即对抗 cross-model findings) ═══════════════
|
|
262
262
|
// Lock the CORRECT Python v0.2.11 behavior the strengthened contracts missed.
|
|
263
263
|
// Golden re-probed via /tmp/probe_p2_provider.py vs team-agent-public @ 439bef8.
|
|
264
|
+
|
|
265
|
+
// ═══════════════ 0.5.67 provider-adapter (Grok + CursorAgent) ═══════════════
|
|
266
|
+
// 仿 claude build_command tests 结构 (见 build_command_includes_model_and_system_prompt)。
|
|
267
|
+
// 不跑 cargo (禁 cargo 红线), 静态编码 + leader verify 时执行。
|
|
268
|
+
|
|
269
|
+
#[test]
|
|
270
|
+
fn test_grok_build_command_includes_rules_flag_when_system_prompt_set() {
|
|
271
|
+
let adapter = get_adapter(Provider::Grok);
|
|
272
|
+
let argv = adapter
|
|
273
|
+
.build_command(AuthMode::Subscription, None, Some("be helpful"), Some("grok-4"))
|
|
274
|
+
.expect("build_command ok");
|
|
275
|
+
assert!(
|
|
276
|
+
argv_contains_adjacent(&argv, &["--model", "grok-4"]),
|
|
277
|
+
"argv must contain `--model grok-4` adjacency: {argv:?}"
|
|
278
|
+
);
|
|
279
|
+
assert!(
|
|
280
|
+
argv_contains_adjacent(&argv, &["--rules", "be helpful"]),
|
|
281
|
+
"grok append-system-prompt must be `--rules 'be helpful'`: {argv:?}"
|
|
282
|
+
);
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
#[test]
|
|
286
|
+
fn test_grok_build_command_bypass_flag_when_dangerous() {
|
|
287
|
+
let adapter = get_adapter(Provider::Grok);
|
|
288
|
+
let dangerous = adapter
|
|
289
|
+
.build_command_with_tools(
|
|
290
|
+
AuthMode::Subscription,
|
|
291
|
+
None,
|
|
292
|
+
None,
|
|
293
|
+
Some("grok-4"),
|
|
294
|
+
&["dangerous_auto_approve"],
|
|
295
|
+
)
|
|
296
|
+
.expect("dangerous build_command ok");
|
|
297
|
+
assert!(
|
|
298
|
+
argv_contains_adjacent(&dangerous, &["--always-approve"]),
|
|
299
|
+
"dangerous grok must include `--always-approve`: {dangerous:?}"
|
|
300
|
+
);
|
|
301
|
+
let safe = adapter
|
|
302
|
+
.build_command(AuthMode::Subscription, None, None, Some("grok-4"))
|
|
303
|
+
.expect("safe build_command ok");
|
|
304
|
+
assert!(
|
|
305
|
+
!safe.iter().any(|a| a == "--always-approve"),
|
|
306
|
+
"non-dangerous grok must not include --always-approve: {safe:?}"
|
|
307
|
+
);
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
#[test]
|
|
311
|
+
fn test_grok_build_command_refuses_missing_model() {
|
|
312
|
+
let adapter = get_adapter(Provider::Grok);
|
|
313
|
+
let err = adapter
|
|
314
|
+
.build_command(AuthMode::Subscription, None, None, None)
|
|
315
|
+
.expect_err("grok must refuse to build argv without an explicit model");
|
|
316
|
+
let text = err.to_string();
|
|
317
|
+
assert!(
|
|
318
|
+
text.to_ascii_lowercase().contains("model"),
|
|
319
|
+
"error must name model; got {text}"
|
|
320
|
+
);
|
|
321
|
+
assert!(
|
|
322
|
+
text.to_ascii_lowercase().contains("built-in")
|
|
323
|
+
|| text.to_ascii_lowercase().contains("builtin")
|
|
324
|
+
|| text.contains("内建"),
|
|
325
|
+
"error must name the built-in default the framework would fill; got {text}"
|
|
326
|
+
);
|
|
327
|
+
assert!(
|
|
328
|
+
argv_contains_adjacent(
|
|
329
|
+
&adapter
|
|
330
|
+
.build_command(AuthMode::Subscription, None, None, Some("grok-4.6"))
|
|
331
|
+
.expect("explicit model must build"),
|
|
332
|
+
&["--model", "grok-4.6"]
|
|
333
|
+
),
|
|
334
|
+
"explicit model must still become adjacent `--model grok-4.6`"
|
|
335
|
+
);
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
#[test]
|
|
339
|
+
fn test_cursor_agent_build_command_includes_workspace_flag() {
|
|
340
|
+
let adapter = get_adapter(Provider::CursorAgent);
|
|
341
|
+
let argv = adapter
|
|
342
|
+
.build_command(AuthMode::Subscription, None, Some("be helpful"), Some("sonnet-4-thinking"))
|
|
343
|
+
.expect("build_command ok");
|
|
344
|
+
// system_prompt 不入 argv (方案 1 变体走 workspace rules 文件), argv 只带
|
|
345
|
+
// --workspace {workspace} placeholder (spawn 时 fill_spawn_placeholders 替换)。
|
|
346
|
+
assert!(
|
|
347
|
+
argv_contains_adjacent(&argv, &["--workspace", "{workspace}"]),
|
|
348
|
+
"cursor argv must carry `--workspace {{workspace}}`: {argv:?}"
|
|
349
|
+
);
|
|
350
|
+
assert!(
|
|
351
|
+
argv_contains_adjacent(&argv, &["--trust"]),
|
|
352
|
+
"cursor argv must carry documented --trust: {argv:?}"
|
|
353
|
+
);
|
|
354
|
+
assert!(
|
|
355
|
+
argv_contains_adjacent(&argv, &["--sandbox", "disabled"]),
|
|
356
|
+
"cursor argv must carry documented --sandbox disabled: {argv:?}"
|
|
357
|
+
);
|
|
358
|
+
assert!(
|
|
359
|
+
!argv.iter().any(|a| a == "--rules" || a == "--append-system-prompt"),
|
|
360
|
+
"cursor append-system-prompt must NOT go on argv (workspace rules file): {argv:?}"
|
|
361
|
+
);
|
|
362
|
+
assert!(
|
|
363
|
+
!argv.iter().any(|a| a == "--system-prompt" || a == "--allowed-tools"),
|
|
364
|
+
"undocumented flags must stay off the main path: {argv:?}"
|
|
365
|
+
);
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
#[test]
|
|
369
|
+
fn test_cursor_agent_build_command_bypass_flag_when_dangerous() {
|
|
370
|
+
let adapter = get_adapter(Provider::CursorAgent);
|
|
371
|
+
let dangerous = adapter
|
|
372
|
+
.build_command_with_tools(
|
|
373
|
+
AuthMode::Subscription,
|
|
374
|
+
None,
|
|
375
|
+
None,
|
|
376
|
+
None,
|
|
377
|
+
&["dangerous_auto_approve"],
|
|
378
|
+
)
|
|
379
|
+
.expect("dangerous build_command ok");
|
|
380
|
+
assert!(
|
|
381
|
+
argv_contains_adjacent(&dangerous, &["--force"]),
|
|
382
|
+
"dangerous cursor must include `--force`: {dangerous:?}"
|
|
383
|
+
);
|
|
384
|
+
let safe = adapter
|
|
385
|
+
.build_command(AuthMode::Subscription, None, None, None)
|
|
386
|
+
.expect("safe build_command ok");
|
|
387
|
+
assert!(
|
|
388
|
+
!safe.iter().any(|a| a == "--force"),
|
|
389
|
+
"non-dangerous cursor must not include --force: {safe:?}"
|
|
390
|
+
);
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
#[test]
|
|
394
|
+
fn test_cursor_agent_accepts_mcp_config_without_putting_it_on_argv() {
|
|
395
|
+
let adapter = get_adapter(Provider::CursorAgent);
|
|
396
|
+
let cfg = McpConfig {
|
|
397
|
+
raw: serde_json::json!({
|
|
398
|
+
"team_orchestrator": {
|
|
399
|
+
"command": "/bin/team-agent",
|
|
400
|
+
"args": ["mcp-server"]
|
|
401
|
+
}
|
|
402
|
+
}),
|
|
403
|
+
};
|
|
404
|
+
let argv = adapter
|
|
405
|
+
.build_command(AuthMode::Subscription, Some(&cfg), None, None)
|
|
406
|
+
.expect("cursor MCP is launch overlay, not an argv capability hole");
|
|
407
|
+
assert!(
|
|
408
|
+
!argv.iter().any(|a| a == "--mcp-config" || a.contains("mcp")),
|
|
409
|
+
"cursor has no --mcp-config flag; overlay writes .cursor/mcp.json: {argv:?}"
|
|
410
|
+
);
|
|
411
|
+
assert!(
|
|
412
|
+
argv_contains_adjacent(&argv, &["--workspace", "{workspace}"]),
|
|
413
|
+
"workspace flag must survive an mcp_config argument: {argv:?}"
|
|
414
|
+
);
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
#[test]
|
|
418
|
+
fn test_cursor_agent_refuses_mcp_config_loudly() {
|
|
419
|
+
// 已废除的行为:旧实现收到 mcp_config 就返回 CapabilityUnsupported
|
|
420
|
+
// (「MCP is not implemented」),此断言证明它确实没了。
|
|
421
|
+
let adapter = get_adapter(Provider::CursorAgent);
|
|
422
|
+
let cfg = McpConfig {
|
|
423
|
+
raw: serde_json::json!({
|
|
424
|
+
"team_orchestrator": {
|
|
425
|
+
"command": "/bin/team-agent",
|
|
426
|
+
"args": ["mcp-server"]
|
|
427
|
+
}
|
|
428
|
+
}),
|
|
429
|
+
};
|
|
430
|
+
let result = adapter.build_command(AuthMode::Subscription, Some(&cfg), None, None);
|
|
431
|
+
assert!(
|
|
432
|
+
!matches!(result, Err(ProviderError::CapabilityUnsupported(_))),
|
|
433
|
+
"feeding mcp_config must not return CapabilityUnsupported; got {result:?}"
|
|
434
|
+
);
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
#[test]
|
|
438
|
+
fn test_grok_build_command_plan_binds_expected_session_id_to_argv() {
|
|
439
|
+
let adapter = get_adapter(Provider::Grok);
|
|
440
|
+
let plan = adapter
|
|
441
|
+
.build_command_plan(ProviderCommandContext {
|
|
442
|
+
auth_mode: AuthMode::Subscription,
|
|
443
|
+
mcp_config: None,
|
|
444
|
+
system_prompt: None,
|
|
445
|
+
model: Some("grok-4.6"),
|
|
446
|
+
tools: &[],
|
|
447
|
+
profile_launch: None,
|
|
448
|
+
agent_id_hint: Some("w1"),
|
|
449
|
+
effort: None,
|
|
450
|
+
})
|
|
451
|
+
.expect("grok plan");
|
|
452
|
+
let sid = plan
|
|
453
|
+
.expected_session_id
|
|
454
|
+
.as_ref()
|
|
455
|
+
.map(|s| s.as_str())
|
|
456
|
+
.expect("grok fresh plan must carry expected_session_id");
|
|
457
|
+
assert!(
|
|
458
|
+
!sid.is_empty(),
|
|
459
|
+
"expected_session_id must be a non-empty uuid"
|
|
460
|
+
);
|
|
461
|
+
assert!(
|
|
462
|
+
argv_contains_adjacent(&plan.argv, &["--session-id", sid]),
|
|
463
|
+
"argv --session-id must match expected_session_id; argv={:?}",
|
|
464
|
+
plan.argv
|
|
465
|
+
);
|
|
466
|
+
assert!(
|
|
467
|
+
!plan.argv.iter().any(|a| a == "--resume"),
|
|
468
|
+
"fresh grok plan must not include --resume; argv={:?}",
|
|
469
|
+
plan.argv
|
|
470
|
+
);
|
|
471
|
+
}
|
|
472
|
+
|
|
473
|
+
#[test]
|
|
474
|
+
fn test_cursor_auth_hint_subscription_is_unknown_not_present() {
|
|
475
|
+
let adapter = get_adapter(Provider::CursorAgent);
|
|
476
|
+
let hint = adapter.auth_hint(AuthMode::Subscription);
|
|
477
|
+
assert_ne!(
|
|
478
|
+
hint,
|
|
479
|
+
crate::provider::types::AuthHintStatus::Present,
|
|
480
|
+
"U-17 前不得把未观测写成 Present"
|
|
481
|
+
);
|
|
482
|
+
assert_ne!(hint, crate::provider::types::AuthHintStatus::PresentWeak);
|
|
483
|
+
assert_eq!(hint, crate::provider::types::AuthHintStatus::Unknown);
|
|
484
|
+
}
|
|
485
|
+
|
|
486
|
+
#[test]
|
|
487
|
+
fn test_cursor_fresh_plan_has_no_session_id_and_no_resume() {
|
|
488
|
+
let adapter = get_adapter(Provider::CursorAgent);
|
|
489
|
+
let plan = adapter
|
|
490
|
+
.build_command_plan(ProviderCommandContext {
|
|
491
|
+
auth_mode: AuthMode::Subscription,
|
|
492
|
+
mcp_config: None,
|
|
493
|
+
system_prompt: None,
|
|
494
|
+
model: Some("sonnet-4-thinking"),
|
|
495
|
+
tools: &[],
|
|
496
|
+
profile_launch: None,
|
|
497
|
+
agent_id_hint: Some("w1"),
|
|
498
|
+
effort: None,
|
|
499
|
+
})
|
|
500
|
+
.expect("cursor plan");
|
|
501
|
+
assert!(
|
|
502
|
+
plan.expected_session_id.is_none(),
|
|
503
|
+
"U-01 未过不得造假 pending; got {:?}",
|
|
504
|
+
plan.expected_session_id
|
|
505
|
+
);
|
|
506
|
+
assert!(
|
|
507
|
+
!plan.argv.iter().any(|a| a == "--session-id" || a == "--resume" || a == "--continue"),
|
|
508
|
+
"fresh cursor argv must not invent session flags; argv={:?}",
|
|
509
|
+
plan.argv
|
|
510
|
+
);
|
|
511
|
+
assert!(
|
|
512
|
+
argv_contains_adjacent(&plan.argv, &["--trust"]),
|
|
513
|
+
"fresh cursor must keep --trust; argv={:?}",
|
|
514
|
+
plan.argv
|
|
515
|
+
);
|
|
516
|
+
}
|
|
517
|
+
|
|
518
|
+
#[test]
|
|
519
|
+
fn test_cursor_resume_plan_requires_chat_id_and_never_emits_empty_resume() {
|
|
520
|
+
let adapter = get_adapter(Provider::CursorAgent);
|
|
521
|
+
let ctx = ProviderCommandContext {
|
|
522
|
+
auth_mode: AuthMode::Subscription,
|
|
523
|
+
mcp_config: None,
|
|
524
|
+
system_prompt: None,
|
|
525
|
+
model: Some("sonnet-4-thinking"),
|
|
526
|
+
tools: &[],
|
|
527
|
+
profile_launch: None,
|
|
528
|
+
agent_id_hint: Some("w1"),
|
|
529
|
+
effort: None,
|
|
530
|
+
};
|
|
531
|
+
let missing = adapter.build_resume_command_plan(None, ctx);
|
|
532
|
+
assert!(
|
|
533
|
+
matches!(missing, Err(ProviderError::ResumeUnavailable(_))),
|
|
534
|
+
"no chatId must not emit empty --resume; got {missing:?}"
|
|
535
|
+
);
|
|
536
|
+
let sid = SessionId::new("502896a1-72ba-4c53-9a86-b2da28780806");
|
|
537
|
+
let plan = adapter
|
|
538
|
+
.build_resume_command_plan(Some(&sid), ctx)
|
|
539
|
+
.expect("resume plan");
|
|
540
|
+
assert!(
|
|
541
|
+
argv_contains_adjacent(&plan.argv, &["--resume", sid.as_str()]),
|
|
542
|
+
"resume plan must hit CursorAgent --resume arm; argv={:?}",
|
|
543
|
+
plan.argv
|
|
544
|
+
);
|
|
545
|
+
assert!(
|
|
546
|
+
!plan.argv.iter().any(|a| a == "--session-id" || a == "--continue"),
|
|
547
|
+
"resume must not mint --session-id/--continue; argv={:?}",
|
|
548
|
+
plan.argv
|
|
549
|
+
);
|
|
550
|
+
}
|
|
551
|
+
|
|
552
|
+
#[test]
|
|
553
|
+
fn test_grok_unknown_tool_mapping_is_explicitly_unsupported() {
|
|
554
|
+
use crate::provider::adapters::grok::{grok_tool_mapping, GrokToolMapping};
|
|
555
|
+
assert_eq!(
|
|
556
|
+
grok_tool_mapping("network"),
|
|
557
|
+
GrokToolMapping::Unsupported
|
|
558
|
+
);
|
|
559
|
+
assert_eq!(
|
|
560
|
+
grok_tool_mapping("not_a_real_tool"),
|
|
561
|
+
GrokToolMapping::Unsupported
|
|
562
|
+
);
|
|
563
|
+
assert!(
|
|
564
|
+
!matches!(grok_tool_mapping("execute_bash"), GrokToolMapping::Unsupported),
|
|
565
|
+
"known tools must stay mapped"
|
|
566
|
+
);
|
|
567
|
+
}
|
|
@@ -353,8 +353,10 @@ pub struct ProviderCommandContext<'a> {
|
|
|
353
353
|
/// framework passes no effort flag (provider default).
|
|
354
354
|
/// - Claude / ClaudeCode: low|medium|high|xhigh|max → `--effort <level>`
|
|
355
355
|
/// - Codex: low|medium|high|xhigh → `-c model_reasoning_effort=<level>`
|
|
356
|
-
/// -
|
|
357
|
-
///
|
|
356
|
+
/// - Grok: low|medium|high|xhigh (NOT max) → `--effort <level>`
|
|
357
|
+
/// - Copilot / Gemini / CursorAgent / Fake: ignored, warning event
|
|
358
|
+
/// emitted at the caller (lifecycle/launch.rs / lifecycle/restart)
|
|
359
|
+
/// before construct.
|
|
358
360
|
pub effort: Option<crate::model::enums::ProviderEffort>,
|
|
359
361
|
}
|
|
360
362
|
|
|
@@ -34,6 +34,8 @@ pub(crate) fn provider_wire(provider: Provider) -> &'static str {
|
|
|
34
34
|
Provider::Codex => "codex",
|
|
35
35
|
Provider::Copilot => "copilot",
|
|
36
36
|
Provider::GeminiCli => "gemini_cli",
|
|
37
|
+
Provider::Grok => "grok",
|
|
38
|
+
Provider::CursorAgent => "cursor_agent",
|
|
37
39
|
Provider::Fake => "fake",
|
|
38
40
|
}
|
|
39
41
|
}
|
|
@@ -75,7 +77,12 @@ pub(crate) fn is_claude_family(provider: Provider) -> bool {
|
|
|
75
77
|
pub(crate) fn requires_resume_backing(provider: Provider) -> bool {
|
|
76
78
|
matches!(
|
|
77
79
|
provider,
|
|
78
|
-
Provider::Codex
|
|
80
|
+
Provider::Codex
|
|
81
|
+
| Provider::Claude
|
|
82
|
+
| Provider::ClaudeCode
|
|
83
|
+
| Provider::Copilot
|
|
84
|
+
| Provider::Grok
|
|
85
|
+
| Provider::CursorAgent
|
|
79
86
|
)
|
|
80
87
|
}
|
|
81
88
|
|
|
@@ -86,6 +93,8 @@ pub(crate) fn provider_model_keys(provider: Provider) -> &'static [&'static str]
|
|
|
86
93
|
Provider::Codex => &["codex"],
|
|
87
94
|
Provider::Copilot => &["copilot"],
|
|
88
95
|
Provider::GeminiCli => &["gemini_cli"],
|
|
96
|
+
Provider::Grok => &["grok"],
|
|
97
|
+
Provider::CursorAgent => &["cursor_agent"],
|
|
89
98
|
Provider::Fake => &["fake"],
|
|
90
99
|
}
|
|
91
100
|
}
|
|
@@ -94,6 +103,10 @@ pub(crate) fn builtin_provider_model(provider: Provider) -> Option<&'static str>
|
|
|
94
103
|
match provider {
|
|
95
104
|
Provider::Claude | Provider::ClaudeCode => Some("claude-sonnet-4-6"),
|
|
96
105
|
Provider::Codex => Some("gpt-5.5"),
|
|
106
|
+
// grok: compiler 另有缺 model 硬闸,这里的 builtin 不再被 grok 角色吃到。
|
|
107
|
+
// cursor_agent: 禁止隐式默认(本机 shim 会剥 sonnet-4-thinking);缺 model 编译失败。
|
|
108
|
+
Provider::Grok => Some("grok-4"),
|
|
109
|
+
Provider::CursorAgent => None,
|
|
97
110
|
Provider::Copilot | Provider::GeminiCli | Provider::Fake => None,
|
|
98
111
|
}
|
|
99
112
|
}
|
|
@@ -112,6 +125,11 @@ pub(crate) fn aliases(provider: Provider) -> &'static [&'static str] {
|
|
|
112
125
|
Provider::Codex => &["codex"],
|
|
113
126
|
Provider::Copilot => &["copilot"],
|
|
114
127
|
Provider::GeminiCli => &["gemini_cli"],
|
|
128
|
+
Provider::Grok => &["grok"],
|
|
129
|
+
// canonical wire form 恒为首项 (parse_provider round-trip 依赖); "agent"
|
|
130
|
+
// 是 exec 二进制名, 仅作 alias (不参与 command-text 子串匹配, 见
|
|
131
|
+
// leader/provider_attribution.rs TODO)。
|
|
132
|
+
Provider::CursorAgent => &["cursor_agent", "agent"],
|
|
115
133
|
Provider::Fake => &["fake"],
|
|
116
134
|
}
|
|
117
135
|
}
|
|
@@ -126,6 +144,8 @@ pub(crate) fn command_name(provider: Provider) -> &'static str {
|
|
|
126
144
|
Provider::Codex => "codex",
|
|
127
145
|
Provider::Copilot => "copilot",
|
|
128
146
|
Provider::GeminiCli => "gemini",
|
|
147
|
+
Provider::Grok => "grok",
|
|
148
|
+
Provider::CursorAgent => "agent",
|
|
129
149
|
Provider::Fake => "team-agent",
|
|
130
150
|
}
|
|
131
151
|
}
|
|
@@ -136,6 +156,8 @@ const ALL_PROVIDERS: &[Provider] = &[
|
|
|
136
156
|
Provider::Codex,
|
|
137
157
|
Provider::Copilot,
|
|
138
158
|
Provider::GeminiCli,
|
|
159
|
+
Provider::Grok,
|
|
160
|
+
Provider::CursorAgent,
|
|
139
161
|
Provider::Fake,
|
|
140
162
|
];
|
|
141
163
|
|