Skip to content

fix: make session runtime metadata and REPL model changes stick - #86

Merged
delete-cloud merged 5 commits into
mainfrom
fix/session-runtime-metadata-repl-model
May 2, 2026
Merged

delete-cloud merged 5 commits into
mainfrom
fix/session-runtime-metadata-repl-model

Conversation

@delete-cloud

@delete-cloud delete-cloud commented May 1, 2026 •

Copy link
Copy Markdown
Owner

Summary

  • Preserve restart metadata in HTTP session records so sessions can be rehydrated with the same provider, model, base URL, and step limit.
  • Rebuild the REPL runtime when /model changes so the next turn actually uses the new model.
  • Add focused regressions for HTTP session creation, session serialization, and the REPL model-change path.

Verification

  • uv run pytest tests/cli/test_repl.py::TestReplInitialization::test_model_command_rebuilds_pipeline_on_next_turn tests/ui/test_http_server.py::TestSessionCreation::test_create_session_accepts_runtime_provider_metadata tests/ui/test_http_server.py::TestSessionCreation::test_create_session_rejects_invalid_runtime_provider tests/ui/test_session_manager_public_api.py::test_session_as_dict_includes_restart_metadata -q
  • uv run basedpyright src/coding_agent/cli/commands.py src/coding_agent/cli/repl.py src/coding_agent/ui/http_server.py src/coding_agent/ui/schemas.py src/coding_agent/ui/session_manager.py tests/cli/test_repl.py tests/ui/test_http_server.py tests/ui/test_session_manager_public_api.py --level error
  • uv run python -m compileall -q src tests
  • Manual QA: REPL and HTTP end-to-end smoke against DeepSeek-compatible provider

Summary by CodeRabbit

  • New Features

    • REPL now supports configurable hooks for clear and async model-change handling, enabling custom post-clear and model-switch workflows.
  • Improvements

    • Session creation API accepts provider, model, base URL, and max-steps parameters.
    • Session info and serialization include provider, model, base URL, and max-steps metadata.
    • Runtime replacement now supports safer rebuild-and-rollback behavior when updating model configuration.
  • Tests

    • New and updated tests cover session creation, model switching, runtime replacement, and session serialization.

delete-cloud and others added 3 commits May 2, 2026 01:03
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
@coderabbitai

coderabbitai Bot commented May 1, 2026 •

Copy link
Copy Markdown
Contributor
📝 Walkthrough

Walkthrough

Adds REPL context hooks for clear and model-change handling, delegates /clear UI redraw to a hook, enables runtime provider/model/base_url/max_steps in session creation and serialization, introduces runtime replacement API, and updates tests to exercise these behaviors.

Changes

Cohort / File(s) Summary
CLI commands & REPL
coding-agent/src/coding_agent/cli/commands.py, coding-agent/src/coding_agent/cli/repl.py
Introduce context["on_clear"] and async context["on_model_change"] hooks; /clear footer redraw delegated to on_clear; /model awaits on_model_change(new_model) which may rebuild/rebind runtime, agent, and pipeline.
HTTP API & Schemas
coding-agent/src/coding_agent/ui/http_server.py, coding-agent/src/coding_agent/ui/schemas.py
CreateSessionRequest gains optional provider, model, base_url, max_steps; POST /sessions forwards these (uses max_steps=30 fallback) into session_manager.create_session(...).
Session manager runtime & serialization
coding-agent/src/coding_agent/ui/session_manager.py
Adds _build_session_runtime helper and replace_session_runtime_config(session_id, *, model_name) to rebuild/replace runtime with model override; Session.as_dict() now includes provider_name, model_name, base_url, max_steps.
CLI tests
coding-agent/tests/cli/test_repl.py
Refactors to use real Config, uses monkeypatch.setattr for internals, asserts on_clear presence, expands session-manager fakes, and adds async tests for /model flows including success and failure rollback cases.
HTTP server tests
coding-agent/tests/ui/test_http_server.py
Adds tests verifying provider/model/base_url/max_steps accepted on session creation and invalid provider input returns 422.
Session manager tests
coding-agent/tests/ui/test_session_manager_public_api.py
Adds test asserting Session.as_dict() exposes provider/model/base_url/max_steps when set.

Sequence Diagram

sequenceDiagram
    participant Client
    participant REPL
    participant Hook as on_model_change (async)
    participant SessionMgr
    participant Runtime
    participant Agent

    Client->>REPL: /model <new_model>
    REPL->>Hook: await on_model_change(new_model)
    Hook->>SessionMgr: replace_session_runtime_config(session_id, model_name)
    SessionMgr->>Runtime: build/terminate/replace runtime (may reuse provider)
    SessionMgr->>Agent: rebind adapter/pipeline/context
    Agent->>Runtime: initialize or bind runtime
    Runtime-->>Hook: ready / error
    Hook-->>REPL: completion (success or rollback)
    REPL-->>Client: report model switch result
Loading

Estimated Code Review Effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly Related PRs

Poem

🐰 I hopped through code with nimble feet,
I wired hooks where models meet,
Sessions swapped and pipelines spun,
Adapters hummed — a job well done,
A carrot cheer for builds complete! 🥕

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 6.25% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely summarizes the main changes: preserving session runtime metadata and ensuring REPL model changes persist correctly.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/session-runtime-metadata-repl-model

Review rate limit: 9/10 reviews remaining, refill in 6 minutes.

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@coding-agent/src/coding_agent/cli/repl.py`:
- Around line 275-276: The code sets managed_session.model_name then calls the
synchronous _session_manager._persist_session which can block the event loop;
replace this with an asynchronous persistence call (e.g., await
self._session_manager.persist_session or await
self._session_manager._persist_session_async(managed_session) if such helper
exists) or offload the blocking call to a thread executor (e.g.,
loop.run_in_executor) so the REPL /model path does not perform sync I/O on the
event loop; update the async model-change path where managed_session and
model_name are set to use the awaited async persistence method or
executor-wrapped call.

In `@coding-agent/tests/cli/test_repl.py`:
- Around line 652-655: The test currently skips asserting the /clear callback
when session._on_clear is missing because it uses getattr(session, "_on_clear",
None) and a callable() guard; change this to require the callback
unconditionally by either asserting hasattr(session, "_on_clear") first or by
accessing session._on_clear directly (e.g., on_clear = session._on_clear), then
call on_clear() and assert redraw_calls == ["redraw"] so the test fails if the
callback is absent or broken.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 549df86a-db52-45f9-a3cf-6c12bec42cc7

📥 Commits

Reviewing files that changed from the base of the PR and between 7b0314d and b7b06d0.

📒 Files selected for processing (8)
  • coding-agent/src/coding_agent/cli/commands.py
  • coding-agent/src/coding_agent/cli/repl.py
  • coding-agent/src/coding_agent/ui/http_server.py
  • coding-agent/src/coding_agent/ui/schemas.py
  • coding-agent/src/coding_agent/ui/session_manager.py
  • coding-agent/tests/cli/test_repl.py
  • coding-agent/tests/ui/test_http_server.py
  • coding-agent/tests/ui/test_session_manager_public_api.py

Comment thread coding-agent/src/coding_agent/cli/repl.py Outdated
Comment thread coding-agent/tests/cli/test_repl.py Outdated
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
@delete-cloud

Copy link
Copy Markdown
Owner Author

@codex[agent] Please review this PR

Repository owner deleted a comment from Codex AI May 1, 2026
Repository owner deleted a comment from Codex AI May 1, 2026
Repository owner deleted a comment from Codex AI May 1, 2026
Repository owner deleted a comment from Codex AI May 1, 2026
Repository owner deleted a comment from Codex AI May 1, 2026
Repository owner deleted a comment from Codex AI May 1, 2026

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: b8b7907b32

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +278 to +282
await self._session_manager.shutdown_session_runtime(session_id)
managed_session = self._session_manager.get_session(session_id)
managed_session.model_name = model_name
await self._session_manager._persist_session_async(managed_session)
await self._switch_session(session_id)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Preserve active runtime until model switch succeeds

The /model handler now shuts down the current runtime before verifying that the replacement runtime can be created. If _persist_session_async or _switch_session fails (for example, store I/O issues or agent initialization failures for the requested model), the previous adapter has already been closed and the REPL is left pointing at a torn-down runtime, so later turns can fail even though the command only reports a recoverable error. Defer teardown until after the new runtime is ready, or restore the old runtime on failure.

Useful? React with 👍 / 👎.

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
coding-agent/tests/cli/test_repl.py (1)

551-560: 💤 Low value

Consider using the module-level _make_config helper.

TestFooterIntegration._make_config duplicates the module-level _make_config() function defined at lines 32-48. The implementations are nearly identical.

♻️ Proposed fix
 class TestFooterIntegration:
-    def _make_config(self) -> Config:
-        return Config(
-            model="gpt-4o",
-            api_key=None,
-            provider="openai",
-            repo=Path("."),
-            base_url=None,
-            max_steps=30,
-            approval_mode="auto",
-        )
-
     def test_init_creates_footer(self, monkeypatch):
         from coding_agent.cli.repl import InteractiveSession

         monkeypatch.setattr(InteractiveSession, "_setup_agent", lambda self: None)
-        session = InteractiveSession(self._make_config())
+        session = InteractiveSession(_make_config())
         assert hasattr(session, "_footer")

Apply similar changes to other usages of self._make_config() in this class.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@coding-agent/tests/cli/test_repl.py` around lines 551 - 560, The
TestFooterIntegration._make_config method duplicates the module-level
_make_config helper; remove the class method and update all uses of
self._make_config() inside TestFooterIntegration to call the module-level
_make_config() instead (ensure the module-level function name _make_config is in
scope); update any other usages in the class to use _make_config() so there is a
single shared implementation.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@coding-agent/tests/cli/test_repl.py`:
- Around line 551-560: The TestFooterIntegration._make_config method duplicates
the module-level _make_config helper; remove the class method and update all
uses of self._make_config() inside TestFooterIntegration to call the
module-level _make_config() instead (ensure the module-level function name
_make_config is in scope); update any other usages in the class to use
_make_config() so there is a single shared implementation.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: e79e77eb-9779-4969-a2e7-6a97e0bdeae4

📥 Commits

Reviewing files that changed from the base of the PR and between b8b7907 and fb0b019.

📒 Files selected for processing (3)
  • coding-agent/src/coding_agent/cli/repl.py
  • coding-agent/src/coding_agent/ui/session_manager.py
  • coding-agent/tests/cli/test_repl.py
🚧 Files skipped from review as they are similar to previous changes (1)
  • coding-agent/src/coding_agent/cli/repl.py

@delete-cloud
delete-cloud merged commit 88eef7c into main May 2, 2026
1 check passed
@delete-cloud
delete-cloud deleted the fix/session-runtime-metadata-repl-model branch May 2, 2026 04:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant