Repository navigation
fix: reconcile engine, TUI, Tower and Remote Control fixes - #377
Merged
Merged
Conversation
…e LLM response-headers timeout
…n select_tools failures
… relax plugin name validation
|
Important Review skippedToo many files! This PR contains 375 files, which is 275 over the limit of 100. To get a review, reduce the PR to 100 files or fewer by splitting it into smaller PRs or changing its base branch. Upgrade to a paid plan to raise the limit. Usage-priced reviews support at most 300 files. ⚙️ Run configuration
⛔ Files ignored due to path filters: 1
📒 Files selected for processing: 375
You can disable this status message by setting the
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
commit: |
elkaix
enabled auto-merge (squash)
October 15, 2026 19:40
Provider replace and delete looked up provider ids on a plain object, so inherited names such as `constructor` or `__proto__` resolved to Object.prototype members: PUT reported success without writing a provider and DELETE returned 204 for a provider that does not exist. Use own-property lookups and build the provider sections with Object.fromEntries. Remote Control trimmed trailing slashes and found the <head> tag with regexes that run in quadratic time on hostile input, and inlined the relay prefix into a <script> block without escaping `</script>`. Trim with a loop, find the head tag with a linear scan, and escape `<`, `>`, `/`, U+2028 and U+2029 in the inlined prefix.
Merged
elkaix
pushed a commit
that referenced
this pull request
Oct 15, 2026
This PR was opened by the [Changesets release](https://github.com/changesets/action) GitHub action. When you're ready to do a release, you can merge this and the packages will be published to npm automatically. If you're not ready to do a release yet, that's fine, whenever you add more changesets to main, this PR will be updated. # Releases ## @pymodel/pythinker-code@2.7.0 ### Minor Changes - [#377](#377) [`9e30eed`](9e30eed) Thanks [@elkaix](https://github.com/elkaix)! - When a provider registry retires your default model, switch to the replacement it declares and show its migration notes. - [#377](#377) [`9e30eed`](9e30eed) Thanks [@elkaix](https://github.com/elkaix)! - Tower now merges and reviews missions through deterministic git checks, adds the TowerComplete and TowerRebase tools, and blocks destructive shell commands in the main checkout. Enable Tower with PYTHINKER_CODE_EXPERIMENTAL_TOWER=1. ### Patch Changes - [#377](#377) [`9e30eed`](9e30eed) Thanks [@elkaix](https://github.com/elkaix)! - Stop discouraging short progress notes between tool calls, and count NotifyUser reminders per round of tool calls. - [#377](#377) [`9e30eed`](9e30eed) Thanks [@elkaix](https://github.com/elkaix)! - Cancel in-flight video uploads when a media read is interrupted. - [#377](#377) [`9e30eed`](9e30eed) Thanks [@elkaix](https://github.com/elkaix)! - Skip executables inside the workspace during command lookup instead of failing, including when the working directory is the filesystem root. - [#377](#377) [`9e30eed`](9e30eed) Thanks [@elkaix](https://github.com/elkaix)! - Stop the footer from waiting on git status; it now refreshes when the repository changes. - [#377](#377) [`9e30eed`](9e30eed) Thanks [@elkaix](https://github.com/elkaix)! - Keep forked subagent requests on the same prefix as the parent so they reuse the prompt cache. - [#377](#377) [`9e30eed`](9e30eed) Thanks [@elkaix](https://github.com/elkaix)! - Use thinking levels for Gemini 4 models, and send the lowest level when thinking is off. - [#377](#377) [`9e30eed`](9e30eed) Thanks [@elkaix](https://github.com/elkaix)! - Run agent hooks in the session's working directory in the web and desktop apps. - [#377](#377) [`9e30eed`](9e30eed) Thanks [@elkaix](https://github.com/elkaix)! - Show skills invoked in a prompt as highlighted tokens in the message, and let Ctrl+S steer a skill prompt into a running turn. - [#377](#377) [`9e30eed`](9e30eed) Thanks [@elkaix](https://github.com/elkaix)! - Add PYTHINKER_CODE_LLM_HEADERS_TIMEOUT_MS to set how long a request waits for LLM response headers, for slow non-streaming thinking. - [#377](#377) [`9e30eed`](9e30eed) Thanks [@elkaix](https://github.com/elkaix)! - Add `default_deferred` under `[mcp]` in config.toml to load the tools of every MCP server on demand; it requires the experimental tool-select feature. - [#377](#377) [`9e30eed`](9e30eed) Thanks [@elkaix](https://github.com/elkaix)! - Restore the image and video reading tools after resuming a session. - [#377](#377) [`9e30eed`](9e30eed) Thanks [@elkaix](https://github.com/elkaix)! - Give NotifyUser updates an optional one-line title in the Updates panel. Enable NotifyUser with PYTHINKER_CODE_EXPERIMENTAL_NOTIFY_USER=1. - [#377](#377) [`9e30eed`](9e30eed) Thanks [@elkaix](https://github.com/elkaix)! - Register plugin skills as `<plugin-id>:<skill-name>`; a bare skill name no longer runs a plugin skill and there is no setting to restore that, so use `/skill:<plugin-id>:<skill-name>`. Plugin names can now contain uppercase letters, dots, and an `@` suffix. - [#377](#377) [`9e30eed`](9e30eed) Thanks [@elkaix](https://github.com/elkaix)! - Keep the default model and provider when re-importing a provider registry. - [#377](#377) [`9e30eed`](9e30eed) Thanks [@elkaix](https://github.com/elkaix)! - Exit `pythinker web` when the Remote Control relay takes the device offline. - [#377](#377) [`9e30eed`](9e30eed) Thanks [@elkaix](https://github.com/elkaix)! - Remote Control now sends HTTP responses larger than 10 MiB in 5 MiB chunks, up to about 100 MiB, and cancels a transfer when the relay aborts it. - [#377](#377) [`9e30eed`](9e30eed) Thanks [@elkaix](https://github.com/elkaix)! - Remove the never-implemented `executor = "pyaos"` option (and its old `"kaos"` alias) from MCP stdio server configuration; configs that use it now fail validation at load time. - [#377](#377) [`9e30eed`](9e30eed) Thanks [@elkaix](https://github.com/elkaix)! - Explain why select_tools cannot load a tool, and report tools that are not available in the current session separately. - [#377](#377) [`9e30eed`](9e30eed) Thanks [@elkaix](https://github.com/elkaix)! - Show shutdown progress while shutdown hooks run, and exit at once when you press Ctrl+C again. - [#377](#377) [`9e30eed`](9e30eed) Thanks [@elkaix](https://github.com/elkaix)! - Describe only the tools a subagent can actually use. - [#377](#377) [`9e30eed`](9e30eed) Thanks [@elkaix](https://github.com/elkaix)! - Keep the previous answer visible when a background task notification turn ends, and show cancelled background agents as stopped. - [#377](#377) [`9e30eed`](9e30eed) Thanks [@elkaix](https://github.com/elkaix)! - Remind the agent to update its todo list when items stay open for several steps. - [#377](#377) [`9e30eed`](9e30eed) Thanks [@elkaix](https://github.com/elkaix)! - Show Working… instead of Thinking… in the status spinner while the model thinks. ## @pymodel/pythinker-desktop@1.8.0 ### Minor Changes - [#377](#377) [`9e30eed`](9e30eed) Thanks [@elkaix](https://github.com/elkaix)! - When a provider registry retires your default model, switch to the replacement it declares and show its migration notes. - [#377](#377) [`9e30eed`](9e30eed) Thanks [@elkaix](https://github.com/elkaix)! - Tower now merges and reviews missions through deterministic git checks, adds the TowerComplete and TowerRebase tools, and blocks destructive shell commands in the main checkout. Enable Tower with PYTHINKER_CODE_EXPERIMENTAL_TOWER=1. ### Patch Changes - [#377](#377) [`9e30eed`](9e30eed) Thanks [@elkaix](https://github.com/elkaix)! - Stop discouraging short progress notes between tool calls, and count NotifyUser reminders per round of tool calls. - [#377](#377) [`9e30eed`](9e30eed) Thanks [@elkaix](https://github.com/elkaix)! - Cancel in-flight video uploads when a media read is interrupted. - [#377](#377) [`9e30eed`](9e30eed) Thanks [@elkaix](https://github.com/elkaix)! - Skip executables inside the workspace during command lookup instead of failing, including when the working directory is the filesystem root. - [#377](#377) [`9e30eed`](9e30eed) Thanks [@elkaix](https://github.com/elkaix)! - Stop the footer from waiting on git status; it now refreshes when the repository changes. - [#377](#377) [`9e30eed`](9e30eed) Thanks [@elkaix](https://github.com/elkaix)! - Keep forked subagent requests on the same prefix as the parent so they reuse the prompt cache. - [#377](#377) [`9e30eed`](9e30eed) Thanks [@elkaix](https://github.com/elkaix)! - Use thinking levels for Gemini 4 models, and send the lowest level when thinking is off. - [#377](#377) [`9e30eed`](9e30eed) Thanks [@elkaix](https://github.com/elkaix)! - Run agent hooks in the session's working directory in the web and desktop apps. - [#377](#377) [`9e30eed`](9e30eed) Thanks [@elkaix](https://github.com/elkaix)! - Show skills invoked in a prompt as highlighted tokens in the message, and let Ctrl+S steer a skill prompt into a running turn. - [#377](#377) [`9e30eed`](9e30eed) Thanks [@elkaix](https://github.com/elkaix)! - Add PYTHINKER_CODE_LLM_HEADERS_TIMEOUT_MS to set how long a request waits for LLM response headers, for slow non-streaming thinking. - [#377](#377) [`9e30eed`](9e30eed) Thanks [@elkaix](https://github.com/elkaix)! - Add `default_deferred` under `[mcp]` in config.toml to load the tools of every MCP server on demand; it requires the experimental tool-select feature. - [#377](#377) [`9e30eed`](9e30eed) Thanks [@elkaix](https://github.com/elkaix)! - Restore the image and video reading tools after resuming a session. - [#377](#377) [`9e30eed`](9e30eed) Thanks [@elkaix](https://github.com/elkaix)! - Give NotifyUser updates an optional one-line title in the Updates panel. Enable NotifyUser with PYTHINKER_CODE_EXPERIMENTAL_NOTIFY_USER=1. - [#377](#377) [`9e30eed`](9e30eed) Thanks [@elkaix](https://github.com/elkaix)! - Register plugin skills as `<plugin-id>:<skill-name>`; a bare skill name no longer runs a plugin skill and there is no setting to restore that, so use `/skill:<plugin-id>:<skill-name>`. Plugin names can now contain uppercase letters, dots, and an `@` suffix. - [#377](#377) [`9e30eed`](9e30eed) Thanks [@elkaix](https://github.com/elkaix)! - Keep the default model and provider when re-importing a provider registry. - [#377](#377) [`9e30eed`](9e30eed) Thanks [@elkaix](https://github.com/elkaix)! - Exit `pythinker web` when the Remote Control relay takes the device offline. - [#377](#377) [`9e30eed`](9e30eed) Thanks [@elkaix](https://github.com/elkaix)! - Remote Control now sends HTTP responses larger than 10 MiB in 5 MiB chunks, up to about 100 MiB, and cancels a transfer when the relay aborts it. - [#377](#377) [`9e30eed`](9e30eed) Thanks [@elkaix](https://github.com/elkaix)! - Remove the never-implemented `executor = "pyaos"` option (and its old `"kaos"` alias) from MCP stdio server configuration; configs that use it now fail validation at load time. - [#377](#377) [`9e30eed`](9e30eed) Thanks [@elkaix](https://github.com/elkaix)! - Explain why select_tools cannot load a tool, and report tools that are not available in the current session separately. - [#377](#377) [`9e30eed`](9e30eed) Thanks [@elkaix](https://github.com/elkaix)! - Show shutdown progress while shutdown hooks run, and exit at once when you press Ctrl+C again. - [#377](#377) [`9e30eed`](9e30eed) Thanks [@elkaix](https://github.com/elkaix)! - Describe only the tools a subagent can actually use. - [#377](#377) [`9e30eed`](9e30eed) Thanks [@elkaix](https://github.com/elkaix)! - Keep the previous answer visible when a background task notification turn ends, and show cancelled background agents as stopped. - [#377](#377) [`9e30eed`](9e30eed) Thanks [@elkaix](https://github.com/elkaix)! - Remind the agent to update its todo list when items stay open for several steps. - [#377](#377) [`9e30eed`](9e30eed) Thanks [@elkaix](https://github.com/elkaix)! - Show Working… instead of Thinking… in the status spinner while the model thinks. ## pythinker@0.9.9 ### Patch Changes - [#377](#377) [`9e30eed`](9e30eed) Thanks [@elkaix](https://github.com/elkaix)! - Add Back navigation to multi-question prompts and keep earlier answers while moving between questions. Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
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.
Requirement or Bug
A set of fixes and features across the engine, TUI, gateway, Tower, Remote Control and the VS Code extension.
Bug Reproduction Steps
Each fix has a regression test. The main ones:
pythinker provider→ the default model and provider are cleared.Root Cause
Each commit fixes its own root cause; see the commit messages. All are fundamental fixes, not workarounds.
Code Changes
32 commits, one per change, so they can be reviewed one at a time:
agent-core-v2): mid-turn progress notes and calmer NotifyUser nudges, media tools restored after resume, fork subagent prefix parity (plus a prompt-cache probe that reports it),PYTHINKER_CODE_LLM_HEADERS_TIMEOUT_MS,select_toolsexplanations, plugin skills under qualified names,[mcp] default_deferred, a todo-list nudge, subagent tool descriptions that match what the subagent can use, model migration metadata from provider registries.TowerCompleteandTowerRebasetools; a bash guard blocks destructive commands in the main checkout;tower.basestate is removed.pythinker webexits when the relay takes the device offline; responses over 10 MiB are sent as 5 MiBresponse_chunkframes (up to about 100 MiB), and a relayabortcancels a transfer. The relay already acceptsresponse_chunkframes (deployed before this merges).packages/pyaospackage, the never-implemented MCPexecutor = "pyaos"option (and its"kaos"alias), the SDKpyaossession options and RPCs, and thessh2overrides.flake.nixworkspace lists and thepnpmDepshash are updated.Behavior Changes and Affected Users
/skill:reviewran a plugin'sreviewskill/skill:<plugin-id>:reviewruns it@suffix allowedexecutor = "pyaos"/"kaos"kaosnormalized topyaos), never implementedpyaos/persistencePyaossession options*WithPyaosRPCs are gone/PYTHINKER_CODE_EXPERIMENTAL_TOWER=1tower_mode.enterrecords withbasebasestored intower.baseresponse_chunksupport (ours is updated)pythinker webwhen the relay takes the device offlinedeferredonly[mcp] default_deferred(needs tool-select flag)Maintainer sign-off needed: the plugin-skill bare-name removal has no escape hatch. Approved by the maintainer for this PR.
Contract files touched and their consumers:
config-manifest.toml: new[mcp] default_deferred, new registryupgradeobject. Additive; old configs load unchanged.state-manifest.d.ts:tower.baseremoved,llmRequester.lastTurnRequestadded. Old journals replay (unknown key dropped).wire-manifest.d.ts:tower_mode.enterdropsbase. Older records still parse.features/externalHooks/: hook cwd change above.apps/pythinker-code/src/cli/:providerrefresh now goes through the engine;webexits on relay offline.packages/node-sdk:pyaosoptions and RPCs removed (SDK is internal; the CLI is the only published consumer).Tests: every row above has a test in the touched package. Full gates: build, typecheck, lint, sherif, all tests, VS Code typecheck and tests, Nix workspace check, web bundle check,
nix build .#pythinker-code.Checklist
/approve).gen-changesetsskill, or this PR needs no changeset.gen-docsskill, or this PR needs no doc update.