Skip to content

Commit 2701492

Browse files
committed
refactor: underscore-prefix internal fold-state fields in SessionSummaryEntry
1 parent ea20121 commit 2701492

3 files changed

Lines changed: 26 additions & 22 deletions

File tree

src/claude_agent_sdk/_internal/session_summary.py

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -71,12 +71,12 @@ def _entry_text_blocks(entry: dict[str, Any]) -> list[str]:
7171
def _fold_first_prompt(summary: SessionSummaryEntry, entry: dict[str, Any]) -> None:
7272
"""Replicate ``_extract_first_prompt_from_head`` for a single parsed entry.
7373
74-
Mutates ``summary`` in place: sets ``first_prompt`` + ``first_prompt_locked``
75-
on a real match, or stashes a ``command_fallback`` for slash-command
76-
messages. Skips tool_result, isMeta, isCompactSummary, and auto-generated
77-
patterns.
74+
Mutates ``summary`` in place: sets ``first_prompt`` +
75+
``_first_prompt_locked`` on a real match, or stashes a
76+
``_command_fallback`` for slash-command messages. Skips tool_result,
77+
isMeta, isCompactSummary, and auto-generated patterns.
7878
"""
79-
if summary.get("first_prompt_locked"):
79+
if summary.get("_first_prompt_locked"):
8080
return
8181
if entry.get("type") != "user":
8282
return
@@ -97,15 +97,15 @@ def _fold_first_prompt(summary: SessionSummaryEntry, entry: dict[str, Any]) -> N
9797
continue
9898
cmd_match = _COMMAND_NAME_RE.search(result)
9999
if cmd_match:
100-
if not summary.get("command_fallback"):
101-
summary["command_fallback"] = cmd_match.group(1)
100+
if not summary.get("_command_fallback"):
101+
summary["_command_fallback"] = cmd_match.group(1)
102102
continue
103103
if _SKIP_FIRST_PROMPT_PATTERN.match(result):
104104
continue
105105
if len(result) > 200:
106106
result = result[:200].rstrip() + "\u2026"
107107
summary["first_prompt"] = result
108-
summary["first_prompt_locked"] = True
108+
summary["_first_prompt_locked"] = True
109109
return
110110

111111

@@ -181,8 +181,8 @@ def summary_entry_to_sdk_info(
181181

182182
first_prompt = (
183183
entry.get("first_prompt")
184-
if entry.get("first_prompt_locked")
185-
else entry.get("command_fallback")
184+
if entry.get("_first_prompt_locked")
185+
else entry.get("_command_fallback")
186186
) or None
187187
custom_title = entry.get("custom_title") or entry.get("ai_title") or None
188188
summary = (

src/claude_agent_sdk/types.py

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1166,6 +1166,10 @@ class SessionSummaryEntry(TypedDict, total=False):
11661166
:func:`fold_session_summary` and return the full set from
11671167
:meth:`SessionStore.list_session_summaries`. Every field is
11681168
append-incremental (set-once or last-wins) so adapters never re-read.
1169+
1170+
Fields prefixed ``_`` are opaque fold state — stores MUST persist them
1171+
verbatim across :func:`fold_session_summary` calls but SHOULD NOT
1172+
interpret them.
11691173
"""
11701174

11711175
session_id: Required[str]
@@ -1177,11 +1181,6 @@ class SessionSummaryEntry(TypedDict, total=False):
11771181
cwd: str
11781182
first_prompt: str
11791183
"""First meaningful user prompt, truncated to 200 chars."""
1180-
first_prompt_locked: bool
1181-
"""Internal: ``True`` once a non-command prompt has been found."""
1182-
command_fallback: str
1183-
"""Internal: first ``<command-name>`` seen, used when no real prompt
1184-
appears."""
11851184
custom_title: str
11861185
ai_title: str
11871186
last_prompt: str
@@ -1190,6 +1189,11 @@ class SessionSummaryEntry(TypedDict, total=False):
11901189
git_branch: str
11911190
tag: str
11921191
file_size: int
1192+
_first_prompt_locked: bool
1193+
"""Opaque fold state: ``True`` once a non-command prompt has been found."""
1194+
_command_fallback: str
1195+
"""Opaque fold state: first ``<command-name>`` seen, used when no real
1196+
prompt appears."""
11931197

11941198

11951199
class SessionListSubkeysKey(TypedDict):

tests/test_session_summary.py

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -181,7 +181,7 @@ def test_first_prompt_skips_meta_tool_result_and_compact(self) -> None:
181181
],
182182
)
183183
assert s["first_prompt"] == "real first"
184-
assert s["first_prompt_locked"] is True
184+
assert s["_first_prompt_locked"] is True
185185

186186
def test_first_prompt_command_fallback(self) -> None:
187187
s = fold_session_summary(
@@ -192,12 +192,12 @@ def test_first_prompt_command_fallback(self) -> None:
192192
_user("<command-name>/second</command-name>"),
193193
],
194194
)
195-
assert s.get("first_prompt_locked") is not True
196-
assert s["command_fallback"] == "/init"
195+
assert s.get("_first_prompt_locked") is not True
196+
assert s["_command_fallback"] == "/init"
197197
# A later real prompt locks it.
198198
s2 = fold_session_summary(s, KEY, [_user("now real")])
199199
assert s2["first_prompt"] == "now real"
200-
assert s2["first_prompt_locked"] is True
200+
assert s2["_first_prompt_locked"] is True
201201

202202
def test_first_prompt_skip_pattern(self) -> None:
203203
s = fold_session_summary(
@@ -246,8 +246,8 @@ def test_precedence_chain(self) -> None:
246246
"session_id": "s",
247247
"mtime": 1,
248248
"first_prompt": "fp",
249-
"first_prompt_locked": True,
250-
"command_fallback": "/cmd",
249+
"_first_prompt_locked": True,
250+
"_command_fallback": "/cmd",
251251
"summary_hint": "sh",
252252
"last_prompt": "lp",
253253
"ai_title": "ai",
@@ -272,7 +272,7 @@ def test_precedence_chain(self) -> None:
272272
info = summary_entry_to_sdk_info(base, None)
273273
assert info is not None and info.summary == "fp" and info.first_prompt == "fp"
274274

275-
base["first_prompt_locked"] = False
275+
base["_first_prompt_locked"] = False
276276
info = summary_entry_to_sdk_info(base, None)
277277
assert (
278278
info is not None and info.summary == "/cmd" and info.first_prompt == "/cmd"

0 commit comments

Comments
 (0)