Skip to content

Commit 53db620

Browse files
author
MCP
committed
feat: separate filtering caps for user, agent, and reasoning blocks
1 parent dfd2b9e commit 53db620

1 file changed

Lines changed: 98 additions & 42 deletions

File tree

codex-md.py

Lines changed: 98 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -636,7 +636,7 @@ def count_lines_by_section(self) -> Dict[str, int]:
636636

637637
# --- markdown rendering with filter ---
638638
def to_markdown(self, section_filter: Optional[Dict[str, bool]] = None,
639-
clean_content: bool = False, output_cap: int = 0, msg_cap: int = 0) -> str:
639+
clean_content: bool = False, output_cap: int = 0, user_cap: int = 0, agent_cap: int = 0, reasoning_cap: int = 0) -> str:
640640
if section_filter is None:
641641
section_filter = {s[0]: True for s in SECTION_DEFS}
642642

@@ -651,13 +651,19 @@ def _cap_text(text: str) -> str:
651651
return f'... ({len(lines) - output_cap} lines trimmed) ...\n' + '\n'.join(kept)
652652

653653
keep_indices = set(range(len(self.data)))
654-
if msg_cap > 0:
655-
chat_msg_count = 0
656-
for i in range(len(self.data) - 1, -1, -1):
657-
if self.data[i]['type'] in {'user_message', 'agent_message', 'agent_reasoning', 'reasoning'}:
658-
if chat_msg_count >= msg_cap:
659-
keep_indices.remove(i)
660-
chat_msg_count += 1
654+
counts = {'user_message': 0, 'agent_message': 0, 'reasoning_group': 0}
655+
656+
for i in range(len(self.data) - 1, -1, -1):
657+
itype = self.data[i]['type']
658+
if itype == 'user_message' and user_cap > 0:
659+
if counts['user_message'] >= user_cap: keep_indices.remove(i)
660+
counts['user_message'] += 1
661+
elif itype == 'agent_message' and agent_cap > 0:
662+
if counts['agent_message'] >= agent_cap: keep_indices.remove(i)
663+
counts['agent_message'] += 1
664+
elif itype in ('agent_reasoning', 'reasoning') and reasoning_cap > 0:
665+
if counts['reasoning_group'] >= reasoning_cap: keep_indices.remove(i)
666+
counts['reasoning_group'] += 1
661667

662668
md: List[str] = []
663669
md.append(f"# {self.title}\n")
@@ -797,15 +803,15 @@ def read_key() -> str:
797803
CAP_STEPS = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 15, 20, 30, 50, 100, 200, 500]
798804
MSG_CAP_STEPS = [0, 5, 10, 20, 50] + list(range(70, 511, 20))
799805

800-
def interactive_filter(parsers: List[SessionParser]) -> Tuple[Dict[str, bool], bool, int, int]:
806+
def interactive_filter(parsers: List[SessionParser]) -> Tuple[Dict[str, bool], bool, int, int, int, int]:
801807
"""
802808
Full-screen interactive filter.
803-
Returns (section_filter, clean_content, output_cap, msg_cap).
809+
Returns (section_filter, clean_content, output_cap, user_cap, agent_cap, reasoning_cap).
804810
"""
805811
_line_cache = {}
806812

807-
def get_lines_for_state(cap_out: int, cap_msg: int, cc: bool) -> Dict[str, int]:
808-
cache_key = (cap_out, cap_msg, cc)
813+
def get_lines_for_state(cap_out: int, cap_user: int, cap_agent: int, cap_reason: int, cc: bool) -> Dict[str, int]:
814+
cache_key = (cap_out, cap_user, cap_agent, cap_reason, cc)
809815
if cache_key in _line_cache:
810816
return _line_cache[cache_key]
811817

@@ -815,13 +821,19 @@ def get_lines_for_state(cap_out: int, cap_msg: int, cc: bool) -> Dict[str, int]:
815821

816822
for parser in parsers:
817823
keep_indices = set(range(len(parser.data)))
818-
if cap_msg > 0:
819-
chat_msg_count = 0
820-
for i in range(len(parser.data) - 1, -1, -1):
821-
if parser.data[i]['type'] in {'user_message', 'agent_message', 'agent_reasoning', 'reasoning'}:
822-
if chat_msg_count >= cap_msg:
823-
keep_indices.remove(i)
824-
chat_msg_count += 1
824+
chat_counts = {'u': 0, 'a': 0, 'r': 0}
825+
826+
for i in range(len(parser.data) - 1, -1, -1):
827+
itype = parser.data[i]['type']
828+
if itype == 'user_message' and cap_user > 0:
829+
if chat_counts['u'] >= cap_user: keep_indices.remove(i)
830+
chat_counts['u'] += 1
831+
elif itype == 'agent_message' and cap_agent > 0:
832+
if chat_counts['a'] >= cap_agent: keep_indices.remove(i)
833+
chat_counts['a'] += 1
834+
elif itype in ('agent_reasoning', 'reasoning') and cap_reason > 0:
835+
if chat_counts['r'] >= cap_reason: keep_indices.remove(i)
836+
chat_counts['r'] += 1
825837

826838
for i, item in enumerate(parser.data):
827839
if i not in keep_indices: continue
@@ -867,19 +879,29 @@ def get_lines_for_state(cap_out: int, cap_msg: int, cc: bool) -> Dict[str, int]:
867879

868880
fstate: Dict[str, bool] = {s[0]: s[3] for s in SECTION_DEFS}
869881
clean_content = False
882+
870883
output_cap = 8
871884
cap_idx = CAP_STEPS.index(8)
872-
msg_cap = 0
873-
msg_idx = MSG_CAP_STEPS.index(0)
885+
886+
user_cap = 0
887+
u_idx = 0
888+
889+
agent_cap = 0
890+
a_idx = 0
891+
892+
reason_cap = 0
893+
r_idx = 0
874894

875895
cursor = 0
876896
ROW_CLEAN = len(SECTION_DEFS)
877897
ROW_CAP = len(SECTION_DEFS) + 1
878-
ROW_MSG = len(SECTION_DEFS) + 2
879-
num_items = len(SECTION_DEFS) + 3
898+
ROW_USER = len(SECTION_DEFS) + 2
899+
ROW_AGENT = len(SECTION_DEFS) + 3
900+
ROW_REASON= len(SECTION_DEFS) + 4
901+
num_items = len(SECTION_DEFS) + 5
880902

881903
while True:
882-
agg_lines = get_lines_for_state(output_cap, msg_cap, clean_content)
904+
agg_lines = get_lines_for_state(output_cap, user_cap, agent_cap, reason_cap, clean_content)
883905
total_lines = sum(agg_lines.get(s[0], 0) for s in SECTION_DEFS)
884906
selected_lines = sum(agg_lines.get(s[0], 0) for s in SECTION_DEFS if fstate.get(s[0], False))
885907
pct = (selected_lines / total_lines * 100) if total_lines > 0 else 0
@@ -932,13 +954,29 @@ def get_lines_for_state(cap_out: int, cap_msg: int, cc: bool) -> Dict[str, int]:
932954
hint = f' {Style.DIM}◀▶{Style.RESET}' if cap_cur else ''
933955
print(f' {cap_arrow} {cap_st}💻 Terminal Output Cap{Style.RESET} {Style.DIM}(max lines/block){Style.RESET} {cap_label}{hint}')
934956

935-
# Msg Cap
936-
msg_cur = (cursor == ROW_MSG)
937-
msg_arrow = f'{Style.BOLD}{Style.YELLOW}{Style.RESET}' if msg_cur else ' '
938-
msg_st = f'{Style.BOLD}' if msg_cur else Style.DIM
939-
msg_label = f'{Style.DIM}ALL{Style.RESET}' if msg_cap == 0 else f'{Style.YELLOW}Last {msg_cap}{Style.RESET}'
940-
msg_hint = f' {Style.DIM}◀▶{Style.RESET}' if msg_cur else ''
941-
print(f' {msg_arrow} {msg_st}🕒 Chat Message Cap{Style.RESET} {Style.DIM}(blocks for 👤🤖🧠){Style.RESET} {msg_label}{msg_hint}')
957+
# User Cap
958+
u_cur = (cursor == ROW_USER)
959+
u_arrow = f'{Style.BOLD}{Style.YELLOW}{Style.RESET}' if u_cur else ' '
960+
u_st = f'{Style.BOLD}' if u_cur else Style.DIM
961+
u_label = f'{Style.DIM}ALL{Style.RESET}' if user_cap == 0 else f'{Style.YELLOW}Last {user_cap}{Style.RESET}'
962+
u_hint = f' {Style.DIM}◀▶{Style.RESET}' if u_cur else ''
963+
print(f' {u_arrow} {u_st}👤 User Message Cap{Style.RESET} {Style.DIM}(blocks){Style.RESET} {u_label}{u_hint}')
964+
965+
# Agent Cap
966+
a_cur = (cursor == ROW_AGENT)
967+
a_arrow = f'{Style.BOLD}{Style.YELLOW}{Style.RESET}' if a_cur else ' '
968+
a_st = f'{Style.BOLD}' if a_cur else Style.DIM
969+
a_label = f'{Style.DIM}ALL{Style.RESET}' if agent_cap == 0 else f'{Style.YELLOW}Last {agent_cap}{Style.RESET}'
970+
a_hint = f' {Style.DIM}◀▶{Style.RESET}' if a_cur else ''
971+
print(f' {a_arrow} {a_st}🤖 Agent Message Cap{Style.RESET} {Style.DIM}(blocks){Style.RESET} {a_label}{a_hint}')
972+
973+
# Reason Cap
974+
r_cur = (cursor == ROW_REASON)
975+
r_arrow = f'{Style.BOLD}{Style.YELLOW}{Style.RESET}' if r_cur else ' '
976+
r_st = f'{Style.BOLD}' if r_cur else Style.DIM
977+
r_label = f'{Style.DIM}ALL{Style.RESET}' if reason_cap == 0 else f'{Style.YELLOW}Last {reason_cap}{Style.RESET}'
978+
r_hint = f' {Style.DIM}◀▶{Style.RESET}' if r_cur else ''
979+
print(f' {r_arrow} {r_st}🧠 Agent Reasoning Cap{Style.RESET} {Style.DIM}(blocks){Style.RESET} {r_label}{r_hint}')
942980

943981
print(f'\n {Style.DIM}{"━" * 62}{Style.RESET}')
944982
bar_w = 30
@@ -962,16 +1000,28 @@ def get_lines_for_state(cap_out: int, cap_msg: int, cc: bool) -> Dict[str, int]:
9621000
if cursor == ROW_CAP:
9631001
cap_idx = max(0, cap_idx - 1)
9641002
output_cap = CAP_STEPS[cap_idx]
965-
elif cursor == ROW_MSG:
966-
msg_idx = max(0, msg_idx - 1)
967-
msg_cap = MSG_CAP_STEPS[msg_idx]
1003+
elif cursor == ROW_USER:
1004+
u_idx = max(0, u_idx - 1)
1005+
user_cap = MSG_CAP_STEPS[u_idx]
1006+
elif cursor == ROW_AGENT:
1007+
a_idx = max(0, a_idx - 1)
1008+
agent_cap = MSG_CAP_STEPS[a_idx]
1009+
elif cursor == ROW_REASON:
1010+
r_idx = max(0, r_idx - 1)
1011+
reason_cap = MSG_CAP_STEPS[r_idx]
9681012
elif key == 'RIGHT':
9691013
if cursor == ROW_CAP:
9701014
cap_idx = min(len(CAP_STEPS) - 1, cap_idx + 1)
9711015
output_cap = CAP_STEPS[cap_idx]
972-
elif cursor == ROW_MSG:
973-
msg_idx = min(len(MSG_CAP_STEPS) - 1, msg_idx + 1)
974-
msg_cap = MSG_CAP_STEPS[msg_idx]
1016+
elif cursor == ROW_USER:
1017+
u_idx = min(len(MSG_CAP_STEPS) - 1, u_idx + 1)
1018+
user_cap = MSG_CAP_STEPS[u_idx]
1019+
elif cursor == ROW_AGENT:
1020+
a_idx = min(len(MSG_CAP_STEPS) - 1, a_idx + 1)
1021+
agent_cap = MSG_CAP_STEPS[a_idx]
1022+
elif cursor == ROW_REASON:
1023+
r_idx = min(len(MSG_CAP_STEPS) - 1, r_idx + 1)
1024+
reason_cap = MSG_CAP_STEPS[r_idx]
9751025
elif key == 'A':
9761026
for s in SECTION_DEFS: fstate[s[0]] = True
9771027
elif key == 'N':
@@ -983,8 +1033,12 @@ def get_lines_for_state(cap_out: int, cap_msg: int, cc: bool) -> Dict[str, int]:
9831033
clean_content = False
9841034
output_cap = 8
9851035
cap_idx = CAP_STEPS.index(8)
986-
msg_cap = 0
987-
msg_idx = MSG_CAP_STEPS.index(0)
1036+
user_cap = 0
1037+
u_idx = 0
1038+
agent_cap = 0
1039+
a_idx = 0
1040+
reason_cap = 0
1041+
r_idx = 0
9881042
elif key == 'Q' or key == 'ESC':
9891043
break
9901044
elif key.isdigit():
@@ -997,7 +1051,7 @@ def get_lines_for_state(cap_out: int, cap_msg: int, cc: bool) -> Dict[str, int]:
9971051
for s in SECTION_DEFS: fstate[s[0]] = s[0] in pkeys
9981052
clean_content = pclean
9991053

1000-
return fstate, clean_content, output_cap, msg_cap
1054+
return fstate, clean_content, output_cap, user_cap, agent_cap, reason_cap
10011055

10021056
# ──────────────────────────────────────────────────────────────
10031057
# Session List & Main Loop
@@ -1127,7 +1181,7 @@ def process_conversion(indices_str: str, files: List[Path]):
11271181
return
11281182

11291183
# Interactive filter
1130-
section_filter, clean_content, output_cap, msg_cap = interactive_filter(parsers)
1184+
section_filter, clean_content, output_cap, user_cap, agent_cap, reason_cap = interactive_filter(parsers)
11311185

11321186
# Check anything is selected
11331187
if not any(section_filter.values()):
@@ -1164,7 +1218,9 @@ def process_conversion(indices_str: str, files: List[Path]):
11641218
section_filter=section_filter,
11651219
clean_content=clean_content,
11661220
output_cap=output_cap,
1167-
msg_cap=msg_cap,
1221+
user_cap=user_cap,
1222+
agent_cap=agent_cap,
1223+
reasoning_cap=reason_cap,
11681224
)
11691225

11701226
date_prefix = datetime.fromtimestamp(

0 commit comments

Comments
 (0)