Repository navigation
fix(sdk-python): stop the CLI gracefully, bound pipe waits, pin cwd, resolve Windows launchers - #586
Merged
Merged
Conversation
- Cancel with SIGTERM: after a terminal Ctrl+C already delivered SIGINT, a second SIGINT hit the CLI's default action and skipped exec.completed. - Wait for the CLI's 60 s shutdown budget before SIGKILL and fire the timeout_ms backstop 90 s after timeout_ms, matching the TypeScript SDK. - Treat exec.completed as terminal, kill a CLI lingering 5 s after it, and detect exit from returncode so a grandchild holding stdout or stderr no longer keeps the Turn open; drain output for at most 2 s after exit. - Pin ThreadOptions.cwd when a Thread is created. - On Windows, run the JS entry and Node runtime behind npm/pnpm shims and the installer's versioned launcher instead of the .cmd file. - CI adds Python 3.14 and a windows-latest job.
… encodings The new windows-latest job failed in test_release_check.py: its helper wrote CHANGELOG.md with the locale code page (cp1252 on Windows), so the '·' in the heading was not UTF-8. Pass encoding="utf-8" to every read_text and write_text in the tests and run pytest with PYTHONWARNDEFAULTENCODING=1 so implicit encodings fail on every platform.
1anZhang
force-pushed
the
fix/python-sdk-process-lifecycle
branch
from
November 4, 2026 01:41
1fe5546 to
e9019de
Compare
3 of 4 tasks
hetaoBackend
approved these changes
Nov 4, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Stacked on #585 (base
fix/python-sdk-4-bugs); GitHub retargets it tomainonce #585 merges. Review the diff against #585 only.Change
Process-lifecycle and Windows fixes for the Python SDK (
packages/code-sdk-python) found while reviewing #585 before0.1.0. All reproduced against the published0.1.0b1and still present with #585 applied. Aligns the SDK with the TypeScript SDK'sexec-process.ts/project-bin.ts.exec.completed. The CLI registers one-shot (once) SIGINT/SIGTERM handlers. A terminal Ctrl+C delivers SIGINT to the CLI's process group; the SDK's cancel then sent a second SIGINT, which hit the default action. Repro: CLI killed after 0.7 s without completing. Fix: cancel with SIGTERM (as the TS SDK does). After: the CLI finishes its graceful shutdown and writesexec.completed.timeout_ms+ 30 s) were shorter than the CLI's 60 s shutdown budget. A CLI still shutting down cleanly was SIGKILLed (repro: 20 s shutdown killed at 10 s). Fix:CANCEL_GRACE_S = 60,BACKSTOP_EXTRA_S = 60 + 30, matchingCLI_SHUTDOWN_BUDGET_MS/CLI_STARTUP_SLACK_MS.thread.run()waiting until it exited (repro: 25.5 s afterexec.completed).asyncio'sProcess.wait()only resolves after every pipe closes, so exit is now detected fromreturncode.exec.completedis terminal (later output ignored, a lingering CLI is killed after 5 s), and after exit the remaining output is drained for at most 2 s (TS:terminateGraceMs,exitDrainMs). After: 2.6 s.cwdwas resolved per Turn, so anos.chdir()between Turns moved an existing Session to another workspace, which the CLI rejects. A Thread now pins its absolutecwdat creation.mcode.cmdthrough cmd.exe. Both the official installer and npm install a.cmdlauncher; arguments were reinterpreted by cmd.exe and cancel (terminate()) stopped only cmd.exe, orphaning the CLI. The SDK now follows npm/pnpm shims and the installer's versioned launcher to the JS entry plus its Node runtime (adjacentnode.exefor npm, the pinned runtime for installer releases; the release pointer is re-read before every Turn), rejects unrecognized batch files, and readsMCODE_BIN/PATHcase-insensitively on Windows.Also: CI matrix adds Python 3.14 and a
windows-latestjob (resolver and option tests; fake-CLI process tests are POSIX-only and skip there); Python version classifiers; README and CHANGELOG (## Unreleased) updated. Version unchanged.bug.Validation
uv run ruff check,ruff format --check,mypy(strict),pytest -W error: 57 passed, 3 skipped (opt-in e2e) on Python 3.10, 3.13 and 3.14 (macOS arm64).exec.completed;cwdpinned at creation;tests/test_cli.pyresolves synthetic npm shims (with/without adjacentnode.exe), the installer's versioned launcher across a self-update, an invalid release pointer, unknown batch files, shell shims,.exe, and case-insensitive env names.mcode0.7.1): e2e 3 passed; breaking out of a streamed Turn and immediately running the next Turn on the same Thread succeeds after the graceful shutdown.release_check.py metadataanddistpass on a fresh build;source-inventory.mjs --writerecordedtests/test_cli.py.windows-latestjob runs it on Windows in CI); the monorepopnpm verifylocally (no TypeScript changes; CI runs it). Results are offline/fake-CLI except the e2e and cancel runs noted above.Publication and contribution checks
release/public-source.json; new tests are declared intest/vitest-suites.jsonwhere applicable (one pytest file added; collected by pytest, not Vitest).Maintainer handoff
Publication scope or license changes (if any): none.
Shared-source port: pending. Follow-up for the TypeScript SDK: it also resolves
cwdper run (args.ts), so item 4 applies there too.Open in [code]smith · Need help on this PR? Tag
@codesmith-botwith what you need.