|
18 | 18 | from pathlib import Path |
19 | 19 | from typing import Any |
20 | 20 |
|
| 21 | +from codex_context import ( |
| 22 | + conversation_record_count, |
| 23 | + is_context_control_command_text, |
| 24 | + is_contextual_user_text, |
| 25 | +) |
| 26 | + |
21 | 27 |
|
22 | | -HOST = os.environ.get("HASH_CONTEXT_PROXY_HOST", "127.0.0.1") |
| 28 | +HOST = os.environ.get("HASH_CONTEXT_PROXY_HOST", os.environ.get("HASH_CONTEXT_HOST", "localhost")) |
23 | 29 | PORT = int(os.environ.get("HASH_CONTEXT_PROXY_PORT", "8787")) |
24 | 30 | OPENAI_UPSTREAM_BASE_URL = os.environ.get( |
25 | 31 | "HASH_CONTEXT_OPENAI_UPSTREAM_BASE_URL", |
|
36 | 42 | CODEX_PROXY_BASE_URL = f"http://{HOST}:{PORT}/v1" |
37 | 43 | INTERNAL_CONTEXT_HEADER = "x-hash-context-internal" |
38 | 44 | INTERNAL_CONTEXT_VALUE = "context-workbench" |
39 | | -CONTEXT_CONTROL_COMMANDS = {"ctx", "/ctx", "context", "/context"} |
40 | 45 | CONTEXT_CONTROL_NOTICE_TEXT = "Hash Context: opened workbench." |
41 | 46 | CONTROL_PORT = int(os.environ.get("HASH_CONTEXT_CONTROL_PORT", "8790")) |
42 | 47 | LOCAL_COMPACT_PROMPT_PREFIX = "You are performing a CONTEXT CHECKPOINT COMPACTION." |
@@ -507,10 +512,6 @@ def flush_assistant() -> None: |
507 | 512 | return records |
508 | 513 |
|
509 | 514 |
|
510 | | -def is_context_control_command_text(text: str) -> bool: |
511 | | - return str(text or "").strip().lower() in CONTEXT_CONTROL_COMMANDS |
512 | | - |
513 | | - |
514 | 515 | def context_control_command_from_input(input_items: Any) -> str: |
515 | 516 | transcript = input_items_to_transcript(input_items) |
516 | 517 | for record in reversed(transcript): |
@@ -938,7 +939,7 @@ def open_context_workbench(session_id: str) -> tuple[bool, str]: |
938 | 939 | path = "/show" |
939 | 940 | if session_id: |
940 | 941 | path = f"{path}?session_id={urllib.parse.quote(session_id, safe='')}" |
941 | | - conn = http.client.HTTPConnection("127.0.0.1", CONTROL_PORT, timeout=2) |
| 942 | + conn = http.client.HTTPConnection(os.environ.get("HASH_CONTEXT_HOST", "localhost"), CONTROL_PORT, timeout=2) |
942 | 943 | try: |
943 | 944 | conn.request("POST", path, body=b"", headers={"Content-Length": "0"}) |
944 | 945 | response = conn.getresponse() |
@@ -1115,19 +1116,6 @@ def is_local_compact_summary_text(text: str) -> bool: |
1115 | 1116 | return str(text or "").startswith(f"{LOCAL_COMPACT_SUMMARY_PREFIX}\n\n") |
1116 | 1117 |
|
1117 | 1118 |
|
1118 | | -def is_contextual_user_text(text: str) -> bool: |
1119 | | - trimmed = str(text or "").lstrip() |
1120 | | - lowered = trimmed.lower() |
1121 | | - return ( |
1122 | | - trimmed.startswith("# AGENTS.md instructions for ") |
1123 | | - or lowered.startswith("<environment_context>") |
1124 | | - or lowered.startswith("<skills>") |
1125 | | - or lowered.startswith("<user_shell_command>") |
1126 | | - or lowered.startswith("<turn_aborted>") |
1127 | | - or lowered.startswith("<subagent_notification>") |
1128 | | - ) |
1129 | | - |
1130 | | - |
1131 | 1119 | def is_initial_context_prefix_record(record: dict[str, Any]) -> bool: |
1132 | 1120 | role = str(record.get("role") or "").strip() |
1133 | 1121 | if role in {"system", "developer"}: |
@@ -1161,6 +1149,13 @@ def with_fresh_initial_context_prefix( |
1161 | 1149 | return clean_transcript([*prefix, *body]) |
1162 | 1150 |
|
1163 | 1151 |
|
| 1152 | +def should_replace_transcript_from_control_intercept( |
| 1153 | + existing_transcript: list[dict[str, Any]], |
| 1154 | + candidate_transcript: list[dict[str, Any]], |
| 1155 | +) -> bool: |
| 1156 | + return conversation_record_count(candidate_transcript) >= conversation_record_count(existing_transcript) |
| 1157 | + |
| 1158 | + |
1164 | 1159 | def local_compact_source_from_transcript(transcript: list[dict[str, Any]]) -> list[dict[str, Any]] | None: |
1165 | 1160 | records = clean_transcript(transcript) |
1166 | 1161 | if not records: |
@@ -1410,8 +1405,12 @@ def record_control_intercept(self, session_id: str, body: dict[str, Any], header |
1410 | 1405 | if session is None: |
1411 | 1406 | session = ProxySession(id=session_id, title=f"Codex {session_id[:8]}") |
1412 | 1407 | self.sessions[session_id] = session |
1413 | | - source_transcript = strip_context_edit_notice_records(input_items_to_transcript(body.get("input"))) |
1414 | | - session.transcript = clean_transcript(source_transcript) |
| 1408 | + source_transcript = clean_transcript( |
| 1409 | + strip_context_edit_notice_records(input_items_to_transcript(body.get("input"))) |
| 1410 | + ) |
| 1411 | + existing_transcript = clean_transcript(session.transcript) |
| 1412 | + if should_replace_transcript_from_control_intercept(existing_transcript, source_transcript): |
| 1413 | + session.transcript = source_transcript |
1415 | 1414 | session.pending_transcript = None |
1416 | 1415 | session.local_compact_source_transcript = None |
1417 | 1416 | session.status = "override" if session.edited_transcript is not None else "mirror" |
|
0 commit comments