737a2266b9
- owner 独占锁改为可多窗口同时持有的界面参与锁 agent-runner.gui-participant.lock - Runner 启动检查、attach 门禁与 watchdog 改用参与锁存活判定,最后一个窗口退出才关停 Runner - 窗口启动只采纳现有 owner claim,登录/refresh/退出/换号才发布新 epoch claim - 同 claim 重复 attach 改为幂等空操作,不再清空 Runner 平台登录态 - manifest 失效与 Runtime update relay 接收端改为按 token 去重的注册表并广播,失败只淘汰该接收端 - GUI 退出先释放参与锁,仍有其它窗口时保留 Runner 并记录 retained_for_other_windows - Runner 启动失败时按最新 endpoint 复用一次,避免两窗口同时冷启动被实例锁竞争误报 - 更新 runner 定向测试、GUI 生命周期集成测试与自检用例 - 同步 AGC 技术方案、决策记录、踩坑记录与多窗口里程碑/实施计划
71 lines
3.0 KiB
Rust
71 lines
3.0 KiB
Rust
mod client;
|
|
mod dispatch;
|
|
mod endpoint;
|
|
mod project_owner;
|
|
mod protocol;
|
|
mod server;
|
|
mod state;
|
|
|
|
#[allow(unused_imports)]
|
|
pub(crate) use client::{
|
|
attach_external_agent_runner_gui_owner, cancel_external_agent_runner_goal,
|
|
clear_external_agent_runner_platform_session, compact_external_agent_runner_context,
|
|
configure_external_agent_runner, configure_external_agent_runner_read_only,
|
|
continue_external_agent_runner_action, ensure_external_agent_runner_started,
|
|
ensure_external_agent_runner_started_for_gui, hold_external_agent_runner_gui_participant_lock,
|
|
install_external_agent_runner_platform_session,
|
|
interrupt_external_agent_runner_provider_for_steer_decision, notify_external_agent_runner,
|
|
pause_external_agent_runner, read_external_agent_runner_status,
|
|
require_external_agent_runner_configured_for_cli_runtime_write,
|
|
require_external_agent_runner_for_cli_runtime_write, resume_external_agent_runner,
|
|
shutdown_external_agent_runner, shutdown_external_agent_runner_for_client_exit,
|
|
shutdown_external_agent_runner_for_gui_exit, shutdown_external_agent_runner_if_idle,
|
|
steer_external_agent_runner, wake_external_agent_runner_pending,
|
|
wake_external_agent_runner_pending_for_run,
|
|
};
|
|
#[cfg(windows)]
|
|
pub(crate) use endpoint::validate_windows_regular_file_handle;
|
|
pub(crate) use endpoint::{external_agent_runner_enabled, external_agent_runner_is_server_process};
|
|
#[allow(unused_imports)]
|
|
pub(crate) use protocol::{ExternalAgentRunnerStatus, EXTERNAL_AGENT_RUNNER_PROTOCOL_VERSION};
|
|
pub(crate) use server::{
|
|
bind_loopback_listener_with_linux_fallback, run_external_agent_runner_server,
|
|
};
|
|
|
|
#[cfg(test)]
|
|
pub(crate) fn simulate_external_agent_runner_cross_boot_owner_claim_for_test(
|
|
root: &std::path::Path,
|
|
config_dir: &std::path::Path,
|
|
previous_boot_id: &str,
|
|
current_boot_id: &str,
|
|
) -> Result<(std::path::PathBuf, Option<String>), String> {
|
|
let previous = project_owner::acquire_external_agent_runner_project_execution_owner(
|
|
root,
|
|
previous_boot_id,
|
|
protocol::EXTERNAL_AGENT_RUNNER_PROTOCOL_VERSION,
|
|
)?;
|
|
drop(previous);
|
|
let state = state::ExternalAgentRunnerServerState::new(
|
|
config_dir.join(protocol::EXTERNAL_AGENT_RUNNER_ENDPOINT_FILE_NAME),
|
|
protocol::ExternalAgentRunnerEndpoint {
|
|
protocol_version: protocol::EXTERNAL_AGENT_RUNNER_PROTOCOL_VERSION,
|
|
pid: std::process::id(),
|
|
boot_id: current_boot_id.to_string(),
|
|
port: 41009,
|
|
token: "owner-provider-token-owner-provider-token".to_string(),
|
|
heartbeat_at: 1_725_000_000_000,
|
|
executable_fingerprint: Some("a".repeat(64)),
|
|
process_start_identity: None,
|
|
},
|
|
);
|
|
let claim = state.claim_project_execution_owner(root)?;
|
|
let result = (claim.root, claim.recovered_from_boot_id);
|
|
let second = state.claim_project_execution_owner(root)?;
|
|
if second.recovered_from_boot_id.is_some() {
|
|
return Err("同 boot execution owner 重入重复触发恢复".to_string());
|
|
}
|
|
Ok(result)
|
|
}
|
|
#[cfg(test)]
|
|
mod tests;
|