清理局部未使用代码并收紧测试编译边界

删除无消费者的包装、声明和重导出
将Direct执行测试入口限定为测试构建
记录86条复核与33条清理结果,验证85项回归
This commit is contained in:
2026-09-23 12:18:32 +00:00
parent 268f45015c
commit 600beb452b
26 changed files with 173 additions and 381 deletions
@@ -47,10 +47,8 @@ mod runtime_tools;
mod skill_pack;
use codex_app_server::*;
pub(crate) use codex_app_server::{
cancel_direct_codex_turn_at,
direct_codex_canonical_project_identity_for_commands as direct_codex_canonical_project_identity,
direct_game_creator_codex_chat_at, direct_game_creator_home_codex_chat,
direct_thread_id_for_project, DirectTurnCancelView,
cancel_direct_codex_turn_at, direct_game_creator_codex_chat_at,
direct_game_creator_home_codex_chat, direct_thread_id_for_project, DirectTurnCancelView,
};
use codex_cli::*;
pub(crate) use codex_cli::{
@@ -16,11 +16,8 @@ use process_tree::{OwnedProcessTree, ProcessTreeExitProof};
mod direct_project_identity;
mod execution;
mod model_catalog;
pub(crate) use direct_project_identity::direct_thread_id_for_project;
use direct_project_identity::*;
pub(crate) use direct_project_identity::{
direct_codex_canonical_project_identity as direct_codex_canonical_project_identity_for_commands,
direct_thread_id_for_project,
};
use execution::ExecutionAdapter;
const GAME_CREATOR_CODEX_APP_SERVER_PROVIDER_ID: &str = "genarrative_agc";
@@ -4998,24 +4995,6 @@ pub(crate) async fn direct_game_creator_codex_chat_at(
.await
}
pub(crate) async fn direct_game_creator_codex_chat_at_with_observer(
root: &std::path::Path,
system_prompt: String,
user_prompt: String,
observer: &mut (dyn FnMut(DirectCodexTurnObservation) + Send),
) -> Result<String, String> {
direct_game_creator_codex_chat_at_with_optional_observer(
root,
system_prompt,
user_prompt,
DirectCodexTurnKind::User,
None,
Some(observer),
None,
)
.await
}
pub(crate) async fn direct_game_creator_codex_chat_at_with_optional_observer(
root: &std::path::Path,
system_prompt: String,
@@ -4,12 +4,9 @@ mod model;
mod validation;
mod wire;
pub(crate) use model::{
DirectCodexUserAttachmentReferencePart, DirectCodexUserContentPart, DirectCodexUserItem,
DirectCodexUserMessageItem, DirectCodexUserRole, DirectCodexUserRuntimeRegionPart,
};
pub(crate) use model::DirectCodexUserItem;
pub(crate) use validation::validate_direct_codex_user_item;
pub(crate) use wire::{
direct_codex_user_item_to_codex_turn_input, direct_codex_user_item_to_prompt,
direct_codex_user_item_to_response_item, direct_codex_user_item_to_wire_input,
direct_codex_user_item_to_response_item,
};
@@ -483,6 +483,7 @@ pub(super) async fn begin(
Ok(ExecutionSessionGuard { session })
}
#[cfg(test)]
pub(super) fn open_at(
host: &Path,
root: &Path,
@@ -32,8 +32,6 @@ tokio::task_local! {
pub(crate) struct ExternalMcpServer {
_bridge: super::direct_tool_bridge::DirectToolBridge,
pub(crate) url: String,
pub(crate) token: String,
task: tokio::task::JoinHandle<()>,
}
@@ -2159,8 +2157,6 @@ pub(crate) async fn start_external_mcp_loopback(
}
*guard = Some(ExternalMcpServer {
_bridge: bridge,
url: url.clone(),
token: token.clone(),
task,
});
Ok((url, token))
@@ -1746,10 +1746,6 @@ pub(in crate::agent) struct PreparedPlatformArtAssetGeneration {
}
impl PreparedPlatformArtAssetGeneration {
pub(in crate::agent) fn slice_count(&self) -> usize {
self.slices.len()
}
fn validate_frozen_session(&self) -> Result<(), String> {
self.platform_session_fence
.as_ref()
@@ -1,13 +1,6 @@
use super::*;
use std::sync::OnceLock;
pub(super) fn render_agent_runtime_prompt_context(
root: &Path,
agent_id: &str,
) -> Result<String, String> {
render_agent_runtime_prompt_context_for_session(root, agent_id, None, true)
}
pub(super) fn render_agent_runtime_prompt_context_for_session(
root: &Path,
agent_id: &str,
@@ -394,13 +387,6 @@ pub(crate) fn build_game_creator_role_agent_chat_request_for_session(
Ok((llm, config_path, request))
}
pub(super) fn build_game_creator_role_agent_context(
root: &Path,
agent_id: &str,
) -> Result<(GameCreatorLlmConfig, String, String), String> {
build_game_creator_role_agent_context_for_session(root, agent_id, None)
}
pub(super) fn build_game_creator_role_agent_context_for_session(
root: &Path,
agent_id: &str,
@@ -262,10 +262,6 @@ pub(crate) fn register_game_creator_manifest_invalidation_event_sink(
sinks.push(sink);
}
fn remove_game_creator_manifest_invalidation_event_sink(token: &str) {
lock_game_creator_manifest_invalidation_event_sinks().retain(|sink| sink.token != token);
}
#[cfg(test)]
pub(crate) struct GameCreatorManifestInvalidationEventSinkTestGuard {
_isolation: std::sync::MutexGuard<'static, ()>,
@@ -253,14 +253,6 @@ fn acceptance_evidence_tools_at<'a>(
Ok(tools)
}
#[derive(Clone, Debug, Eq, PartialEq)]
struct FastGddFileReadCoverage {
content_sha256: String,
start_line: usize,
end_line: usize,
total_lines: usize,
}
fn validate_acceptance_required_evidence(
node: &AgentRuntimeGoalContractAcceptanceNode,
evidence_tools: &BTreeSet<String>,
@@ -14464,17 +14464,6 @@ pub(in crate::agent) fn inherited_gameplay_semantics_gap_with_external_javascrip
missing.map(str::to_string)
}
pub(in crate::agent) fn inherited_gameplay_semantics_gap(
task: &str,
html: &[u8],
) -> Option<String> {
inherited_gameplay_semantics_gap_with_external_javascript(
task,
html,
&ExternalGameplayJavascript::default(),
)
}
fn autonomous_inherited_gameplay_semantics_gap_at(
root: &Path,
contract: &AgentRuntimeAutonomousCompletionContract,
@@ -325,26 +325,6 @@ pub(in crate::agent) fn game_creator_agent_runtime_llm_request_fingerprint(
Ok(format!("{:x}", Sha256::digest(serialized)))
}
pub(in crate::agent) fn game_creator_agent_runtime_provider_config_fingerprint(
llm: &GameCreatorLlmConfig,
) -> Result<String, String> {
let app_config = load_game_creator_app_config()?;
let agent_mode = normalize_game_creator_agent_mode(&app_config.agent_mode)?;
let codex_cli_version = if matches!(
agent_mode.as_str(),
GAME_CREATOR_AGENT_MODE_CODEX_APP_SERVER | GAME_CREATOR_AGENT_MODE_CODEX_CLI
) {
Some(game_creator_codex_cli_version_identity()?)
} else {
None
};
game_creator_agent_runtime_provider_config_fingerprint_for_mode(
&agent_mode,
codex_cli_version.as_deref(),
llm,
)
}
fn game_creator_agent_runtime_provider_config_fingerprint_for_mode(
agent_mode: &str,
codex_cli_version: Option<&str>,
@@ -1643,25 +1623,6 @@ pub(in crate::agent) fn game_creator_agent_runtime_provider_request_attempt_id(
)
}
pub(in crate::agent) fn game_creator_agent_runtime_provider_request_slot_for_id(
snapshot: &AgentRuntimeProviderRequestSnapshot,
request_id: &str,
) -> Option<String> {
let base_request_id = game_creator_agent_runtime_provider_request_id(snapshot);
for attempt in 0..=64_usize {
let candidate =
game_creator_agent_runtime_provider_request_attempt_id(&base_request_id, attempt);
if candidate == request_id {
return Some(if attempt == 0 {
snapshot.request_slot.clone()
} else {
format!("{}-transient-{attempt}", snapshot.request_slot)
});
}
}
None
}
pub(in crate::agent) fn resolve_game_creator_agent_runtime_provider_request_attempt_at_locked(
root: &Path,
base_request_id: &str,
@@ -280,15 +280,6 @@ fn game_creator_agent_runtime_public_event_text(
Some(summary)
}
pub(crate) fn start_game_creator_agent_runtime_turn_at(
root: &Path,
agent_id: &str,
prompt: &str,
run_id: &str,
) -> Result<AgentRuntimeState, String> {
start_game_creator_agent_runtime_turn_for_session_at(root, agent_id, None, prompt, run_id)
}
pub(crate) fn start_game_creator_agent_runtime_turn_for_session_at(
root: &Path,
agent_id: &str,
@@ -26,35 +26,6 @@ fn autonomous_art_director_non_canvas_validation_command_is_denied(
)
}
fn autonomous_design_foundation_command_is_allowed(command_id: &str) -> bool {
matches!(
command_id,
"memory.read"
| "conversation.read"
| "asset.list"
| "asset.library.list"
| "project.index"
| "project.search"
| "file.read"
| "project.diff"
| "git.inspect"
| "file.list"
| "file.write"
| "file.delete"
| "project.patchset"
| "task.list"
| "command.run_limited"
| "image.inspect"
| "canvas.asset_generate"
| "canvas.asset_import"
| "asset.register"
| "ui.workflow.run"
| "agent.audit"
| "agent.action_history"
| "agent.run_status"
)
}
pub(in crate::agent) fn refresh_game_creator_agent_runtime_tool_policy(
root: &Path,
state: &mut AgentRuntimeState,
@@ -19,10 +19,8 @@ pub use model::{
DiscoveredBrowserKind,
};
pub(crate) use process::check_browser_health;
pub use process::validate_local_preview_in_browser;
pub(crate) use process::validate_local_preview_in_browser_with_cancellation;
pub use process::{
validate_local_preview_in_browser, validate_local_preview_in_browser_with_interaction,
};
pub(crate) use sweep::sweep_stale_browser_processes;
pub(crate) use model::required_viewport_playtests_passed;
@@ -2374,16 +2374,6 @@ pub(crate) fn initialize_windows_game_creator_directory_owner_for_current_user(
secure_windows_game_creator_path_for_current_user_with_owner_policy(path, true, true, true)
}
/// Repairs an AGC-managed private object after an explicit UAC elevation.
/// Foreign-owned regular files/directories are deliberately reassigned to the
/// current token user here. The caller has already rejected links/reparse
/// points, and the final strict verification below is mandatory.
#[cfg(windows)]
pub(crate) fn repair_game_creator_private_acl_for_current_user(path: &Path) -> Result<(), String> {
let target_user_sid = current_windows_token_user_sid_string()?;
repair_game_creator_private_acl_for_user_sid(path, &target_user_sid)
}
#[cfg(windows)]
fn current_windows_token_user_sid_string() -> Result<String, String> {
use std::ffi::c_void;
@@ -518,12 +518,6 @@ pub(crate) fn disconnect_managed_editor_project(
pub(crate) fn unity_execution_fence_path(config: &Path) -> PathBuf {
editor_execution_fence_path(ManagedEditor::Unity, config)
}
pub(crate) fn unity_uncertain_fence_path(config: &Path) -> PathBuf {
editor_uncertain_fence_path(ManagedEditor::Unity, config)
}
pub(crate) fn mark_unity_execution_uncertain_at(config: &Path) -> Result<(), String> {
mark_editor_execution_uncertain_at(ManagedEditor::Unity, config)
}
pub(crate) fn unity_execute_receipt_is_valid(value: &Value) -> bool {
editor_execute_receipt_is_valid(value)
}
@@ -185,13 +185,6 @@ pub(crate) fn ack(event_ids: &[String]) {
}
}
pub(crate) fn generation() -> u64 {
let state = queue()
.lock()
.unwrap_or_else(|poisoned| poisoned.into_inner());
state.sequence
}
#[cfg(test)]
pub(crate) fn reset_for_tests() {
let mut state = queue()
@@ -1034,17 +1034,6 @@ pub(crate) fn mark_game_creator_agent_goal_cleared_for_runtime_at_locked(
Ok(Some(goal))
}
pub(crate) fn mark_game_creator_agent_goal_cleared_for_runtime_at(
root: &Path,
state: &AgentRuntimeState,
) -> Result<Option<AgentGoalRecord>, String> {
let _lock = acquire_game_creator_agent_runtime_project_write_lock_with_wait(
root,
"runtime.goal.cleared",
)?;
mark_game_creator_agent_goal_cleared_for_runtime_at_locked(root, state)
}
pub(crate) fn complete_game_creator_agent_goal_for_runtime_at_locked(
root: &Path,
state: &mut AgentRuntimeState,
@@ -1725,7 +1725,6 @@ struct LlmAgentHandoff {
const DIAGNOSTIC_LOG_MAX_BYTES: u64 = 256 * 1024;
static DIAGNOSTIC_LOG_LOCK: OnceLock<Mutex<()>> = OnceLock::new();
static STARTUP_PANIC_LOG_PATH: OnceLock<PathBuf> = OnceLock::new();
static STARTUP_ERROR_DIALOG_SHOWN: AtomicBool = AtomicBool::new(false);
#[tauri::command]
@@ -702,11 +702,6 @@ pub(crate) fn platform_session_is_available() -> bool {
current_platform_session().is_some()
}
pub(crate) fn platform_session_service_identity() -> Option<String> {
current_platform_session()
.map(|snapshot| format!("{}\nuser:{}", snapshot.api_base_url, snapshot.user_id))
}
#[cfg(test)]
static PLATFORM_SESSION_TEST_LOCK: OnceLock<Mutex<()>> = OnceLock::new();
@@ -2492,99 +2492,6 @@ pub(crate) fn read_agent_db_records_bounded(
Ok((records.into_iter().collect(), truncated))
}
/// 全量扫描 Agent 本地索引,返回全部命中 `predicate` 的记录。
///
/// 有界尾窗(`read_agent_db_records_bounded`)保留的是最新的一段:它能证明「在」,
/// 证明不了「不在」,也看不见已经滑出窗口的更旧记录。凡是要拿扫描结果做 fail-closed
/// 判据的调用方——「这条回执消费过没有」「这个 (gddId, version) 下有没有第二条冲突
/// audit」——都必须走这条路。用尾窗做这种判据只有两种输出,而两种都是错的:命不中就
/// 报「不存在」会把视野缺失当成事实,命不中就报错会把首次写入拦在写之前。
///
/// 扫描上限与写侧的幂等扫描完全一致(`AGENT_DB_MAX_ACTION_RECEIPT_SCAN_BYTES` /
/// `AGENT_DB_MAX_SCAN_RECORDS`),所以只要追加还写得进去,这里就一定扫得完;不会出现
/// 「写得进但读不到」的窗口——那正是尾窗留下的那道两个数量级的缺口。
///
/// `max_matches` 是命中数上限,超出报错而不是静默截断:判据宁可停,也不能拿一个不完
/// 整的命中集合下结论。
pub(crate) fn read_agent_db_records_matching(
root: &Path,
max_matches: usize,
predicate: impl Fn(&serde_json::Value) -> bool,
) -> Result<Vec<serde_json::Value>, String> {
let path = root.join(".agent/agent.db");
let Some(directory) = open_agent_db_directory(root, false)? else {
return Ok(Vec::new());
};
let append_lock = project_append_lock_for(&path)?;
let _append_guard = append_lock.lock_process("Agent 本地索引")?;
verify_agent_db_directory_current(&directory)?;
let Some(mut storage) = open_agent_db_storage(directory, false, false)? else {
return Ok(Vec::new());
};
let length = storage
.file
.metadata()
.map_err(|error| {
format!(
"读取 Agent 本地索引元数据失败:{}: {error}",
storage.path.display()
)
})?
.len();
if length > AGENT_DB_MAX_ACTION_RECEIPT_SCAN_BYTES {
return Err(format!(
"Agent 本地索引超过 {} 字节扫描上限:{}",
AGENT_DB_MAX_ACTION_RECEIPT_SCAN_BYTES,
storage.path.display()
));
}
storage.file.seek(SeekFrom::Start(0)).map_err(|error| {
format!(
"定位 Agent 本地索引失败:{}: {error}",
storage.path.display()
)
})?;
let mut reader = BufReader::new(&mut storage.file);
let mut matches = Vec::new();
let mut record_count = 0usize;
while let Some(line) = read_agent_db_jsonl_line_bounded(&mut reader, &storage.path)? {
// 崩溃留下的残缺末行从未提交成功,写侧下一次追加会把它截掉。它不是记录,也不
// 该让判据 fail closed——扫到这里停住就够了。
if !line.complete {
break;
}
if line.content.iter().all(|byte| byte.is_ascii_whitespace()) {
continue;
}
record_count = record_count.saturating_add(1);
if record_count > AGENT_DB_MAX_SCAN_RECORDS {
return Err(format!(
"Agent 本地索引超过 {} 条记录扫描上限:{}",
AGENT_DB_MAX_SCAN_RECORDS,
storage.path.display()
));
}
let record =
serde_json::from_slice::<serde_json::Value>(&line.content).map_err(|error| {
format!(
"解析 Agent 本地索引失败:{}: {error}",
storage.path.display()
)
})?;
if !predicate(&record) {
continue;
}
if matches.len() >= max_matches {
return Err(format!(
"Agent 本地索引命中记录超过 {max_matches} 条上限:{}",
storage.path.display()
));
}
matches.push(record);
}
Ok(matches)
}
pub(crate) fn read_agent_db_action_receipts_by_identities(
root: &Path,
identities: &BTreeSet<(String, String, String)>,
@@ -3186,48 +3093,6 @@ pub(crate) fn read_agent_db_lifecycle_transitions_at(
.unwrap_or_default())
}
pub(crate) fn read_agent_db_lifecycle_transitions_matching_at(
root: &Path,
record_type: &str,
identity_field: &str,
identity_value: &str,
expected_identity: &serde_json::Value,
) -> Result<Vec<String>, String> {
let (expected_identity_field, _) = agent_db_lifecycle_key_fields(record_type)?;
if identity_field != expected_identity_field
|| (record_type == AGENT_DB_PROVIDER_REQUEST_LIFECYCLE_RECORD_TYPE
&& !is_valid_agent_db_provider_request_id(identity_value))
|| (record_type == AGENT_DB_FINALIZATION_LIFECYCLE_RECORD_TYPE
&& !is_valid_agent_db_finalization_id(identity_value))
{
return Err("Agent DB lifecycle 查询身份或 recordType 不受支持".to_string());
}
validate_agent_db_lifecycle_record_semantics(record_type, expected_identity, false)?;
let path = root.join(".agent/agent.db");
let Some(directory) = open_agent_db_directory(root, false)? else {
return Ok(Vec::new());
};
let append_lock = project_append_lock_for(&path)?;
let _append_guard = append_lock.lock_process("Agent 本地索引 lifecycle identity 查询")?;
verify_agent_db_directory_current(&directory)?;
let Some(mut storage) = open_agent_db_storage(directory, false, false)? else {
return Ok(Vec::new());
};
verify_agent_db_storage_current(&storage)?;
let scan =
scan_agent_db_lifecycle_records_unlocked(&mut storage.file, &storage.path, record_type)?;
verify_agent_db_storage_current(&storage)?;
let Some(sequence) = scan.sequences.get(identity_value) else {
return Ok(Vec::new());
};
validate_agent_db_lifecycle_record_identity(
&sequence.identity_record,
expected_identity,
record_type,
)?;
Ok(sequence.transitions_in_physical_order.clone())
}
pub(crate) fn read_agent_db_incomplete_provider_request_ids_at(
root: &Path,
agent_id: &str,
@@ -1441,14 +1441,6 @@ pub(crate) fn conversation_file_path_for_session(
))
}
pub(crate) fn conversation_file_path(
root: &Path,
agent_id: Option<&str>,
) -> Result<(PathBuf, Option<String>), String> {
let (path, agent_id, _session_id) = conversation_file_path_for_session(root, agent_id, None)?;
Ok((path, agent_id))
}
pub(crate) fn normalize_conversation_agent_id(agent_id: &str) -> Result<String, String> {
if agent_id.is_empty()
|| agent_id.contains("..")
@@ -570,18 +570,6 @@ pub(crate) fn collect_project_export_package_files(
Ok(files)
}
pub(crate) fn ensure_project_export_package_dir(
root: &Path,
relative_dir: &str,
) -> Result<(), String> {
let dir = resolve_local_project_path(root, relative_dir)?;
let metadata = checked_export_package_metadata(&dir, relative_dir)?;
if !metadata.is_dir() {
return Err(format!("{relative_dir} 必须是目录"));
}
Ok(())
}
pub(crate) fn collect_project_export_package_dir_files(
root: &Path,
relative_dir: &str,
@@ -12,19 +12,18 @@ pub(crate) use client::{
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,
hold_external_agent_runner_gui_participant_lock,
install_external_agent_runner_platform_session, 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,
};
pub(crate) use client::{
call_external_managed_editor, disconnect_external_managed_editor,
disconnect_external_managed_editor_project, mark_external_editor_uncertain,
call_external_managed_editor, disconnect_external_managed_editor_project,
mark_external_editor_uncertain,
};
pub(crate) use endpoint::external_agent_runner_process_start_identity;
#[cfg(windows)]
@@ -1065,12 +1065,6 @@ fn force_terminate_external_agent_runner_process(
Err("当前平台不支持核验并强制终止 Agent Runner".to_string())
}
pub(crate) fn shutdown_external_agent_runner() -> Result<(), String> {
let config_dir = external_agent_runner_config_dir()
.ok_or_else(|| "外部 Agent Runner 尚未配置 AppData;请显式传入 --config-dir".to_string())?;
shutdown_external_agent_runner_at(&config_dir)
}
pub(crate) fn attach_external_agent_runner_gui_owner(
event_sink: &GameCreatorManifestInvalidationEventSink,
) -> Result<(), String> {
@@ -1402,14 +1396,6 @@ pub(super) fn shutdown_external_agent_runner_for_client_exit_at(
Ok(true)
}
pub(crate) fn shutdown_external_agent_runner_for_client_exit() -> Result<bool, String> {
let _configure = lock_unpoisoned(external_agent_runner_configure_lock());
let Some(config_dir) = external_agent_runner_config_dir() else {
return Ok(true);
};
shutdown_external_agent_runner_for_client_exit_at(&config_dir)
}
/// 窗口退出的收尾:先释放本窗口参与锁,再决定 Runner 是否需要关闭。
///
/// 返回 `Ok(false)` 表示仍检测到其它窗口持有参与锁,Runner 必须保留给它们;
@@ -1563,12 +1549,6 @@ pub(crate) fn ensure_external_agent_runner_started() -> Result<(), String> {
ensure_external_agent_runner(&config_dir).map(|_| ())
}
pub(crate) fn ensure_external_agent_runner_started_for_gui() -> Result<(), String> {
EXTERNAL_AGENT_RUNNER_GUI_OWNER_REQUIRED_CLIENT
.store(true, std::sync::atomic::Ordering::Release);
ensure_external_agent_runner_started()
}
pub(crate) fn require_external_agent_runner_for_cli_runtime_write(
root: &Path,
) -> Result<(), String> {
@@ -1836,12 +1816,6 @@ pub(crate) fn call_external_managed_editor(
}
}
pub(crate) fn disconnect_external_managed_editor(
editor: crate::editor_adapters::ManagedEditor,
) -> Result<(), String> {
disconnect_external_managed_editor_project(editor, None)
}
pub(crate) fn disconnect_external_managed_editor_project(
editor: crate::editor_adapters::ManagedEditor,
project: Option<&Path>,

Some files were not shown because too many files have changed in this diff Show More