mirror of
https://github.com/pchuan98/codex.git
synced 2026-07-01 00:31:56 +08:00
chore(config) rm Feature::CodexGitCommit (#22412)
## Summary Removes the unused Feature::CodexGitCommit ## Testing - [x] tests pass
This commit is contained in:
committed by
GitHub
Unverified
parent
a98b57d065
commit
d18a7c982e
Generated
-11
@@ -1902,7 +1902,6 @@ dependencies = [
|
||||
"codex-feedback",
|
||||
"codex-file-search",
|
||||
"codex-file-watcher",
|
||||
"codex-git-attribution",
|
||||
"codex-git-utils",
|
||||
"codex-guardian",
|
||||
"codex-hooks",
|
||||
@@ -2912,16 +2911,6 @@ dependencies = [
|
||||
"tracing",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "codex-git-attribution"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"codex-core",
|
||||
"codex-extension-api",
|
||||
"codex-features",
|
||||
"pretty_assertions",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "codex-git-utils"
|
||||
version = "0.0.0"
|
||||
|
||||
@@ -46,7 +46,6 @@ members = [
|
||||
"execpolicy-legacy",
|
||||
"ext/extension-api",
|
||||
"ext/guardian",
|
||||
"ext/git-attribution",
|
||||
"ext/memories",
|
||||
"external-agent-migration",
|
||||
"external-agent-sessions",
|
||||
@@ -164,7 +163,6 @@ codex-exec-server = { path = "exec-server" }
|
||||
codex-execpolicy = { path = "execpolicy" }
|
||||
codex-extension-api = { path = "ext/extension-api" }
|
||||
codex-guardian = { path = "ext/guardian" }
|
||||
codex-git-attribution = { path = "ext/git-attribution" }
|
||||
codex-external-agent-migration = { path = "external-agent-migration" }
|
||||
codex-external-agent-sessions = { path = "external-agent-sessions" }
|
||||
codex-experimental-api-macros = { path = "codex-experimental-api-macros" }
|
||||
|
||||
@@ -42,7 +42,6 @@ codex-external-agent-migration = { workspace = true }
|
||||
codex-external-agent-sessions = { workspace = true }
|
||||
codex-features = { workspace = true }
|
||||
codex-guardian = { workspace = true }
|
||||
codex-git-attribution = { workspace = true }
|
||||
codex-git-utils = { workspace = true }
|
||||
codex-file-watcher = { workspace = true }
|
||||
codex-hooks = { workspace = true }
|
||||
|
||||
@@ -17,7 +17,6 @@ where
|
||||
S: AgentSpawner<StartThreadOptions, Spawned = NewThread, Error = CodexErr> + 'static,
|
||||
{
|
||||
let mut builder = ExtensionRegistryBuilder::<Config>::new();
|
||||
codex_git_attribution::install(&mut builder);
|
||||
codex_guardian::install(&mut builder, guardian_agent_spawner);
|
||||
Arc::new(builder.build())
|
||||
}
|
||||
|
||||
@@ -177,14 +177,6 @@ pub struct ConfigToml {
|
||||
/// Compact prompt used for history compaction.
|
||||
pub compact_prompt: Option<String>,
|
||||
|
||||
/// Optional commit attribution text for commit message co-author trailers.
|
||||
/// This top-level setting only takes effect when `[features].codex_git_commit`
|
||||
/// is enabled.
|
||||
///
|
||||
/// When enabled and unset, Codex uses `Codex <noreply@openai.com>`.
|
||||
/// Set to an empty string to disable automatic commit attribution.
|
||||
pub commit_attribution: Option<String>,
|
||||
|
||||
/// When set, restricts ChatGPT login to a specific workspace identifier.
|
||||
#[serde(default)]
|
||||
pub forced_chatgpt_workspace_id: Option<String>,
|
||||
|
||||
@@ -4026,10 +4026,6 @@
|
||||
"default": null,
|
||||
"description": "Preferred backend for storing CLI auth credentials. file (default): Use a file in the Codex home directory. keyring: Use an OS-specific keyring service. auto: Use the keyring if available, otherwise use a file."
|
||||
},
|
||||
"commit_attribution": {
|
||||
"description": "Optional commit attribution text for commit message co-author trailers. This top-level setting only takes effect when `[features].codex_git_commit` is enabled.\n\nWhen enabled and unset, Codex uses `Codex <noreply@openai.com>`. Set to an empty string to disable automatic commit attribution.",
|
||||
"type": "string"
|
||||
},
|
||||
"compact_prompt": {
|
||||
"description": "Compact prompt used for history compaction.",
|
||||
"type": "string"
|
||||
|
||||
@@ -7357,7 +7357,6 @@ async fn test_precedence_fixture_with_o3_profile() -> std::io::Result<()> {
|
||||
include_skill_instructions: true,
|
||||
include_environment_context: true,
|
||||
compact_prompt: None,
|
||||
commit_attribution: None,
|
||||
forced_chatgpt_workspace_id: None,
|
||||
forced_login_method: None,
|
||||
include_apply_patch_tool: true,
|
||||
@@ -7805,7 +7804,6 @@ async fn test_precedence_fixture_with_gpt3_profile() -> std::io::Result<()> {
|
||||
include_skill_instructions: true,
|
||||
include_environment_context: true,
|
||||
compact_prompt: None,
|
||||
commit_attribution: None,
|
||||
forced_chatgpt_workspace_id: None,
|
||||
forced_login_method: None,
|
||||
include_apply_patch_tool: true,
|
||||
@@ -7967,7 +7965,6 @@ async fn test_precedence_fixture_with_zdr_profile() -> std::io::Result<()> {
|
||||
include_skill_instructions: true,
|
||||
include_environment_context: true,
|
||||
compact_prompt: None,
|
||||
commit_attribution: None,
|
||||
forced_chatgpt_workspace_id: None,
|
||||
forced_login_method: None,
|
||||
include_apply_patch_tool: true,
|
||||
@@ -8114,7 +8111,6 @@ async fn test_precedence_fixture_with_gpt5_profile() -> std::io::Result<()> {
|
||||
include_skill_instructions: true,
|
||||
include_environment_context: true,
|
||||
compact_prompt: None,
|
||||
commit_attribution: None,
|
||||
forced_chatgpt_workspace_id: None,
|
||||
forced_login_method: None,
|
||||
include_apply_patch_tool: true,
|
||||
|
||||
@@ -478,15 +478,6 @@ pub struct Config {
|
||||
/// Compact prompt override.
|
||||
pub compact_prompt: Option<String>,
|
||||
|
||||
/// Optional commit attribution text for commit message co-author trailers.
|
||||
/// This top-level setting only takes effect when `[features].codex_git_commit`
|
||||
/// is enabled.
|
||||
///
|
||||
/// - `None`: use default attribution (`Codex <noreply@openai.com>`)
|
||||
/// - `Some("")` or whitespace-only: disable commit attribution
|
||||
/// - `Some("...")`: use the provided attribution text verbatim
|
||||
pub commit_attribution: Option<String>,
|
||||
|
||||
/// Optional external notifier command. When set, Codex will spawn this
|
||||
/// program after each completed *turn* (i.e. when the agent finishes
|
||||
/// processing a user submission). The value must be the full command
|
||||
@@ -2809,8 +2800,6 @@ impl Config {
|
||||
}
|
||||
});
|
||||
|
||||
let commit_attribution = cfg.commit_attribution;
|
||||
|
||||
// Load base instructions override from a file if specified. If the
|
||||
// path is relative, resolve it against the effective cwd so the
|
||||
// behaviour matches other path-like config values.
|
||||
@@ -3052,7 +3041,6 @@ impl Config {
|
||||
personality,
|
||||
developer_instructions,
|
||||
compact_prompt,
|
||||
commit_attribution,
|
||||
include_permissions_instructions,
|
||||
include_apps_instructions,
|
||||
include_collaboration_mode_instructions,
|
||||
|
||||
@@ -6493,10 +6493,10 @@ async fn make_multi_agent_v2_usage_hint_test_session(
|
||||
(session, turn_context)
|
||||
}
|
||||
|
||||
struct GitAttributionTestContributor;
|
||||
struct GitAttributionTestState;
|
||||
struct PromptExtensionTestContributor;
|
||||
struct PromptExtensionTestState;
|
||||
|
||||
impl codex_extension_api::ContextContributor for GitAttributionTestContributor {
|
||||
impl codex_extension_api::ContextContributor for PromptExtensionTestContributor {
|
||||
fn contribute<'a>(
|
||||
&'a self,
|
||||
_session_store: &'a codex_extension_api::ExtensionData,
|
||||
@@ -6506,11 +6506,11 @@ impl codex_extension_api::ContextContributor for GitAttributionTestContributor {
|
||||
> {
|
||||
Box::pin(async move {
|
||||
thread_store
|
||||
.get::<GitAttributionTestState>()
|
||||
.get::<PromptExtensionTestState>()
|
||||
.is_some()
|
||||
.then(|| {
|
||||
codex_extension_api::PromptFragment::developer_policy(
|
||||
"git attribution extension enabled",
|
||||
"prompt extension enabled",
|
||||
)
|
||||
})
|
||||
.into_iter()
|
||||
@@ -6519,21 +6519,21 @@ impl codex_extension_api::ContextContributor for GitAttributionTestContributor {
|
||||
}
|
||||
}
|
||||
|
||||
fn git_attribution_test_registry()
|
||||
fn prompt_extension_test_registry()
|
||||
-> Arc<codex_extension_api::ExtensionRegistry<crate::config::Config>> {
|
||||
let mut builder = codex_extension_api::ExtensionRegistryBuilder::new();
|
||||
builder.prompt_contributor(Arc::new(GitAttributionTestContributor));
|
||||
builder.prompt_contributor(Arc::new(PromptExtensionTestContributor));
|
||||
Arc::new(builder.build())
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn build_initial_context_includes_git_attribution_from_extensions() {
|
||||
async fn build_initial_context_includes_prompt_fragments_from_extensions() {
|
||||
let (mut session, turn_context) = make_session_and_context().await;
|
||||
session.services.extensions = git_attribution_test_registry();
|
||||
session.services.extensions = prompt_extension_test_registry();
|
||||
session
|
||||
.services
|
||||
.thread_extension_data
|
||||
.insert(GitAttributionTestState);
|
||||
.insert(PromptExtensionTestState);
|
||||
|
||||
let initial_context = session.build_initial_context(&turn_context).await;
|
||||
let developer_messages = developer_message_texts(&initial_context);
|
||||
@@ -6542,15 +6542,15 @@ async fn build_initial_context_includes_git_attribution_from_extensions() {
|
||||
developer_messages
|
||||
.iter()
|
||||
.flatten()
|
||||
.any(|text| *text == "git attribution extension enabled"),
|
||||
"expected git attribution developer text, got {developer_messages:?}"
|
||||
.any(|text| *text == "prompt extension enabled"),
|
||||
"expected prompt extension developer text, got {developer_messages:?}"
|
||||
);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn build_initial_context_omits_git_attribution_when_feature_is_disabled() {
|
||||
async fn build_initial_context_omits_prompt_fragments_without_extension_state() {
|
||||
let (mut session, turn_context) = make_session_and_context().await;
|
||||
session.services.extensions = git_attribution_test_registry();
|
||||
session.services.extensions = prompt_extension_test_registry();
|
||||
|
||||
let initial_context = session.build_initial_context(&turn_context).await;
|
||||
let developer_messages = developer_message_texts(&initial_context);
|
||||
@@ -6559,8 +6559,8 @@ async fn build_initial_context_omits_git_attribution_when_feature_is_disabled()
|
||||
!developer_messages
|
||||
.iter()
|
||||
.flatten()
|
||||
.any(|text| *text == "git attribution extension enabled"),
|
||||
"did not expect git attribution developer text, got {developer_messages:?}"
|
||||
.any(|text| *text == "prompt extension enabled"),
|
||||
"did not expect prompt extension developer text, got {developer_messages:?}"
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
load("//:defs.bzl", "codex_rust_crate")
|
||||
|
||||
codex_rust_crate(
|
||||
name = "git-attribution",
|
||||
crate_name = "codex_git_attribution",
|
||||
)
|
||||
@@ -1,21 +0,0 @@
|
||||
[package]
|
||||
edition.workspace = true
|
||||
license.workspace = true
|
||||
name = "codex-git-attribution"
|
||||
version.workspace = true
|
||||
|
||||
[lib]
|
||||
name = "codex_git_attribution"
|
||||
path = "src/lib.rs"
|
||||
doctest = false
|
||||
|
||||
[lints]
|
||||
workspace = true
|
||||
|
||||
[dependencies]
|
||||
codex-core = { workspace = true }
|
||||
codex-extension-api = { workspace = true }
|
||||
codex-features = { workspace = true }
|
||||
|
||||
[dev-dependencies]
|
||||
pretty_assertions = { workspace = true }
|
||||
@@ -1,134 +0,0 @@
|
||||
use std::sync::Arc;
|
||||
|
||||
use codex_core::config::Config;
|
||||
use codex_extension_api::ContextContributor;
|
||||
use codex_extension_api::ExtensionData;
|
||||
use codex_extension_api::ExtensionRegistryBuilder;
|
||||
use codex_extension_api::PromptFragment;
|
||||
use codex_extension_api::ThreadLifecycleContributor;
|
||||
use codex_extension_api::ThreadStartInput;
|
||||
use codex_features::Feature;
|
||||
|
||||
const DEFAULT_ATTRIBUTION_VALUE: &str = "Codex <noreply@openai.com>";
|
||||
|
||||
/// Contributes the configured git-attribution instruction.
|
||||
#[derive(Clone, Copy, Debug, Default)]
|
||||
pub struct GitAttributionExtension;
|
||||
|
||||
impl ContextContributor for GitAttributionExtension {
|
||||
fn contribute<'a>(
|
||||
&'a self,
|
||||
_session_store: &'a ExtensionData,
|
||||
thread_store: &'a ExtensionData,
|
||||
) -> std::pin::Pin<Box<dyn std::future::Future<Output = Vec<PromptFragment>> + Send + 'a>> {
|
||||
Box::pin(async move {
|
||||
let Some(config_store) = thread_store.get::<GitAttributionConfig>() else {
|
||||
return Vec::new();
|
||||
};
|
||||
if !config_store.enabled {
|
||||
return Vec::new();
|
||||
}
|
||||
build_instruction(config_store.prompt.as_deref())
|
||||
.map(PromptFragment::developer_policy)
|
||||
.into_iter()
|
||||
.collect()
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Default)]
|
||||
struct GitAttributionConfig {
|
||||
enabled: bool,
|
||||
prompt: Option<String>,
|
||||
}
|
||||
|
||||
impl ThreadLifecycleContributor<Config> for GitAttributionExtension {
|
||||
fn on_thread_start(&self, input: ThreadStartInput<'_, Config>) {
|
||||
input.thread_store.insert(GitAttributionConfig {
|
||||
enabled: input.config.features.enabled(Feature::CodexGitCommit),
|
||||
prompt: input.config.commit_attribution.clone(),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/// Installs the git-attribution contributors into the extension registry.
|
||||
pub fn install(registry: &mut ExtensionRegistryBuilder<Config>) {
|
||||
let extension = Arc::new(GitAttributionExtension);
|
||||
registry.thread_lifecycle_contributor(extension.clone());
|
||||
registry.prompt_contributor(extension);
|
||||
}
|
||||
|
||||
fn build_commit_message_trailer(config_attribution: Option<&str>) -> Option<String> {
|
||||
let value = resolve_attribution_value(config_attribution)?;
|
||||
Some(format!("Co-authored-by: {value}"))
|
||||
}
|
||||
|
||||
fn build_instruction(config_attribution: Option<&str>) -> Option<String> {
|
||||
let trailer = build_commit_message_trailer(config_attribution)?;
|
||||
Some(format!(
|
||||
"When you write or edit a git commit message, ensure the message ends with this trailer exactly once:\n{trailer}\n\nRules:\n- Keep existing trailers and append this trailer at the end if missing.\n- Do not duplicate this trailer if it already exists.\n- Keep one blank line between the commit body and trailer block."
|
||||
))
|
||||
}
|
||||
|
||||
fn resolve_attribution_value(config_attribution: Option<&str>) -> Option<String> {
|
||||
match config_attribution {
|
||||
Some(value) => {
|
||||
let trimmed = value.trim();
|
||||
if trimmed.is_empty() {
|
||||
None
|
||||
} else {
|
||||
Some(trimmed.to_string())
|
||||
}
|
||||
}
|
||||
None => Some(DEFAULT_ATTRIBUTION_VALUE.to_string()),
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use pretty_assertions::assert_eq;
|
||||
|
||||
use super::build_commit_message_trailer;
|
||||
use super::build_instruction;
|
||||
use super::resolve_attribution_value;
|
||||
|
||||
#[test]
|
||||
fn blank_attribution_disables_trailer_prompt() {
|
||||
assert_eq!(build_commit_message_trailer(Some("")), None);
|
||||
assert_eq!(build_instruction(Some(" ")), None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn default_attribution_uses_codex_trailer() {
|
||||
assert_eq!(
|
||||
build_commit_message_trailer(/*config_attribution*/ None).as_deref(),
|
||||
Some("Co-authored-by: Codex <noreply@openai.com>")
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn resolve_value_handles_default_custom_and_blank() {
|
||||
assert_eq!(
|
||||
resolve_attribution_value(/*config_attribution*/ None),
|
||||
Some("Codex <noreply@openai.com>".to_string())
|
||||
);
|
||||
assert_eq!(
|
||||
resolve_attribution_value(Some("MyAgent <me@example.com>")),
|
||||
Some("MyAgent <me@example.com>".to_string())
|
||||
);
|
||||
assert_eq!(
|
||||
resolve_attribution_value(Some("MyAgent")),
|
||||
Some("MyAgent".to_string())
|
||||
);
|
||||
assert_eq!(resolve_attribution_value(Some(" ")), None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn instruction_mentions_trailer_and_omits_generated_with() {
|
||||
let instruction =
|
||||
build_instruction(Some("AgentX <agent@example.com>")).expect("instruction expected");
|
||||
assert!(instruction.contains("Co-authored-by: AgentX <agent@example.com>"));
|
||||
assert!(instruction.contains("exactly once"));
|
||||
assert!(!instruction.contains("Generated-with"));
|
||||
}
|
||||
}
|
||||
@@ -130,7 +130,7 @@ pub enum Feature {
|
||||
RemoteModels,
|
||||
/// Experimental shell snapshotting.
|
||||
ShellSnapshot,
|
||||
/// Enable git commit attribution guidance via model instructions.
|
||||
/// Removed legacy git commit attribution guidance flag.
|
||||
CodexGitCommit,
|
||||
/// Enable runtime metrics snapshots via a manual reader.
|
||||
RuntimeMetrics,
|
||||
@@ -784,11 +784,10 @@ pub const FEATURES: &[FeatureSpec] = &[
|
||||
stage: Stage::Removed,
|
||||
default_enabled: false,
|
||||
},
|
||||
// Experimental program. Rendered in the `/experimental` menu for users.
|
||||
FeatureSpec {
|
||||
id: Feature::CodexGitCommit,
|
||||
key: "codex_git_commit",
|
||||
stage: Stage::UnderDevelopment,
|
||||
stage: Stage::Removed,
|
||||
default_enabled: false,
|
||||
},
|
||||
FeatureSpec {
|
||||
|
||||
@@ -196,7 +196,6 @@ fn new_config(model: Option<String>, arg0_paths: Arg0DispatchPaths) -> anyhow::R
|
||||
include_skill_instructions: false,
|
||||
include_environment_context: false,
|
||||
compact_prompt: None,
|
||||
commit_attribution: None,
|
||||
notify: None,
|
||||
tui_notifications: TuiNotificationSettings::default(),
|
||||
animations: true,
|
||||
|
||||
Reference in New Issue
Block a user