Skip to content

Commit 803e698

Browse files
committed
fix: strip codex user file mention wrappers
Codex-Thread-ID: https://jieli.app/threads/T-019ea91c-c153-7dc1-8d50-4fdc2ee9b7e0
1 parent fe9eee0 commit 803e698

3 files changed

Lines changed: 57 additions & 2 deletions

File tree

plugins/codex/.codex-plugin/plugin.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "codex",
3-
"version": "0.1.0+codex.20260609102652",
3+
"version": "0.1.0+codex.20260610092530",
44
"description": "Sync Codex sessions to Jieli threads and attach Jieli thread trailers to Codex-created commits.",
55
"author": {
66
"name": "Jieli"

plugins/codex/scripts/sync.py

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,10 @@
3737
LOCAL_MARKDOWN_LINK_RE = re.compile(r"\[([^\]]+)\]\((/[^)\n]+)\)")
3838
HANDOFF_SUMMARY_RE = re.compile(r"^(?:#{1,6}\s*)?\*{0,2}Handoff Summary\*{0,2}\s*(?:\n|$)", re.IGNORECASE)
3939
CODEX_GIT_DIRECTIVE_RE = re.compile(r"(?m)^[ \t]*::git-[A-Za-z0-9_-]+\{[^\n]*\}[ \t]*\n?")
40+
CODEX_USER_FILE_MENTIONS_RE = re.compile(
41+
r"\A\s*#{0,6}\s*Files mentioned by the user:\s*\n.*?^\s*#{0,6}\s*My request for Codex:\s*\n?",
42+
re.DOTALL | re.MULTILINE,
43+
)
4044
SUPPORTED_IMAGE_MEDIA_TYPES = {"image/png", "image/jpeg", "image/gif", "image/webp"}
4145
COMPACTION_PLACEHOLDER = (
4246
"[Context compacted - earlier conversation summarized to continue past the context window]"
@@ -355,6 +359,8 @@ def normalize_content_blocks(
355359
data_image_uploader: DataImageUploader | None = None,
356360
) -> Any | None:
357361
if isinstance(raw_content, str):
362+
if role == "user":
363+
raw_content = clean_codex_user_text(raw_content)
358364
return normalize_text_with_images(raw_content, image_uploader)
359365
if not isinstance(raw_content, list):
360366
if raw_content is None:
@@ -368,6 +374,8 @@ def normalize_content_blocks(
368374
block_type = str(block.get("type") or "")
369375
text = block.get("text")
370376
if block_type in {"input_text", "output_text", "text"} and isinstance(text, str):
377+
if role == "user":
378+
text = clean_codex_user_text(text)
371379
append_blocks(blocks, normalize_text_blocks(text, image_uploader))
372380
continue
373381
if block_type == "input_image":
@@ -397,7 +405,7 @@ def normalize_content_blocks(
397405

398406

399407
def normalize_user_event_content(message: str, local_images: Any, image_uploader: ImageUploader | None = None) -> Any | None:
400-
blocks = normalize_text_blocks(message, image_uploader)
408+
blocks = normalize_text_blocks(clean_codex_user_text(message), image_uploader)
401409
if isinstance(local_images, list):
402410
for image_path in local_images:
403411
if not isinstance(image_path, str):
@@ -575,6 +583,10 @@ def clean_codex_text(text: str) -> str:
575583
return re.sub(r"\n{3,}", "\n\n", cleaned)
576584

577585

586+
def clean_codex_user_text(text: str) -> str:
587+
return clean_codex_text(CODEX_USER_FILE_MENTIONS_RE.sub("", text, count=1))
588+
589+
578590
def file_url_local_markdown_link_targets(text: str) -> str:
579591
def replace(match: re.Match[str]) -> str:
580592
label = match.group(1).strip()

plugins/codex/tests/test_plugin_scripts.py

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -586,6 +586,49 @@ def test_build_payload_skips_loaded_skill_content_block(self):
586586
self.assertNotIn("Spec-Driven Planning", raw_payload)
587587
self.assertNotIn("SKILL.md", raw_payload)
588588

589+
def test_build_payload_strips_codex_user_file_mentions_prefix(self):
590+
from sync import build_payload_from_hook
591+
592+
user_text = """# Files mentioned by the user:
593+
594+
## codex-clipboard-ba43ae37-fd1b-46d2-98dc-a3f3e3c14b3e.png: /var/folders/2s/q99hddf140l937t46th4b91w0000gn/T/codex-clipboard-ba43ae37-fd1b-46d2-98dc-a3f3e3c14b3e.png
595+
596+
## My request for Codex:
597+
threads list, hidden branch name, just show repo"""
598+
with tempfile.TemporaryDirectory() as tmpdir:
599+
transcript = Path(tmpdir) / "session.jsonl"
600+
transcript.write_text(
601+
"\n".join(
602+
[
603+
json.dumps({"type": "session_meta", "payload": {"id": "codex-file-prefix", "cwd": "/Users/alice/work/jieli"}}),
604+
json.dumps(
605+
{
606+
"type": "response_item",
607+
"payload": {
608+
"type": "message",
609+
"role": "user",
610+
"content": [{"type": "input_text", "text": user_text}],
611+
},
612+
}
613+
),
614+
]
615+
)
616+
+ "\n",
617+
encoding="utf-8",
618+
)
619+
620+
payload = build_payload_from_hook(
621+
{"session_id": "codex-file-prefix", "transcript_path": str(transcript)},
622+
base_url="https://jieli.example.test",
623+
)
624+
625+
raw_payload = json.dumps(payload, ensure_ascii=False)
626+
self.assertEqual(payload["thread"]["messages"][0]["content"], "threads list, hidden branch name, just show repo")
627+
self.assertEqual(payload["thread"]["title"], "threads list, hidden branch name, just show repo")
628+
self.assertNotIn("Files mentioned by the user", raw_payload)
629+
self.assertNotIn("codex-clipboard-ba43ae37", raw_payload)
630+
self.assertNotIn("/var/folders/", raw_payload)
631+
589632
def test_build_payload_rewrites_local_markdown_link_targets_as_file_urls(self):
590633
from sync import build_payload_from_hook
591634

0 commit comments

Comments
 (0)