fix(web): stabilize /web handoff and preserve session migration#1073
fix(web): stabilize /web handoff and preserve session migration#1073Fengzdadi wants to merge 2 commits intoMoonshotAI:mainfrom
Conversation
There was a problem hiding this comment.
Pull request overview
This PR improves reliability when switching from CLI shell mode to the Web UI (/web) by preserving the active session across the handoff, propagating the session id into the Web UI URL, and avoiding stderr redirection side-effects during Web startup.
Changes:
- Add
initial_session_idsupport to Web server startup and include it in the browser URL query string. - Preserve empty sessions during
/webswitching so session context isn’t dropped. - Add a stderr “restore” path to undo process-level stderr redirection before starting the Web server.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 3 comments.
| File | Description |
|---|---|
src/kimi_cli/web/app.py |
Adds initial_session_id param and builds browser URL query via urlencode. |
src/kimi_cli/utils/logging.py |
Introduces stderr redirector uninstall + a restore_stderr() helper. |
src/kimi_cli/cli/__init__.py |
Preserves empty sessions on /web switch and restores stderr before launching Web server with session id. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| query: dict[str, str] = {} | ||
| if session_token: | ||
| query["token"] = session_token | ||
| if initial_session_id: | ||
| query["session"] = initial_session_id | ||
| browser_url = f"{url}/?{urlencode(query)}" if query else url |
There was a problem hiding this comment.
make_url() now builds browser_url with session when initial_session_id is set, but downstream the banner currently only prints the “URL with token” when session_token is present. This means in local/no-token mode the displayed URLs can omit the session=... parameter even though the browser-open URL includes it, making copy/paste handoff inconsistent. Consider treating any non-empty query (token or session) as the “URL with params” and updating the banner logic/variable naming accordingly.
src/kimi_cli/utils/logging.py
Outdated
| def uninstall(self) -> None: | ||
| with self._lock: | ||
| if not self._installed: | ||
| return | ||
| if self._original_fd is not None: | ||
| with contextlib.suppress(OSError): | ||
| os.dup2(self._original_fd, 2) | ||
| self._installed = False |
There was a problem hiding this comment.
uninstall() marks the redirector as not installed even if _original_fd is None (e.g., if os.dup(2) failed during install() due to an OSError being suppressed). In that case fd=2 may remain pointing at the pipe, but future logic will believe stderr is restored. Consider making install() fail (or skip redirecting) if the original fd can’t be duplicated, or make uninstall() restore from sys.__stderr__.fileno() / otherwise ensure fd=2 is not left redirected before setting _installed = False.
| if e.session_id is not None: | ||
| session = await Session.find(work_dir, e.session_id) | ||
| if session is not None: | ||
| await _post_run(session, True) | ||
| return True | ||
| await _post_run(session, True, preserve_empty_session=True) | ||
| return True, e.session_id |
There was a problem hiding this comment.
The /web switch path now has new behavior that’s easy to regress (preserving empty sessions and passing initial_session_id into run_web_server). The repo already has pytest coverage for CLI/session behavior; adding a focused test around the SwitchToWeb handling (metadata update + empty-session preservation and/or asserted URL query composition) would help keep the handoff stable.


Related Issue
Related discussions:
Description
This PR fixes
/websession handoff reliability when switching from CLI shell mode to Web UI.What changed:
/webswitch, including empty sessions, so handoff does not lose the current session context.session_idinto Web startup and append it to browser URL as?session=...(coexisting with token query if present)./webswitch path, restore process stderr to avoid same-process stderr redirection interaction causing server hang/timeouts.Manual verification performed locally:
uv run python -m kimi_cli.cli/web/healthzresponds quicklysession=<current_session_id>Checklist
Tested locally; I intentionally did not include additional test files in this PR to keep scope minimal.
make gen-changelogto update the changelog.make gen-docsto update the user documentation.