agent-session-bridge 0.2.2__tar.gz → 0.2.4__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {agent_session_bridge-0.2.2/src/agent_session_bridge.egg-info → agent_session_bridge-0.2.4}/PKG-INFO +8 -4
- {agent_session_bridge-0.2.2 → agent_session_bridge-0.2.4}/README.md +7 -3
- {agent_session_bridge-0.2.2 → agent_session_bridge-0.2.4}/pyproject.toml +1 -1
- {agent_session_bridge-0.2.2 → agent_session_bridge-0.2.4/src/agent_session_bridge.egg-info}/PKG-INFO +8 -4
- {agent_session_bridge-0.2.2 → agent_session_bridge-0.2.4}/src/session_bridge/writers/claude_code.py +16 -1
- {agent_session_bridge-0.2.2 → agent_session_bridge-0.2.4}/src/session_bridge/writers/codex.py +28 -0
- {agent_session_bridge-0.2.2 → agent_session_bridge-0.2.4}/tests/test_codex_db.py +13 -0
- {agent_session_bridge-0.2.2 → agent_session_bridge-0.2.4}/tests/test_review_round11_fixes.py +10 -2
- {agent_session_bridge-0.2.2 → agent_session_bridge-0.2.4}/tests/test_writers.py +31 -0
- {agent_session_bridge-0.2.2 → agent_session_bridge-0.2.4}/LICENSE +0 -0
- {agent_session_bridge-0.2.2 → agent_session_bridge-0.2.4}/setup.cfg +0 -0
- {agent_session_bridge-0.2.2 → agent_session_bridge-0.2.4}/src/agent_session_bridge.egg-info/SOURCES.txt +0 -0
- {agent_session_bridge-0.2.2 → agent_session_bridge-0.2.4}/src/agent_session_bridge.egg-info/dependency_links.txt +0 -0
- {agent_session_bridge-0.2.2 → agent_session_bridge-0.2.4}/src/agent_session_bridge.egg-info/entry_points.txt +0 -0
- {agent_session_bridge-0.2.2 → agent_session_bridge-0.2.4}/src/agent_session_bridge.egg-info/requires.txt +0 -0
- {agent_session_bridge-0.2.2 → agent_session_bridge-0.2.4}/src/agent_session_bridge.egg-info/top_level.txt +0 -0
- {agent_session_bridge-0.2.2 → agent_session_bridge-0.2.4}/src/session_bridge/__init__.py +0 -0
- {agent_session_bridge-0.2.2 → agent_session_bridge-0.2.4}/src/session_bridge/_ids.py +0 -0
- {agent_session_bridge-0.2.2 → agent_session_bridge-0.2.4}/src/session_bridge/cli.py +0 -0
- {agent_session_bridge-0.2.2 → agent_session_bridge-0.2.4}/src/session_bridge/convert.py +0 -0
- {agent_session_bridge-0.2.2 → agent_session_bridge-0.2.4}/src/session_bridge/handshake.py +0 -0
- {agent_session_bridge-0.2.2 → agent_session_bridge-0.2.4}/src/session_bridge/ir.py +0 -0
- {agent_session_bridge-0.2.2 → agent_session_bridge-0.2.4}/src/session_bridge/place.py +0 -0
- {agent_session_bridge-0.2.2 → agent_session_bridge-0.2.4}/src/session_bridge/readers/__init__.py +0 -0
- {agent_session_bridge-0.2.2 → agent_session_bridge-0.2.4}/src/session_bridge/readers/_content.py +0 -0
- {agent_session_bridge-0.2.2 → agent_session_bridge-0.2.4}/src/session_bridge/readers/_jsonl.py +0 -0
- {agent_session_bridge-0.2.2 → agent_session_bridge-0.2.4}/src/session_bridge/readers/_pending.py +0 -0
- {agent_session_bridge-0.2.2 → agent_session_bridge-0.2.4}/src/session_bridge/readers/claude_code.py +0 -0
- {agent_session_bridge-0.2.2 → agent_session_bridge-0.2.4}/src/session_bridge/readers/codex.py +0 -0
- {agent_session_bridge-0.2.2 → agent_session_bridge-0.2.4}/src/session_bridge/readers/hermes.py +0 -0
- {agent_session_bridge-0.2.2 → agent_session_bridge-0.2.4}/src/session_bridge/skill_install.py +0 -0
- {agent_session_bridge-0.2.2 → agent_session_bridge-0.2.4}/src/session_bridge/skills/session-handoff/SKILL.md +0 -0
- {agent_session_bridge-0.2.2 → agent_session_bridge-0.2.4}/src/session_bridge/tui/__init__.py +0 -0
- {agent_session_bridge-0.2.2 → agent_session_bridge-0.2.4}/src/session_bridge/tui/actions.py +0 -0
- {agent_session_bridge-0.2.2 → agent_session_bridge-0.2.4}/src/session_bridge/tui/app.py +0 -0
- {agent_session_bridge-0.2.2 → agent_session_bridge-0.2.4}/src/session_bridge/tui/discovery.py +0 -0
- {agent_session_bridge-0.2.2 → agent_session_bridge-0.2.4}/src/session_bridge/tui/options.py +0 -0
- {agent_session_bridge-0.2.2 → agent_session_bridge-0.2.4}/src/session_bridge/tui/register.py +0 -0
- {agent_session_bridge-0.2.2 → agent_session_bridge-0.2.4}/src/session_bridge/tui/screens.py +0 -0
- {agent_session_bridge-0.2.2 → agent_session_bridge-0.2.4}/src/session_bridge/tui/summary.py +0 -0
- {agent_session_bridge-0.2.2 → agent_session_bridge-0.2.4}/src/session_bridge/writers/__init__.py +0 -0
- {agent_session_bridge-0.2.2 → agent_session_bridge-0.2.4}/src/session_bridge/writers/_common.py +0 -0
- {agent_session_bridge-0.2.2 → agent_session_bridge-0.2.4}/src/session_bridge/writers/codex_db.py +0 -0
- {agent_session_bridge-0.2.2 → agent_session_bridge-0.2.4}/src/session_bridge/writers/hermes.py +0 -0
- {agent_session_bridge-0.2.2 → agent_session_bridge-0.2.4}/src/session_bridge/writers/hermes_db.py +0 -0
- {agent_session_bridge-0.2.2 → agent_session_bridge-0.2.4}/tests/test_claude_reader.py +0 -0
- {agent_session_bridge-0.2.2 → agent_session_bridge-0.2.4}/tests/test_cli_tui.py +0 -0
- {agent_session_bridge-0.2.2 → agent_session_bridge-0.2.4}/tests/test_codex_reader.py +0 -0
- {agent_session_bridge-0.2.2 → agent_session_bridge-0.2.4}/tests/test_handshake_convert_cli.py +0 -0
- {agent_session_bridge-0.2.2 → agent_session_bridge-0.2.4}/tests/test_hermes_db.py +0 -0
- {agent_session_bridge-0.2.2 → agent_session_bridge-0.2.4}/tests/test_hermes_reader.py +0 -0
- {agent_session_bridge-0.2.2 → agent_session_bridge-0.2.4}/tests/test_ir.py +0 -0
- {agent_session_bridge-0.2.2 → agent_session_bridge-0.2.4}/tests/test_place.py +0 -0
- {agent_session_bridge-0.2.2 → agent_session_bridge-0.2.4}/tests/test_review_fixes.py +0 -0
- {agent_session_bridge-0.2.2 → agent_session_bridge-0.2.4}/tests/test_review_round12_fixes.py +0 -0
- {agent_session_bridge-0.2.2 → agent_session_bridge-0.2.4}/tests/test_review_round13_fixes.py +0 -0
- {agent_session_bridge-0.2.2 → agent_session_bridge-0.2.4}/tests/test_review_round14_fixes.py +0 -0
- {agent_session_bridge-0.2.2 → agent_session_bridge-0.2.4}/tests/test_review_round16_fixes.py +0 -0
- {agent_session_bridge-0.2.2 → agent_session_bridge-0.2.4}/tests/test_review_round17_fixes.py +0 -0
- {agent_session_bridge-0.2.2 → agent_session_bridge-0.2.4}/tests/test_review_round18_fixes.py +0 -0
- {agent_session_bridge-0.2.2 → agent_session_bridge-0.2.4}/tests/test_review_round18b_fixes.py +0 -0
- {agent_session_bridge-0.2.2 → agent_session_bridge-0.2.4}/tests/test_review_round1_fixes.py +0 -0
- {agent_session_bridge-0.2.2 → agent_session_bridge-0.2.4}/tests/test_review_round21_fixes.py +0 -0
- {agent_session_bridge-0.2.2 → agent_session_bridge-0.2.4}/tests/test_review_round22_fixes.py +0 -0
- {agent_session_bridge-0.2.2 → agent_session_bridge-0.2.4}/tests/test_review_round25_fixes.py +0 -0
- {agent_session_bridge-0.2.2 → agent_session_bridge-0.2.4}/tests/test_review_round27_fixes.py +0 -0
- {agent_session_bridge-0.2.2 → agent_session_bridge-0.2.4}/tests/test_review_round28_fixes.py +0 -0
- {agent_session_bridge-0.2.2 → agent_session_bridge-0.2.4}/tests/test_review_round2_fixes.py +0 -0
- {agent_session_bridge-0.2.2 → agent_session_bridge-0.2.4}/tests/test_review_round3_fixes.py +0 -0
- {agent_session_bridge-0.2.2 → agent_session_bridge-0.2.4}/tests/test_review_round4_fixes.py +0 -0
- {agent_session_bridge-0.2.2 → agent_session_bridge-0.2.4}/tests/test_review_round5_fixes.py +0 -0
- {agent_session_bridge-0.2.2 → agent_session_bridge-0.2.4}/tests/test_review_round6_fixes.py +0 -0
- {agent_session_bridge-0.2.2 → agent_session_bridge-0.2.4}/tests/test_review_round7_fixes.py +0 -0
- {agent_session_bridge-0.2.2 → agent_session_bridge-0.2.4}/tests/test_review_round8_fixes.py +0 -0
- {agent_session_bridge-0.2.2 → agent_session_bridge-0.2.4}/tests/test_review_round9_fixes.py +0 -0
- {agent_session_bridge-0.2.2 → agent_session_bridge-0.2.4}/tests/test_skill_install.py +0 -0
- {agent_session_bridge-0.2.2 → agent_session_bridge-0.2.4}/tests/test_stub_open_calls.py +0 -0
- {agent_session_bridge-0.2.2 → agent_session_bridge-0.2.4}/tests/test_tui_actions.py +0 -0
- {agent_session_bridge-0.2.2 → agent_session_bridge-0.2.4}/tests/test_tui_discovery.py +0 -0
- {agent_session_bridge-0.2.2 → agent_session_bridge-0.2.4}/tests/test_tui_options.py +0 -0
- {agent_session_bridge-0.2.2 → agent_session_bridge-0.2.4}/tests/test_tui_pilot.py +0 -0
- {agent_session_bridge-0.2.2 → agent_session_bridge-0.2.4}/tests/test_tui_register.py +0 -0
- {agent_session_bridge-0.2.2 → agent_session_bridge-0.2.4}/tests/test_tui_summary.py +0 -0
{agent_session_bridge-0.2.2/src/agent_session_bridge.egg-info → agent_session_bridge-0.2.4}/PKG-INFO
RENAMED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: agent-session-bridge
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.4
|
|
4
4
|
Summary: Local-first cross-harness agent-session portability: export a live coding-agent session from one harness and resume it in another.
|
|
5
5
|
Author: Prakash Chaudhary
|
|
6
6
|
License: MIT
|
|
@@ -59,11 +59,15 @@ and fail closed (no write) when it doesn't match.
|
|
|
59
59
|
|
|
60
60
|
| Harness | Last verified against | Verification |
|
|
61
61
|
|---|---|---|
|
|
62
|
-
| Claude Code | 2.1.
|
|
63
|
-
| Codex | Codex CLI 0.145.0 (`state_5.sqlite`) | Live `codex resume` recall of
|
|
64
|
-
| Hermes | `state.db` schema as of 2026-07 | Live `hermes --resume` replay
|
|
62
|
+
| Claude Code | 2.1.212 | Live `claude --resume` recall of user AND assistant sentinels, from claude, codex, and hermes sources |
|
|
63
|
+
| Codex | Codex CLI 0.145.0 (`state_5.sqlite`) | Live `codex resume` recall of both-role sentinels from claude and hermes sources, and registered sessions listed in the resume picker |
|
|
64
|
+
| Hermes | `state.db` schema as of 2026-07-28 | Live `hermes --resume` replay with both-role recall, from claude and codex sources |
|
|
65
65
|
| Python | 3.11 – 3.13 | CI test matrix |
|
|
66
66
|
|
|
67
|
+
All six directed conversion pairs were live-verified on real installs on
|
|
68
|
+
2026-07-28 (each source harness resumed in each other target, with the model
|
|
69
|
+
quoting both a user turn and one of its own prior replies).
|
|
70
|
+
|
|
67
71
|
A newer harness version usually still works (formats drift rarely), but treat
|
|
68
72
|
anything beyond this table as unverified: run `session-bridge inspect` first,
|
|
69
73
|
and expect SQLite registration to refuse cleanly if the schema moved.
|
|
@@ -28,11 +28,15 @@ and fail closed (no write) when it doesn't match.
|
|
|
28
28
|
|
|
29
29
|
| Harness | Last verified against | Verification |
|
|
30
30
|
|---|---|---|
|
|
31
|
-
| Claude Code | 2.1.
|
|
32
|
-
| Codex | Codex CLI 0.145.0 (`state_5.sqlite`) | Live `codex resume` recall of
|
|
33
|
-
| Hermes | `state.db` schema as of 2026-07 | Live `hermes --resume` replay
|
|
31
|
+
| Claude Code | 2.1.212 | Live `claude --resume` recall of user AND assistant sentinels, from claude, codex, and hermes sources |
|
|
32
|
+
| Codex | Codex CLI 0.145.0 (`state_5.sqlite`) | Live `codex resume` recall of both-role sentinels from claude and hermes sources, and registered sessions listed in the resume picker |
|
|
33
|
+
| Hermes | `state.db` schema as of 2026-07-28 | Live `hermes --resume` replay with both-role recall, from claude and codex sources |
|
|
34
34
|
| Python | 3.11 – 3.13 | CI test matrix |
|
|
35
35
|
|
|
36
|
+
All six directed conversion pairs were live-verified on real installs on
|
|
37
|
+
2026-07-28 (each source harness resumed in each other target, with the model
|
|
38
|
+
quoting both a user turn and one of its own prior replies).
|
|
39
|
+
|
|
36
40
|
A newer harness version usually still works (formats drift rarely), but treat
|
|
37
41
|
anything beyond this table as unverified: run `session-bridge inspect` first,
|
|
38
42
|
and expect SQLite registration to refuse cleanly if the schema moved.
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "agent-session-bridge"
|
|
7
|
-
version = "0.2.
|
|
7
|
+
version = "0.2.4"
|
|
8
8
|
description = "Local-first cross-harness agent-session portability: export a live coding-agent session from one harness and resume it in another."
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.11"
|
{agent_session_bridge-0.2.2 → agent_session_bridge-0.2.4/src/agent_session_bridge.egg-info}/PKG-INFO
RENAMED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: agent-session-bridge
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.4
|
|
4
4
|
Summary: Local-first cross-harness agent-session portability: export a live coding-agent session from one harness and resume it in another.
|
|
5
5
|
Author: Prakash Chaudhary
|
|
6
6
|
License: MIT
|
|
@@ -59,11 +59,15 @@ and fail closed (no write) when it doesn't match.
|
|
|
59
59
|
|
|
60
60
|
| Harness | Last verified against | Verification |
|
|
61
61
|
|---|---|---|
|
|
62
|
-
| Claude Code | 2.1.
|
|
63
|
-
| Codex | Codex CLI 0.145.0 (`state_5.sqlite`) | Live `codex resume` recall of
|
|
64
|
-
| Hermes | `state.db` schema as of 2026-07 | Live `hermes --resume` replay
|
|
62
|
+
| Claude Code | 2.1.212 | Live `claude --resume` recall of user AND assistant sentinels, from claude, codex, and hermes sources |
|
|
63
|
+
| Codex | Codex CLI 0.145.0 (`state_5.sqlite`) | Live `codex resume` recall of both-role sentinels from claude and hermes sources, and registered sessions listed in the resume picker |
|
|
64
|
+
| Hermes | `state.db` schema as of 2026-07-28 | Live `hermes --resume` replay with both-role recall, from claude and codex sources |
|
|
65
65
|
| Python | 3.11 – 3.13 | CI test matrix |
|
|
66
66
|
|
|
67
|
+
All six directed conversion pairs were live-verified on real installs on
|
|
68
|
+
2026-07-28 (each source harness resumed in each other target, with the model
|
|
69
|
+
quoting both a user turn and one of its own prior replies).
|
|
70
|
+
|
|
67
71
|
A newer harness version usually still works (formats drift rarely), but treat
|
|
68
72
|
anything beyond this table as unverified: run `session-bridge inspect` first,
|
|
69
73
|
and expect SQLite registration to refuse cleanly if the schema moved.
|
{agent_session_bridge-0.2.2 → agent_session_bridge-0.2.4}/src/session_bridge/writers/claude_code.py
RENAMED
|
@@ -23,7 +23,12 @@ def _assistant_content(msg: Message) -> list[dict[str, Any]]:
|
|
|
23
23
|
blocks: list[dict[str, Any]] = []
|
|
24
24
|
for b in msg.content:
|
|
25
25
|
if b.type is BlockType.REASONING:
|
|
26
|
-
|
|
26
|
+
# An empty reasoning block (a presence marker from sources that
|
|
27
|
+
# store reasoning opaquely, e.g. Hermes codex_reasoning_items) is
|
|
28
|
+
# rejected by the Anthropic API on resume ("each thinking block
|
|
29
|
+
# must contain thinking"), so it cannot be preserved here.
|
|
30
|
+
if (b.text or "").strip():
|
|
31
|
+
blocks.append({"type": "thinking", "thinking": b.text, "signature": ""})
|
|
27
32
|
elif b.type is BlockType.TEXT:
|
|
28
33
|
blocks.append({"type": "text", "text": b.text or ""})
|
|
29
34
|
elif b.type is BlockType.TOOL_CALL:
|
|
@@ -78,6 +83,16 @@ def _user_content(msg: Message) -> Any:
|
|
|
78
83
|
|
|
79
84
|
def write_claude_code(session: Session) -> tuple[list[dict[str, Any]], ConversionReport]:
|
|
80
85
|
report = report_losses(session, "claude-code")
|
|
86
|
+
if any(
|
|
87
|
+
b.type is BlockType.REASONING and not (b.text or "").strip()
|
|
88
|
+
for m in session.messages
|
|
89
|
+
for b in m.content
|
|
90
|
+
):
|
|
91
|
+
report.warn(
|
|
92
|
+
"reasoning blocks with no visible text (opaque-source presence "
|
|
93
|
+
"markers) are dropped: the Anthropic API rejects empty thinking "
|
|
94
|
+
"blocks when the transcript is resumed."
|
|
95
|
+
)
|
|
81
96
|
records: list[dict[str, Any]] = []
|
|
82
97
|
|
|
83
98
|
# Preserve original uids/links when present; else synthesize a linear chain.
|
{agent_session_bridge-0.2.2 → agent_session_bridge-0.2.4}/src/session_bridge/writers/codex.py
RENAMED
|
@@ -23,6 +23,16 @@ def _codex_role(role: Role) -> str:
|
|
|
23
23
|
|
|
24
24
|
|
|
25
25
|
def _msg_payload(role: str, text: str) -> dict[str, Any]:
|
|
26
|
+
if role == "assistant":
|
|
27
|
+
# Codex's history reconstruction keeps assistant messages by channel
|
|
28
|
+
# phase; without this the resumed model sees only the user turns.
|
|
29
|
+
block_type = "output_text"
|
|
30
|
+
return {
|
|
31
|
+
"type": "message",
|
|
32
|
+
"role": role,
|
|
33
|
+
"content": [{"type": block_type, "text": text}],
|
|
34
|
+
"phase": "final_answer",
|
|
35
|
+
}
|
|
26
36
|
# Assistant emits output_text; user/system emit input_text.
|
|
27
37
|
block_type = "output_text" if role == "assistant" else "input_text"
|
|
28
38
|
return {"type": "message", "role": role, "content": [{"type": block_type, "text": text}]}
|
|
@@ -173,5 +183,23 @@ def write_codex(
|
|
|
173
183
|
},
|
|
174
184
|
}
|
|
175
185
|
)
|
|
186
|
+
elif msg.role is Role.ASSISTANT:
|
|
187
|
+
# Same twin discipline for assistant turns: the transcript view
|
|
188
|
+
# renders from event_msg records, so without agent_message events
|
|
189
|
+
# a resumed session displays as user-messages-only.
|
|
190
|
+
assistant_text = msg.text()
|
|
191
|
+
if assistant_text.strip():
|
|
192
|
+
records.append(
|
|
193
|
+
{
|
|
194
|
+
"timestamp": ts,
|
|
195
|
+
"type": "event_msg",
|
|
196
|
+
"payload": {
|
|
197
|
+
"type": "agent_message",
|
|
198
|
+
"message": assistant_text,
|
|
199
|
+
"phase": "final_answer",
|
|
200
|
+
"memory_citation": None,
|
|
201
|
+
},
|
|
202
|
+
}
|
|
203
|
+
)
|
|
176
204
|
|
|
177
205
|
return records, report
|
|
@@ -343,6 +343,19 @@ def test_registration_matches_native_picker_requirements(tmp_path, monkeypatch):
|
|
|
343
343
|
]
|
|
344
344
|
assert user_events, "picker requires an event_msg user_message in the rollout"
|
|
345
345
|
assert user_events[0]["payload"]["message"].strip()
|
|
346
|
+
agent_events = [
|
|
347
|
+
r for r in records
|
|
348
|
+
if r.get("type") == "event_msg" and r["payload"].get("type") == "agent_message"
|
|
349
|
+
]
|
|
350
|
+
assert agent_events, "transcript rendering requires agent_message events"
|
|
351
|
+
assistant_items = [
|
|
352
|
+
r for r in records
|
|
353
|
+
if r.get("type") == "response_item" and r["payload"].get("type") == "message"
|
|
354
|
+
and r["payload"].get("role") == "assistant"
|
|
355
|
+
]
|
|
356
|
+
assert assistant_items and all(
|
|
357
|
+
i["payload"].get("phase") == "final_answer" for i in assistant_items
|
|
358
|
+
), "history reconstruction drops assistant messages without a phase"
|
|
346
359
|
conn = sqlite3.connect(home / "state_5.sqlite")
|
|
347
360
|
row = dict(zip([c[0] for c in conn.execute("SELECT model, first_user_message, preview, cli_version FROM threads").description],
|
|
348
361
|
conn.execute("SELECT model, first_user_message, preview, cli_version FROM threads").fetchone()))
|
{agent_session_bridge-0.2.2 → agent_session_bridge-0.2.4}/tests/test_review_round11_fixes.py
RENAMED
|
@@ -34,7 +34,11 @@ def test_codex_preserves_empty_text_reasoning_block(tmp_path):
|
|
|
34
34
|
assert _reasoning_count(back) == 1
|
|
35
35
|
|
|
36
36
|
|
|
37
|
-
def
|
|
37
|
+
def test_empty_reasoning_dropped_with_disclosure_on_claude_return(tmp_path):
|
|
38
|
+
"""Empty reasoning survives INTO codex, but cannot return into a
|
|
39
|
+
claude-code transcript: the Anthropic API rejects empty thinking blocks
|
|
40
|
+
on resume, which would make the whole output unresumable. The drop must
|
|
41
|
+
be disclosed instead."""
|
|
38
42
|
src = tmp_path / "in.jsonl"
|
|
39
43
|
src.write_text(
|
|
40
44
|
json.dumps({
|
|
@@ -49,11 +53,15 @@ def test_empty_reasoning_survives_claude_codex_claude(tmp_path):
|
|
|
49
53
|
h1 = convert("claude-code", "codex", src, inject_handshake=False)
|
|
50
54
|
f1 = tmp_path / "codex.jsonl"
|
|
51
55
|
f1.write_text("\n".join(json.dumps(r) for r in h1.records) + "\n", encoding="utf-8")
|
|
56
|
+
# presence still crosses into codex
|
|
57
|
+
from session_bridge.readers.codex import read_codex
|
|
58
|
+
assert _reasoning_count(read_codex(f1)) == 1
|
|
52
59
|
h2 = convert("codex", "claude-code", f1, inject_handshake=False)
|
|
53
60
|
f2 = tmp_path / "back.jsonl"
|
|
54
61
|
f2.write_text("\n".join(json.dumps(r) for r in h2.records) + "\n", encoding="utf-8")
|
|
55
62
|
from session_bridge.readers.claude_code import read_claude_code
|
|
56
|
-
assert _reasoning_count(read_claude_code(f2)) ==
|
|
63
|
+
assert _reasoning_count(read_claude_code(f2)) == 0
|
|
64
|
+
assert any("empty thinking" in w for w in h2.report.warnings)
|
|
57
65
|
|
|
58
66
|
|
|
59
67
|
def test_hermes_reports_empty_reasoning_loss():
|
|
@@ -120,3 +120,34 @@ def test_to_hermes_warns_when_source_has_open_tool_call(tmp_path):
|
|
|
120
120
|
assert any("no matching result" in w.lower() or "open tool call" in w.lower()
|
|
121
121
|
or "pending" in w.lower()
|
|
122
122
|
for w in report.warnings)
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
def test_claude_writer_drops_empty_reasoning_and_discloses():
|
|
126
|
+
"""Anthropic rejects empty thinking blocks on resume, so presence-marker
|
|
127
|
+
reasoning (e.g. Hermes codex_reasoning_items) cannot reach the output."""
|
|
128
|
+
from session_bridge.ir import ContentBlock, Message, Role, Session, SessionMeta
|
|
129
|
+
from session_bridge.writers.claude_code import write_claude_code
|
|
130
|
+
|
|
131
|
+
session = Session(
|
|
132
|
+
meta=SessionMeta(source_harness="hermes", session_id="s1"),
|
|
133
|
+
messages=(
|
|
134
|
+
Message(role=Role.USER, content=(ContentBlock.text_block("hi"),)),
|
|
135
|
+
Message(
|
|
136
|
+
role=Role.ASSISTANT,
|
|
137
|
+
content=(
|
|
138
|
+
ContentBlock.reasoning(""),
|
|
139
|
+
ContentBlock.text_block("hello"),
|
|
140
|
+
),
|
|
141
|
+
),
|
|
142
|
+
),
|
|
143
|
+
)
|
|
144
|
+
records, report = write_claude_code(session)
|
|
145
|
+
thinking = [
|
|
146
|
+
b
|
|
147
|
+
for r in records
|
|
148
|
+
if isinstance(r.get("message", {}).get("content"), list)
|
|
149
|
+
for b in r["message"]["content"]
|
|
150
|
+
if b.get("type") == "thinking"
|
|
151
|
+
]
|
|
152
|
+
assert not thinking
|
|
153
|
+
assert any("empty thinking" in w for w in report.warnings)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{agent_session_bridge-0.2.2 → agent_session_bridge-0.2.4}/src/session_bridge/readers/__init__.py
RENAMED
|
File without changes
|
{agent_session_bridge-0.2.2 → agent_session_bridge-0.2.4}/src/session_bridge/readers/_content.py
RENAMED
|
File without changes
|
{agent_session_bridge-0.2.2 → agent_session_bridge-0.2.4}/src/session_bridge/readers/_jsonl.py
RENAMED
|
File without changes
|
{agent_session_bridge-0.2.2 → agent_session_bridge-0.2.4}/src/session_bridge/readers/_pending.py
RENAMED
|
File without changes
|
{agent_session_bridge-0.2.2 → agent_session_bridge-0.2.4}/src/session_bridge/readers/claude_code.py
RENAMED
|
File without changes
|
{agent_session_bridge-0.2.2 → agent_session_bridge-0.2.4}/src/session_bridge/readers/codex.py
RENAMED
|
File without changes
|
{agent_session_bridge-0.2.2 → agent_session_bridge-0.2.4}/src/session_bridge/readers/hermes.py
RENAMED
|
File without changes
|
{agent_session_bridge-0.2.2 → agent_session_bridge-0.2.4}/src/session_bridge/skill_install.py
RENAMED
|
File without changes
|
|
File without changes
|
{agent_session_bridge-0.2.2 → agent_session_bridge-0.2.4}/src/session_bridge/tui/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{agent_session_bridge-0.2.2 → agent_session_bridge-0.2.4}/src/session_bridge/tui/discovery.py
RENAMED
|
File without changes
|
|
File without changes
|
{agent_session_bridge-0.2.2 → agent_session_bridge-0.2.4}/src/session_bridge/tui/register.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{agent_session_bridge-0.2.2 → agent_session_bridge-0.2.4}/src/session_bridge/writers/__init__.py
RENAMED
|
File without changes
|
{agent_session_bridge-0.2.2 → agent_session_bridge-0.2.4}/src/session_bridge/writers/_common.py
RENAMED
|
File without changes
|
{agent_session_bridge-0.2.2 → agent_session_bridge-0.2.4}/src/session_bridge/writers/codex_db.py
RENAMED
|
File without changes
|
{agent_session_bridge-0.2.2 → agent_session_bridge-0.2.4}/src/session_bridge/writers/hermes.py
RENAMED
|
File without changes
|
{agent_session_bridge-0.2.2 → agent_session_bridge-0.2.4}/src/session_bridge/writers/hermes_db.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{agent_session_bridge-0.2.2 → agent_session_bridge-0.2.4}/tests/test_handshake_convert_cli.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{agent_session_bridge-0.2.2 → agent_session_bridge-0.2.4}/tests/test_review_round12_fixes.py
RENAMED
|
File without changes
|
{agent_session_bridge-0.2.2 → agent_session_bridge-0.2.4}/tests/test_review_round13_fixes.py
RENAMED
|
File without changes
|
{agent_session_bridge-0.2.2 → agent_session_bridge-0.2.4}/tests/test_review_round14_fixes.py
RENAMED
|
File without changes
|
{agent_session_bridge-0.2.2 → agent_session_bridge-0.2.4}/tests/test_review_round16_fixes.py
RENAMED
|
File without changes
|
{agent_session_bridge-0.2.2 → agent_session_bridge-0.2.4}/tests/test_review_round17_fixes.py
RENAMED
|
File without changes
|
{agent_session_bridge-0.2.2 → agent_session_bridge-0.2.4}/tests/test_review_round18_fixes.py
RENAMED
|
File without changes
|
{agent_session_bridge-0.2.2 → agent_session_bridge-0.2.4}/tests/test_review_round18b_fixes.py
RENAMED
|
File without changes
|
|
File without changes
|
{agent_session_bridge-0.2.2 → agent_session_bridge-0.2.4}/tests/test_review_round21_fixes.py
RENAMED
|
File without changes
|
{agent_session_bridge-0.2.2 → agent_session_bridge-0.2.4}/tests/test_review_round22_fixes.py
RENAMED
|
File without changes
|
{agent_session_bridge-0.2.2 → agent_session_bridge-0.2.4}/tests/test_review_round25_fixes.py
RENAMED
|
File without changes
|
{agent_session_bridge-0.2.2 → agent_session_bridge-0.2.4}/tests/test_review_round27_fixes.py
RENAMED
|
File without changes
|
{agent_session_bridge-0.2.2 → agent_session_bridge-0.2.4}/tests/test_review_round28_fixes.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|