抽离 DirectProject 身份解析模块

将项目 canonical identity 与 digest 放入独立文件

保持 Codex app-server 线程池调用接口不变
This commit is contained in:
2026-09-15 15:22:39 +08:00
committed by kdletters
parent 76bbeb6848
commit 5bc7340304
2 changed files with 52 additions and 46 deletions
@@ -0,0 +1,50 @@
//! DirectProject 线程池身份的 canonical 解析与摘要。
use super::super::*;
use sha2::{Digest, Sha256};
pub(super) fn direct_codex_canonical_project_identity(
root: &std::path::Path,
) -> Result<(std::path::PathBuf, String), String> {
let (canonical_root, _) = resolve_direct_codex_project_authority(root)?;
let manifest = read_manifest(&canonical_root.join(".agent/manifest.json"))
.map_err(|error| format!("读取 DirectProject 权威项目身份失败:{error}"))?;
let manifest_project_id = manifest.project_id.trim();
if manifest_project_id.is_empty() || manifest_project_id.chars().count() > 256 {
return Err("DirectProject manifest.projectId 不满足身份边界".to_string());
}
let path_identity = direct_codex_os_path_identity_bytes(&canonical_root);
Ok((
canonical_root,
direct_codex_project_identity_digest(&path_identity, manifest_project_id.as_bytes()),
))
}
fn direct_codex_os_path_identity_bytes(path: &std::path::Path) -> Vec<u8> {
#[cfg(unix)]
{
use std::os::unix::ffi::OsStrExt;
return path.as_os_str().as_bytes().to_vec();
}
#[cfg(windows)]
{
use std::os::windows::ffi::OsStrExt;
let mut bytes = Vec::new();
for unit in path.as_os_str().encode_wide() {
bytes.extend_from_slice(&unit.to_le_bytes());
}
return bytes;
}
#[cfg(not(any(unix, windows)))]
path.as_os_str().to_string_lossy().as_bytes().to_vec()
}
fn direct_codex_project_identity_digest(path_identity: &[u8], project_id: &[u8]) -> String {
let mut digest = Sha256::new();
digest.update(b"genarrative-direct-project-identity.v1\0");
digest.update((path_identity.len() as u64).to_le_bytes());
digest.update(path_identity);
digest.update((project_id.len() as u64).to_le_bytes());
digest.update(project_id);
format!("{:x}", digest.finalize())
}
@@ -12,6 +12,8 @@ use uuid::Uuid;
mod direct_project_history_wire;
use direct_project_history_wire::build_direct_project_history_injection_params;
mod direct_project_identity;
use direct_project_identity::*;
const GAME_CREATOR_CODEX_APP_SERVER_PROVIDER_ID: &str = "genarrative_agc";
const GAME_CREATOR_CODEX_APP_SERVER_API_KEY_ENV: &str = "GENARRATIVE_AGC_CODEX_API_KEY";
@@ -3778,52 +3780,6 @@ pub(crate) async fn direct_game_creator_codex_chat_at_with_observer(
.await
}
fn direct_codex_canonical_project_identity(
root: &std::path::Path,
) -> Result<(std::path::PathBuf, String), String> {
let (canonical_root, _) = resolve_direct_codex_project_authority(root)?;
let manifest = read_manifest(&canonical_root.join(".agent/manifest.json"))
.map_err(|error| format!("读取 DirectProject 权威项目身份失败:{error}"))?;
let manifest_project_id = manifest.project_id.trim();
if manifest_project_id.is_empty() || manifest_project_id.chars().count() > 256 {
return Err("DirectProject manifest.projectId 不满足身份边界".to_string());
}
let path_identity = direct_codex_os_path_identity_bytes(&canonical_root);
Ok((
canonical_root,
direct_codex_project_identity_digest(&path_identity, manifest_project_id.as_bytes()),
))
}
fn direct_codex_os_path_identity_bytes(path: &std::path::Path) -> Vec<u8> {
#[cfg(unix)]
{
use std::os::unix::ffi::OsStrExt;
return path.as_os_str().as_bytes().to_vec();
}
#[cfg(windows)]
{
use std::os::windows::ffi::OsStrExt;
let mut bytes = Vec::new();
for unit in path.as_os_str().encode_wide() {
bytes.extend_from_slice(&unit.to_le_bytes());
}
return bytes;
}
#[cfg(not(any(unix, windows)))]
path.as_os_str().to_string_lossy().as_bytes().to_vec()
}
fn direct_codex_project_identity_digest(path_identity: &[u8], project_id: &[u8]) -> String {
let mut digest = Sha256::new();
digest.update(b"genarrative-direct-project-identity.v1\0");
digest.update((path_identity.len() as u64).to_le_bytes());
digest.update(path_identity);
digest.update((project_id.len() as u64).to_le_bytes());
digest.update(project_id);
format!("{:x}", digest.finalize())
}
pub(crate) async fn direct_game_creator_codex_chat_at_with_optional_observer(
root: &std::path::Path,
system_prompt: String,