Codex Handbook
tui/src/hooks_rpc.rs 100 lines
use codex_app_server_client::AppServerRequestHandle;use codex_app_server_protocol::ClientRequest;use codex_app_server_protocol::ConfigBatchWriteParams;use codex_app_server_protocol::ConfigWriteResponse;use codex_app_server_protocol::HookMetadata;use codex_app_server_protocol::HookTrustStatus;use codex_app_server_protocol::HooksListEntry;use codex_app_server_protocol::HooksListParams;use codex_app_server_protocol::HooksListResponse;use codex_app_server_protocol::MergeStrategy;use codex_app_server_protocol::RequestId;use color_eyre::eyre::Result;use color_eyre::eyre::WrapErr;use std::path::Path;use std::path::PathBuf;use uuid::Uuid;#[derive(Clone, Debug, Eq, PartialEq)]pub(crate) struct HookTrustUpdate {    pub(crate) key: String,    pub(crate) current_hash: String,}pub(crate) async fn fetch_hooks_list(    request_handle: AppServerRequestHandle,    cwd: PathBuf,) -> Result<HooksListResponse> {    let request_id = RequestId::String(format!("hooks-list-{}", Uuid::new_v4()));    request_handle        .request_typed(ClientRequest::HooksList {            request_id,            params: HooksListParams { cwds: vec![cwd] },        })        .await        .wrap_err("hooks/list failed in TUI")}pub(crate) fn hooks_list_entry_for_cwd(response: HooksListResponse, cwd: &Path) -> HooksListEntry {    response        .data        .into_iter()        .find(|entry| entry.cwd.as_path() == cwd)        .unwrap_or_else(|| HooksListEntry {            cwd: cwd.to_path_buf(),            hooks: Vec::new(),            warnings: Vec::new(),            errors: Vec::new(),        })}pub(crate) fn hook_needs_review(hook: &HookMetadata) -> bool {    matches!(        hook.trust_status,        HookTrustStatus::Untrusted | HookTrustStatus::Modified    )}pub(crate) async fn write_hook_trusts(    request_handle: AppServerRequestHandle,    trust_updates: Vec<HookTrustUpdate>,) -> Result<ConfigWriteResponse> {    let request_id = RequestId::String(format!("hooks-config-write-{}", Uuid::new_v4()));    let value = serde_json::Value::Object(        trust_updates            .into_iter()            .map(|update| {                (                    update.key,                    serde_json::json!({                        "trusted_hash": update.current_hash,                    }),                )            })            .collect(),    );    request_handle        .request_typed(ClientRequest::ConfigBatchWrite {            request_id,            params: ConfigBatchWriteParams {                edits: vec![codex_app_server_protocol::ConfigEdit {                    key_path: "hooks.state".to_string(),                    value,                    merge_strategy: MergeStrategy::Upsert,                }],                file_path: None,                expected_version: None,                reload_user_config: true,            },        })        .await        .wrap_err("config/batchWrite failed while updating hook trust in TUI")}pub(crate) async fn write_hook_trust(    request_handle: AppServerRequestHandle,    key: String,    current_hash: String,) -> Result<ConfigWriteResponse> {    write_hook_trusts(request_handle, vec![HookTrustUpdate { key, current_hash }]).await}