@team-agent/installer 0.5.68 → 0.5.70
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 +1 -1
- package/Cargo.toml +1 -1
- package/crates/team-agent/src/cli/diagnose.rs +74 -0
- package/crates/team-agent/src/cli/emit.rs +5 -4
- package/crates/team-agent/src/cli/leader.rs +1 -0
- package/crates/team-agent/src/cli/spec.rs +1 -0
- package/crates/team-agent/src/compiler.rs +54 -7
- package/crates/team-agent/src/coordinator/runtime_detectors.rs +1 -0
- package/crates/team-agent/src/layout/worker_window_helpers.rs +1 -0
- package/crates/team-agent/src/leader/start.rs +53 -12
- package/crates/team-agent/src/lifecycle/launch/add_agent.rs +67 -15
- package/crates/team-agent/src/lifecycle/launch/add_agent_state.rs +18 -0
- package/crates/team-agent/src/lifecycle/launch/agent_state.rs +1 -0
- package/crates/team-agent/src/lifecycle/launch/cursor_mcp.rs +260 -44
- package/crates/team-agent/src/lifecycle/launch/cursor_mcp_iso.rs +120 -0
- package/crates/team-agent/src/lifecycle/launch/fork_agent.rs +5 -1
- package/crates/team-agent/src/lifecycle/launch/mcp_config.rs +10 -59
- package/crates/team-agent/src/lifecycle/launch/pi_mcp.rs +838 -0
- package/crates/team-agent/src/lifecycle/launch/quick_start_transport.rs +9 -3
- package/crates/team-agent/src/lifecycle/launch/spawn.rs +60 -28
- package/crates/team-agent/src/lifecycle/launch/spec_state.rs +1 -0
- package/crates/team-agent/src/lifecycle/launch.rs +10 -2
- package/crates/team-agent/src/lifecycle/profile_launch.rs +3 -2
- package/crates/team-agent/src/lifecycle/profile_smoke.rs +1 -0
- package/crates/team-agent/src/lifecycle/restart/agent.rs +90 -160
- package/crates/team-agent/src/lifecycle/restart/common.rs +136 -28
- package/crates/team-agent/src/lifecycle/restart/remove.rs +37 -1
- package/crates/team-agent/src/lifecycle/tests/claude_profile_launch_red.rs +24 -3
- package/crates/team-agent/src/lifecycle/tests/cursor_mcp_overlay.rs +195 -18
- package/crates/team-agent/src/lifecycle/tests/cursor_require_explicit_model_red.rs +30 -12
- package/crates/team-agent/src/lifecycle/tests/fixtures/pi_list_models_g0.stdout.txt +222 -0
- package/crates/team-agent/src/lifecycle/tests/g1_silent_faces.rs +5 -2
- package/crates/team-agent/src/lifecycle/tests/grok_mcp_overlay_red.rs +35 -48
- package/crates/team-agent/src/lifecycle/tests/harvest2_a_batch_red.rs +1 -1
- package/crates/team-agent/src/lifecycle/tests/pi_catalog_red.rs +97 -0
- package/crates/team-agent/src/lifecycle/tests/pi_command_red.rs +145 -0
- package/crates/team-agent/src/lifecycle/tests/pi_compiler_red.rs +243 -0
- package/crates/team-agent/src/lifecycle/tests/pi_dual_entry_red.rs +856 -0
- package/crates/team-agent/src/lifecycle/tests/pi_executable_mcp_red.rs +387 -0
- package/crates/team-agent/src/lifecycle/tests/pi_lifecycle_doctor_red.rs +98 -0
- package/crates/team-agent/src/lifecycle/tests/pi_session_delivery_red.rs +216 -0
- package/crates/team-agent/src/lifecycle/tests/restart_rebind_hotfix_252_red.rs +1 -0
- package/crates/team-agent/src/lifecycle/tests.rs +7 -0
- package/crates/team-agent/src/lifecycle/worker_command_context.rs +61 -4
- package/crates/team-agent/src/messaging/delivery.rs +36 -12
- package/crates/team-agent/src/model/enums.rs +3 -1
- package/crates/team-agent/src/model/permissions.rs +1 -1
- package/crates/team-agent/src/provider/adapter.rs +29 -3
- package/crates/team-agent/src/provider/adapters/cursor_agent.rs +5 -2
- package/crates/team-agent/src/provider/adapters/mod.rs +1 -0
- package/crates/team-agent/src/provider/adapters/pi.rs +146 -0
- package/crates/team-agent/src/provider/bypass_flags.rs +1 -0
- package/crates/team-agent/src/provider/classify.rs +2 -2
- package/crates/team-agent/src/provider/faults.rs +1 -1
- package/crates/team-agent/src/provider/session/context_fork.rs +2 -1
- package/crates/team-agent/src/provider/session_scan/common.rs +1 -0
- package/crates/team-agent/src/provider/session_scan/pi.rs +172 -0
- package/crates/team-agent/src/provider/session_scan.rs +4 -0
- package/crates/team-agent/src/provider/tests/adapter.rs +80 -0
- package/crates/team-agent/src/provider/wire.rs +7 -1
- package/crates/team-agent/src/tmux_backend.rs +52 -0
- package/package.json +4 -4
- package/skills/team-agent/SKILL.md +9 -5
|
@@ -183,7 +183,11 @@ pub(crate) fn annotate_runtime_tmux_endpoint(
|
|
|
183
183
|
transport: &dyn Transport,
|
|
184
184
|
workspace: &Path,
|
|
185
185
|
) {
|
|
186
|
-
let
|
|
186
|
+
let transport_endpoint = transport.tmux_endpoint();
|
|
187
|
+
let endpoint = crate::tmux_backend::owning_tmux_endpoint_from_state(state)
|
|
188
|
+
.map(|(endpoint, _source)| endpoint.to_string())
|
|
189
|
+
.or_else(|| transport_endpoint.clone());
|
|
190
|
+
let Some(endpoint) = endpoint else {
|
|
187
191
|
return;
|
|
188
192
|
};
|
|
189
193
|
let endpoint_for_state = if Path::new(&endpoint).is_absolute() || endpoint == "default" {
|
|
@@ -208,8 +212,10 @@ pub(crate) fn annotate_runtime_tmux_endpoint(
|
|
|
208
212
|
.cloned()
|
|
209
213
|
.unwrap_or(serde_json::Value::Null),
|
|
210
214
|
);
|
|
211
|
-
if
|
|
212
|
-
|
|
215
|
+
if transport_endpoint.as_deref() == Some(endpoint.as_str()) {
|
|
216
|
+
if let Some(source) = selected_tmux_socket_source(transport, workspace) {
|
|
217
|
+
obj.insert("tmux_socket_source".to_string(), serde_json::json!(source));
|
|
218
|
+
}
|
|
213
219
|
}
|
|
214
220
|
}
|
|
215
221
|
}
|
|
@@ -135,12 +135,16 @@ pub(super) fn spawn_agents(
|
|
|
135
135
|
.mcp_config(auth_mode)
|
|
136
136
|
.map_err(|e| LifecycleError::Provider(e.to_string()))?;
|
|
137
137
|
let mcp_config = resolve_mcp_config(mcp_config, workspace, agent_id_raw, &mcp_team_id);
|
|
138
|
-
let mcp_config_path =
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
138
|
+
let mcp_config_path = if provider == Provider::Pi {
|
|
139
|
+
None
|
|
140
|
+
} else {
|
|
141
|
+
Some(write_worker_mcp_config_for_provider(
|
|
142
|
+
workspace,
|
|
143
|
+
agent_id_raw,
|
|
144
|
+
&mcp_config,
|
|
145
|
+
Some(provider),
|
|
146
|
+
)?)
|
|
147
|
+
};
|
|
144
148
|
let profile_dir = team_dir.join("profiles");
|
|
145
149
|
let profile_launch =
|
|
146
150
|
crate::lifecycle::profile_launch::prepare_provider_profile_launch_with_profile_dir(
|
|
@@ -159,24 +163,44 @@ pub(super) fn spawn_agents(
|
|
|
159
163
|
let _ = crate::event_log::EventLog::new(workspace)
|
|
160
164
|
.write("provider.effort_unsupported", event_value);
|
|
161
165
|
}
|
|
162
|
-
let
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
166
|
+
let command_context = crate::provider::ProviderCommandContext {
|
|
167
|
+
auth_mode,
|
|
168
|
+
mcp_config: Some(&mcp_config),
|
|
169
|
+
system_prompt: Some(system_prompt.as_str()),
|
|
170
|
+
model: command_model,
|
|
171
|
+
tools: &resolved_tool_refs,
|
|
172
|
+
profile_launch: Some(&profile_launch),
|
|
173
|
+
// Layer 1 self-healing (architect probe 2026-06-22): expose
|
|
174
|
+
// agent_id as a display-name hint so Claude / Copilot
|
|
175
|
+
// adapters can pass `--name <agent_id>`. Codex has no
|
|
176
|
+
// equivalent flag and ignores the hint.
|
|
177
|
+
agent_id_hint: Some(agent_id_raw),
|
|
178
|
+
effort: agent_effort,
|
|
179
|
+
};
|
|
180
|
+
let mut plan = if provider == Provider::Pi {
|
|
181
|
+
crate::lifecycle::launch::pi_mcp::materialize_pi_plan(
|
|
182
|
+
crate::lifecycle::launch::pi_mcp::PiMaterializeRequest {
|
|
183
|
+
workspace,
|
|
184
|
+
team_id: &mcp_team_id,
|
|
185
|
+
agent_id: agent_id_raw,
|
|
186
|
+
model: command_model,
|
|
187
|
+
effort: agent_effort,
|
|
188
|
+
system_prompt: &system_prompt,
|
|
189
|
+
tool_categories: &resolved_tool_refs,
|
|
190
|
+
team_mcp_tools: &["send_message", "report_result"],
|
|
191
|
+
mcp_config: &mcp_config,
|
|
192
|
+
},
|
|
193
|
+
)
|
|
194
|
+
.map_err(|e| LifecycleError::Provider(e.to_string()))?
|
|
195
|
+
} else {
|
|
196
|
+
adapter
|
|
197
|
+
.build_command_plan(command_context)
|
|
198
|
+
.map_err(|e| LifecycleError::Provider(e.to_string()))?
|
|
199
|
+
};
|
|
178
200
|
if !plan.managed_mcp_config && !profile_launch.managed_mcp_config {
|
|
179
|
-
|
|
201
|
+
if let Some(mcp_config_path) = mcp_config_path.as_ref() {
|
|
202
|
+
point_native_mcp_config_at_file(&mut plan.argv, provider, mcp_config_path);
|
|
203
|
+
}
|
|
180
204
|
}
|
|
181
205
|
// C-A-4 cr verdict v2 — Copilot BYOK(compatible_api)硬性校验:
|
|
182
206
|
// "A model is required for BYOK"(help-providers 原文)。检查 agent
|
|
@@ -287,15 +311,23 @@ pub(super) fn spawn_agents(
|
|
|
287
311
|
);
|
|
288
312
|
}
|
|
289
313
|
}
|
|
290
|
-
// Cursor: role 经 .cursor/rules
|
|
291
|
-
// (不继承父进程 TEAM_AGENT_*)。--workspace
|
|
292
|
-
// mcp.json last-writer
|
|
314
|
+
// Cursor: role 经 .cursor/rules。MCP 身份默认写 provider-config/<id>/cursor
|
|
315
|
+
// (不继承父进程 TEAM_AGENT_*)。--workspace 指该工程根,--add-dir 真 workspace。
|
|
316
|
+
// 隔离关闭时仍拒绝第二席(共用 mcp.json last-writer)。不改 HOME。
|
|
293
317
|
if matches!(provider, Provider::CursorAgent) {
|
|
294
318
|
refuse_second_cursor_occupant(workspace, agent_id_raw, Some(spec))?;
|
|
295
319
|
apply_cursor_agent_rules_overlay(workspace, agent_id_raw, system_prompt.as_str())?;
|
|
296
320
|
apply_cursor_mcp_overlay(workspace, &mcp_config)?;
|
|
297
|
-
|
|
298
|
-
|
|
321
|
+
let project = if crate::lifecycle::launch::cursor_mcp_isolation_enabled() {
|
|
322
|
+
Some(crate::lifecycle::launch::cursor_mcp_project_dir(
|
|
323
|
+
workspace,
|
|
324
|
+
agent_id_raw,
|
|
325
|
+
)?)
|
|
326
|
+
} else {
|
|
327
|
+
None
|
|
328
|
+
};
|
|
329
|
+
enable_cursor_workspace_mcp(workspace, project.as_deref())?;
|
|
330
|
+
apply_cursor_spawn_workspace_pointers(&mut plan.argv, workspace, agent_id_raw)?;
|
|
299
331
|
let proxy = apply_cursor_subscription_proxy_env(&mut env);
|
|
300
332
|
let event_log = crate::event_log::EventLog::new(workspace);
|
|
301
333
|
let _ = event_log.write(
|
|
@@ -599,6 +599,7 @@ pub(crate) fn provider_display_str(provider: Provider) -> &'static str {
|
|
|
599
599
|
Provider::GeminiCli => "gemini_cli",
|
|
600
600
|
Provider::Grok => "grok",
|
|
601
601
|
Provider::CursorAgent => "cursor_agent",
|
|
602
|
+
Provider::Pi => "pi",
|
|
602
603
|
Provider::Fake => "fake",
|
|
603
604
|
}
|
|
604
605
|
}
|
|
@@ -307,10 +307,18 @@ pub(crate) use mcp_config::{
|
|
|
307
307
|
write_worker_mcp_config_for_provider,
|
|
308
308
|
};
|
|
309
309
|
|
|
310
|
+
pub(crate) mod pi_mcp;
|
|
311
|
+
|
|
312
|
+
mod cursor_mcp_iso;
|
|
313
|
+
pub use cursor_mcp_iso::{
|
|
314
|
+
cursor_mcp_isolation_enabled, cursor_mcp_json_path, cursor_mcp_project_dir,
|
|
315
|
+
materialize_cursor_mcp_project,
|
|
316
|
+
};
|
|
310
317
|
mod cursor_mcp;
|
|
311
318
|
pub use cursor_mcp::{
|
|
312
|
-
apply_cursor_mcp_overlay,
|
|
313
|
-
|
|
319
|
+
apply_cursor_mcp_overlay, apply_cursor_spawn_workspace_pointers,
|
|
320
|
+
apply_cursor_workspace_physical_path, cursor_mcp_enable_argv, enable_cursor_workspace_mcp,
|
|
321
|
+
physical_workspace_path, refuse_second_cursor_occupant,
|
|
314
322
|
};
|
|
315
323
|
|
|
316
324
|
mod cursor_create_chat;
|
|
@@ -484,7 +484,7 @@ fn provider_env_exports(
|
|
|
484
484
|
// grok/cursor_agent 一期无 profile exports(subscription 已登录态)。
|
|
485
485
|
// Cursor 订阅席的代理透传不在这里:profile 只服务 compatible-api。
|
|
486
486
|
// 订阅路径见 apply_cursor_subscription_proxy_env(只记有无,不记值)。
|
|
487
|
-
Provider::Grok | Provider::CursorAgent => {}
|
|
487
|
+
Provider::Grok | Provider::CursorAgent | Provider::Pi => {}
|
|
488
488
|
Provider::Fake => {}
|
|
489
489
|
}
|
|
490
490
|
exports
|
|
@@ -567,6 +567,7 @@ pub(crate) fn provider_env_unsets(provider: Provider, auth_mode: AuthMode) -> BT
|
|
|
567
567
|
// 禁止在这里 unset 代理。
|
|
568
568
|
Provider::Grok => {}
|
|
569
569
|
Provider::CursorAgent => {}
|
|
570
|
+
Provider::Pi => {}
|
|
570
571
|
Provider::Fake => {}
|
|
571
572
|
}
|
|
572
573
|
unsets
|
|
@@ -992,7 +993,7 @@ fn required_profile_keys(provider: Provider, auth_mode: AuthMode) -> &'static [&
|
|
|
992
993
|
// 二期 BYOK 立项时填(向后兼容字段保留)。
|
|
993
994
|
Provider::Copilot => &[],
|
|
994
995
|
// 0.5.67: grok/cursor_agent 一期无 BYOK required key 集合 (同 copilot 精神)。
|
|
995
|
-
Provider::Grok | Provider::CursorAgent => &[],
|
|
996
|
+
Provider::Grok | Provider::CursorAgent | Provider::Pi => &[],
|
|
996
997
|
Provider::Fake => &[],
|
|
997
998
|
}
|
|
998
999
|
}
|
|
@@ -399,85 +399,97 @@ pub(crate) fn start_agent_at_paths(
|
|
|
399
399
|
return Err(error);
|
|
400
400
|
}
|
|
401
401
|
let actual_spawn_window = spawn.spawn.window.as_str().to_string();
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
.get("agents")
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
),
|
|
432
|
-
|
|
402
|
+
let post_spawn = (|| -> Result<bool, LifecycleError> {
|
|
403
|
+
mark_agent_started(
|
|
404
|
+
&mut state,
|
|
405
|
+
agent_id,
|
|
406
|
+
&actual_spawn_window,
|
|
407
|
+
&spawn,
|
|
408
|
+
transport,
|
|
409
|
+
&safety,
|
|
410
|
+
start_mode,
|
|
411
|
+
)?;
|
|
412
|
+
// 0.5.66 bypass 单源 §2.7:启动即带 bypass → 审计留痕。
|
|
413
|
+
if safety.enabled {
|
|
414
|
+
let state_agent = state.get("agents").and_then(|v| v.get(agent_id.as_str()));
|
|
415
|
+
let _ = crate::event_log::EventLog::new(workspace).write(
|
|
416
|
+
"worker.spawn_dangerously_skip_permissions",
|
|
417
|
+
serde_json::json!({
|
|
418
|
+
"agent_id": agent_id.as_str(),
|
|
419
|
+
"role": state_agent
|
|
420
|
+
.and_then(|a| a.get("role"))
|
|
421
|
+
.and_then(serde_json::Value::as_str)
|
|
422
|
+
.unwrap_or_default(),
|
|
423
|
+
"provider": state_agent
|
|
424
|
+
.and_then(|a| a.get("provider"))
|
|
425
|
+
.and_then(serde_json::Value::as_str)
|
|
426
|
+
.unwrap_or_default(),
|
|
427
|
+
"trigger": "start-agent",
|
|
428
|
+
"spec_source_path": crate::lifecycle::launch::agent_id_spec_source_path(
|
|
429
|
+
workspace, agent_id.as_str(),
|
|
430
|
+
),
|
|
431
|
+
}),
|
|
432
|
+
);
|
|
433
|
+
}
|
|
434
|
+
// **0.3.24 add-agent socket drift fix**: keep `state.tmux_endpoint` /
|
|
435
|
+
// `state.tmux_socket` synchronized with the transport actually used for the
|
|
436
|
+
// spawn. Without this, add-agent / fork-agent could spawn to a socket that
|
|
437
|
+
// never gets persisted, and the next coordinator tick would re-resolve to
|
|
438
|
+
// the workspace-hash socket and lose the new pane. Annotation runs inside
|
|
439
|
+
// the same `save_restart_projected_state` window — no parallel "annotate
|
|
440
|
+
// after spawn" race with coordinator and no double source of truth.
|
|
441
|
+
crate::lifecycle::launch::annotate_runtime_tmux_endpoint(&mut state, transport, workspace);
|
|
442
|
+
let team_key = restart_projection_team_key(&state, team);
|
|
443
|
+
// 0.5.32 (`.team/artifacts/restart-resumed-stale-activity-locate.md` §5):
|
|
444
|
+
// clear the matching `agent_health` observation on the new spawn cohort
|
|
445
|
+
// so five-line status summary and status --json do not surface a stale
|
|
446
|
+
// WORKING row from the pre-shutdown process. Best-effort: DB failure
|
|
447
|
+
// must not fail the start-agent path.
|
|
448
|
+
let _ = crate::db::agent_health_capture::clear_agent_health_observation(
|
|
449
|
+
workspace, &team_key, agent_id,
|
|
433
450
|
);
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
451
|
+
let skip_capture_backfill = if matches!(
|
|
452
|
+
start_mode,
|
|
453
|
+
StartMode::Fresh | StartMode::FreshAfterMissingRollout
|
|
454
|
+
) {
|
|
455
|
+
vec![agent_id.as_str()]
|
|
456
|
+
} else {
|
|
457
|
+
Vec::new()
|
|
458
|
+
};
|
|
459
|
+
save_restart_projected_state_with_capture_backfill_skip(
|
|
460
|
+
workspace,
|
|
461
|
+
&mut state,
|
|
462
|
+
&team_key,
|
|
463
|
+
&skip_capture_backfill,
|
|
464
|
+
&[agent_id.as_str()],
|
|
465
|
+
)?;
|
|
466
|
+
write_start_agent_start_event(
|
|
467
|
+
workspace,
|
|
468
|
+
agent_id,
|
|
469
|
+
&agent,
|
|
470
|
+
provider,
|
|
471
|
+
&spawn.plan,
|
|
472
|
+
start_mode,
|
|
473
|
+
&session_name,
|
|
474
|
+
&actual_spawn_window,
|
|
475
|
+
spawn_session_id,
|
|
476
|
+
tmux_start_mode_for_spawn(&spawn, into_existing_session),
|
|
477
|
+
)?;
|
|
478
|
+
replay_worker_target_missing_messages(workspace, agent_id, &team_key, &state, transport)?;
|
|
479
|
+
Ok(start_coordinator_for_workspace(workspace, Some(&team_key))?.ok)
|
|
480
|
+
})();
|
|
481
|
+
let coordinator_started = match post_spawn {
|
|
482
|
+
Ok(started) => started,
|
|
483
|
+
Err(error) => {
|
|
484
|
+
if let Err(rollback_error) = transport.kill_pane(&spawn.spawn.pane_id) {
|
|
485
|
+
return Err(LifecycleError::RequirementUnmet(format!(
|
|
486
|
+
"{error}; failed to roll back spawned pane {}: {rollback_error}",
|
|
487
|
+
spawn.spawn.pane_id.as_str()
|
|
488
|
+
)));
|
|
489
|
+
}
|
|
490
|
+
return Err(error);
|
|
491
|
+
}
|
|
459
492
|
};
|
|
460
|
-
save_restart_projected_state_with_capture_backfill_skip(
|
|
461
|
-
workspace,
|
|
462
|
-
&mut state,
|
|
463
|
-
&team_key,
|
|
464
|
-
&skip_capture_backfill,
|
|
465
|
-
&[agent_id.as_str()],
|
|
466
|
-
)?;
|
|
467
|
-
write_start_agent_start_event(
|
|
468
|
-
workspace,
|
|
469
|
-
agent_id,
|
|
470
|
-
&agent,
|
|
471
|
-
provider,
|
|
472
|
-
start_mode,
|
|
473
|
-
&session_name,
|
|
474
|
-
&actual_spawn_window,
|
|
475
|
-
spawn_session_id,
|
|
476
|
-
tmux_start_mode_for_spawn(&spawn, into_existing_session),
|
|
477
|
-
)?;
|
|
478
|
-
replay_worker_target_missing_messages(workspace, agent_id, &team_key, &state, transport)?;
|
|
479
|
-
let coordinator = start_coordinator_for_workspace(workspace, Some(&team_key))?;
|
|
480
|
-
let coordinator_started = coordinator.ok;
|
|
481
493
|
Ok(StartAgentOutcome::Running {
|
|
482
494
|
env: AgentActionEnvelope {
|
|
483
495
|
agent_id: agent_id.clone(),
|
|
@@ -1772,95 +1784,13 @@ fn write_start_agent_start_event(
|
|
|
1772
1784
|
agent_id: &AgentId,
|
|
1773
1785
|
agent: &serde_json::Value,
|
|
1774
1786
|
provider: crate::provider::Provider,
|
|
1787
|
+
plan: &crate::provider::CommandPlan,
|
|
1775
1788
|
start_mode: StartMode,
|
|
1776
1789
|
session_name: &SessionName,
|
|
1777
1790
|
window: &str,
|
|
1778
1791
|
session_id: Option<&SessionId>,
|
|
1779
1792
|
tmux_start_mode: &'static str,
|
|
1780
1793
|
) -> Result<(), LifecycleError> {
|
|
1781
|
-
let auth_mode = agent_auth_mode(agent);
|
|
1782
|
-
let model = agent.get("model").and_then(|v| v.as_str());
|
|
1783
|
-
let adapter = crate::provider::get_adapter(provider);
|
|
1784
|
-
// Contract C / F6.4: event log must record the same context-aware argv that the
|
|
1785
|
-
// actual spawn used — so the role/tools/MCP context appears in `start_agent.agent_start`.
|
|
1786
|
-
let command_agent = crate::lifecycle::worker_command_context::WorkerCommandAgent::from_json(
|
|
1787
|
-
agent,
|
|
1788
|
-
Some(agent_id.as_str()),
|
|
1789
|
-
provider,
|
|
1790
|
-
)?;
|
|
1791
|
-
let system_prompt =
|
|
1792
|
-
crate::lifecycle::worker_command_context::compile_worker_system_prompt(&command_agent)?;
|
|
1793
|
-
let tools = crate::lifecycle::worker_command_context::resolved_tool_strings_for_command(
|
|
1794
|
-
&command_agent,
|
|
1795
|
-
provider,
|
|
1796
|
-
)?;
|
|
1797
|
-
let resolved_tool_refs: Vec<&str> = tools.iter().map(String::as_str).collect();
|
|
1798
|
-
let mcp_config = adapter
|
|
1799
|
-
.mcp_config(auth_mode)
|
|
1800
|
-
.map_err(|e| LifecycleError::Provider(e.to_string()))?;
|
|
1801
|
-
let team_id = agent.get("owner_team_id").and_then(|v| v.as_str());
|
|
1802
|
-
let mcp_config = crate::lifecycle::launch::resolve_mcp_config(
|
|
1803
|
-
mcp_config,
|
|
1804
|
-
workspace,
|
|
1805
|
-
agent_id.as_str(),
|
|
1806
|
-
team_id.unwrap_or(""),
|
|
1807
|
-
);
|
|
1808
|
-
let mcp_config_path = crate::lifecycle::launch::write_worker_mcp_config(
|
|
1809
|
-
workspace,
|
|
1810
|
-
agent_id.as_str(),
|
|
1811
|
-
&mcp_config,
|
|
1812
|
-
)?;
|
|
1813
|
-
let profile_launch =
|
|
1814
|
-
crate::lifecycle::profile_launch::prepare_provider_profile_launch_from_json(
|
|
1815
|
-
workspace,
|
|
1816
|
-
agent_id.as_str(),
|
|
1817
|
-
agent,
|
|
1818
|
-
Some(&mcp_config),
|
|
1819
|
-
)?;
|
|
1820
|
-
let command_model = profile_launch.command_overrides.model.as_deref().or(model);
|
|
1821
|
-
// 0.4.x provider effort MVP: start_agent path preserves effort from the
|
|
1822
|
-
// persisted agent JSON.
|
|
1823
|
-
let start_agent_effort =
|
|
1824
|
-
crate::lifecycle::launch::provider_effort_for_spawn_json(&agent, provider);
|
|
1825
|
-
if let Some(event_value) = crate::lifecycle::launch::provider_effort_event_if_dropped_json(
|
|
1826
|
-
&agent,
|
|
1827
|
-
provider,
|
|
1828
|
-
agent_id.as_str(),
|
|
1829
|
-
) {
|
|
1830
|
-
let _ = crate::event_log::EventLog::new(workspace)
|
|
1831
|
-
.write("provider.effort_unsupported", event_value);
|
|
1832
|
-
}
|
|
1833
|
-
let context = crate::provider::ProviderCommandContext {
|
|
1834
|
-
auth_mode,
|
|
1835
|
-
mcp_config: Some(&mcp_config),
|
|
1836
|
-
system_prompt: Some(system_prompt.as_str()),
|
|
1837
|
-
model: command_model,
|
|
1838
|
-
tools: &resolved_tool_refs,
|
|
1839
|
-
profile_launch: Some(&profile_launch),
|
|
1840
|
-
agent_id_hint: Some(agent_id.as_str()),
|
|
1841
|
-
effort: start_agent_effort,
|
|
1842
|
-
};
|
|
1843
|
-
let mut plan = match session_id {
|
|
1844
|
-
Some(session_id) => adapter
|
|
1845
|
-
.build_resume_command_plan(Some(session_id), context)
|
|
1846
|
-
.map_err(|e| LifecycleError::Provider(e.to_string()))?,
|
|
1847
|
-
None => adapter
|
|
1848
|
-
.build_command_plan(context)
|
|
1849
|
-
.map_err(|e| LifecycleError::Provider(e.to_string()))?,
|
|
1850
|
-
};
|
|
1851
|
-
if !plan.managed_mcp_config && !profile_launch.managed_mcp_config {
|
|
1852
|
-
crate::lifecycle::launch::point_native_mcp_config_at_file(
|
|
1853
|
-
&mut plan.argv,
|
|
1854
|
-
provider,
|
|
1855
|
-
&mcp_config_path,
|
|
1856
|
-
);
|
|
1857
|
-
}
|
|
1858
|
-
crate::lifecycle::launch::fill_spawn_placeholders_full(
|
|
1859
|
-
&mut plan.argv,
|
|
1860
|
-
workspace,
|
|
1861
|
-
agent_id.as_str(),
|
|
1862
|
-
team_id,
|
|
1863
|
-
);
|
|
1864
1794
|
crate::event_log::EventLog::new(workspace)
|
|
1865
1795
|
.write(
|
|
1866
1796
|
"start_agent.agent_start",
|