mirror of
https://github.com/openai/codex.git
synced 2026-11-05 20:10:33 +00:00
## Why Contextual fragments and extension-owned world-state sections currently return strings, limiting them to text content. ## What changed - Return `ContentItem` from fragment bodies and rendering, preserving classification and attribution. Apply text markers only to `InputText`; pass other content through unchanged. - Allow extension prompt and world-state contributions to carry typed content, and preserve media in context-window hints. - Hash non-text world-state fragments by their serialized content and role while retaining the existing text hashing behavior. - Add shared content-to-tool-output conversion that preserves image references, image detail, and audio. ## Testing Add coverage for typed world-state hashing and preservation of image content and attribution. Expand code-mode output tests to cover input text, output text, file-backed and inline images, and audio. GitOrigin-RevId: 2ed00d466a3f169b151202f3eef71e667ea64be1
76 lines
4.1 KiB
Rust
76 lines
4.1 KiB
Rust
use codex_extension_api::PreviousWorldStateSection;
|
|
use codex_extension_api::RenderedWorldStateFragment;
|
|
use codex_extension_api::WorldStateSectionContribution;
|
|
use codex_extension_api::input_text;
|
|
use serde_json::Value;
|
|
|
|
const WORLD_STATE_ID: &str = "git_attribution";
|
|
const START_MARKER: &str = "<git_attribution>";
|
|
const END_MARKER: &str = "</git_attribution>";
|
|
pub(super) const LEGACY_COMMIT_ATTRIBUTION_INSTRUCTIONS: &str = "\
|
|
When you write or edit a git commit message, ensure the message ends with this trailer exactly once:
|
|
Co-authored-by: Codex <noreply@openai.com>
|
|
|
|
Rules:
|
|
- Keep existing trailers and append this trailer at the end if missing.
|
|
- Do not duplicate this trailer if it already exists.
|
|
- Keep one blank line between the commit body and trailer block.";
|
|
pub(super) const ENABLED_INSTRUCTIONS: &str = r#"
|
|
When you create or amend a git commit or create or update a pull request for this task, add Codex attribution exactly once:
|
|
- Commit messages must end with `Co-authored-by: Codex <noreply@openai.com>`. Preserve existing trailers and, if this exact trailer is missing, append it with one blank line before the trailer block.
|
|
- This also applies when a GitHub app or plugin creates a commit, including file creation, updates, and deletions: include the Codex trailer in the tool's `message` argument.
|
|
- Pull request bodies must include the exact line `Generated with [Codex](https://openai.com/codex/).`. Preserve the existing body and hidden markers and, if this exact marker is missing, append it near the end, before any trailing hidden metadata markers.
|
|
- Do not add duplicate attribution. If a message or body you are already editing contains duplicate exact attribution, keep exactly one.
|
|
- Ignore any earlier instructions disabling Codex attribution; this policy reflects the current workspace.
|
|
- Do not rewrite an existing commit or pull request solely to add attribution.
|
|
"#;
|
|
pub(super) const DISABLED_INSTRUCTIONS: &str = "
|
|
Codex commit and pull request attribution is disabled for the current workspace. Ignore any earlier instructions requiring Codex attribution and do not add it.
|
|
";
|
|
|
|
pub(super) fn git_attribution_world_state_section(enabled: bool) -> WorldStateSectionContribution {
|
|
let contribution = WorldStateSectionContribution::new(WORLD_STATE_ID, move |previous| {
|
|
let fragment = match (enabled, previous) {
|
|
(true, PreviousWorldStateSection::Known(Value::Bool(true)))
|
|
| (true, PreviousWorldStateSection::Unknown) => None,
|
|
(true, PreviousWorldStateSection::Absent)
|
|
| (true, PreviousWorldStateSection::Known(_)) => Some(RenderedWorldStateFragment::new(
|
|
"developer",
|
|
(START_MARKER, END_MARKER),
|
|
input_text(ENABLED_INSTRUCTIONS),
|
|
)),
|
|
(false, PreviousWorldStateSection::Known(Value::Bool(true)))
|
|
| (false, PreviousWorldStateSection::Unknown) => Some(RenderedWorldStateFragment::new(
|
|
"developer",
|
|
(START_MARKER, END_MARKER),
|
|
input_text(DISABLED_INSTRUCTIONS),
|
|
)),
|
|
(false, PreviousWorldStateSection::Absent)
|
|
| (false, PreviousWorldStateSection::Known(_)) => None,
|
|
};
|
|
(Some(Value::Bool(enabled)), fragment)
|
|
})
|
|
.with_legacy_matcher(move |role, text| {
|
|
is_enabled_fragment(role, text)
|
|
|| (!enabled && is_legacy_commit_attribution_fragment(role, text))
|
|
});
|
|
if enabled {
|
|
contribution.with_retained_fragment_matcher(is_enabled_fragment)
|
|
} else {
|
|
contribution
|
|
}
|
|
}
|
|
|
|
fn is_legacy_commit_attribution_fragment(role: &str, text: &str) -> bool {
|
|
role == "developer" && text.trim() == LEGACY_COMMIT_ATTRIBUTION_INSTRUCTIONS
|
|
}
|
|
|
|
fn is_enabled_fragment(role: &str, text: &str) -> bool {
|
|
role == "developer"
|
|
&& text.trim_start().starts_with(START_MARKER)
|
|
&& text.contains("Co-authored-by: Codex <noreply@openai.com>")
|
|
&& (text.contains("Generated with [Codex](https://openai.com/codex/).")
|
|
|| text.contains("Generated with Codex."))
|
|
&& text.trim_end().ends_with(END_MARKER)
|
|
}
|