Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,19 @@ GitHub Releases page; `0.8.0` is the new starting line.

## Unreleased

## 0.39.0 (2026-06-09)

- **Refreshed TUI theme and Catppuccin syntax highlighting.** The interface adopts a brand periwinkle/indigo accent (`#B3B9F4` dark / `#0B114E` light) with a reharmonized selection tint, and code blocks now highlight with Catppuccin Mocha (dark) / Latte (light), adaptive to the active theme — implemented as foreground-only Pygments styles with no new dependency. Markdown inline code and links render terminal-native cyan, blockquotes green, and ordered-list markers bright blue (so they adapt per terminal), and user messages sit on a neutral grey block instead of the prior blue tint.
- **Homebrew updater no longer no-ops or false-reports success.** `pythinker update` on a Homebrew install now runs `brew update` to refresh the tap before `brew upgrade`, so a stale local tap clone can't pin the old formula and silently no-op ("0.37.0 already installed"). After upgrading it re-checks the installed version via `brew list --versions` and reports a clear failure instead of "Updated successfully!" when the version did not actually advance.
- **Homebrew updater no longer no-ops or false-reports success.** `pythinker update` on a Homebrew install now runs `brew update` to refresh the tap before `brew upgrade`, so a stale local tap clone can't pin the old formula and silently no-op ("0.38.0 already installed"). After upgrading it re-checks the installed version via `brew list --versions` and reports a clear failure instead of "Updated successfully!" when the version did not actually advance.
- **Friendlier usage-limit (429) messages and ChatGPT account switching.** When a provider returns a 429, Pythinker now renders a human-readable notice — the plan name, the reset window, and a dimmed `Server:` detail line (all markup-escaped) — instead of a raw error string. `/login` for ChatGPT now uses `prompt=login`, so you can switch between ChatGPT accounts instead of being silently kept on the previous session.
- **Agent phase-0 enhancements.** Adds a model-invocable cross-session Recall tool (search and read prior sessions on demand, sanitized and read-only for subagents), read-only MCP resources/prompts surfaced as tools, project-scoped `.pythinker/mcp.json` layering, subagent token/cost roll-up to the orchestrator, and truncated tool output that spills to disk with a recovery hint instead of being lost.
- **No more spurious `coroutine … was never awaited` warnings.** Dropped Sentry's `AsyncioIntegration`, whose `create_task` monkeypatch wrapped every coroutine and — when a task was cancelled before its first step during turn/prompt teardown — orphaned the inner coroutine, printing `WireUISide.receive` and prompt_toolkit "never awaited" `RuntimeWarning`s to the console. The integration added no spans (tracing/profiling are off), and exception capture for async tasks is preserved by the existing asyncio exception handler.
- **Read-only profile guard hardened against version-pinned interpreters.** Inline-code interpreter invocations that use a version-suffixed or absolute binary (`python3.14 -c …`, `/usr/bin/python3.12 -c …`, `node20 -e …`) are now classified as mutating/destructive just like the bare `python`/`node` forms, so they can no longer bypass a read-only subagent profile or skip destructive deliberation.
- **The agent sets up and removes MCP servers on request instead of refusing.** Asked to add, remove, or set up an MCP server, the default agent now knows it runs in Pythinker: it configures the server with the `pythinker mcp add`/`remove` CLI (or by editing `~/.pythinker/mcp.json` / `./.pythinker/mcp.json`), verifies with `pythinker mcp list`/`test`, and tells you to restart or `/reload` to load the change — rather than refusing or citing Claude Code/Desktop config paths (`~/.claude.json`) it cannot use. The prompt now also hard-steers the agent away from writing `mcpServers` into `~/.pythinker/config.yaml` (YAML is never parsed for MCP, so such an entry is silently dropped and the server never appears in `/mcp`). As a backstop, MCP config loading now logs a warning when it finds an `mcpServers` block in a `config.yaml` (global or project), so a human or agent that misplaces it gets a diagnosable trace instead of a silent drop.
- **Security: dependency vulnerability remediation.** Cleared the open Dependabot advisories across all manifests. Python: `asyncssh` 2.22.0 → 2.23.0 (path-traversal in `AuthorizedKeysFile %u`) in the `pythinker-host` pin and both lockfiles, and `starlette` 1.0.0 → 1.2.1 (Host-header path poisoning). JS: regenerated the `web`, `vis`, and `install-counter-worker` lockfiles and bumped the worker's `vitest` to `^3.2.6` (critical Vitest UI arbitrary file read/exec), clearing all critical/high/moderate advisories. The only residual is a handful of low-severity transitive `elliptic`/`bn.js` advisories in `web`'s browser crypto polyfill chain, left unforced because the fix downgrades `vite-plugin-node-polyfills` and majors `ai`, breaking the build for marginal benefit.

Upgrade with `pythinker update`, `pip install --upgrade pythinker-code==0.39.0`, or use the native installer for your platform from the [Releases page](https://github.com/Pythoughts-labs/pythinker-code/releases/latest).

## 0.38.0 (2026-06-08)

- **Quieter `/login`.** Logging in no longer prints a `RuntimeWarning` about an un-awaited `redraw_in_future` coroutine. The prompt redraw throttle now uses a coroutine-free path (`max_render_postpone_time`), eliminating the warning emitted during the login prompt handoff.
Expand Down
49 changes: 26 additions & 23 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,14 +50,17 @@ It speaks the [**Agent Client Protocol (ACP)**](https://github.com/agentclientpr

---

## 🆕 What's New in 0.38.0
## 🆕 What's New in 0.39.0

- **Quieter `/login`.** The login prompt handoff no longer emits a `RuntimeWarning` about an un-awaited `redraw_in_future` coroutine; the redraw throttle now uses a coroutine-free path.
- **Alibaba `/usage` reporting.** A dedicated Alibaba usage adapter means an Alibaba login now produces a populated cost/quota panel instead of the no-adapter fallback.
- **Live pricing from models.dev.** `/usage` and the session stats panel pull per-model pricing from the models.dev catalog (cached 24h) for more accurate cost estimates.
- **More robust ripgrep resolution.** File search verifies a bundled `rg` can actually run on the host platform and architecture before using it, falling back to a system or freshly downloaded ripgrep otherwise.
- **Refreshed TUI theme and Catppuccin syntax highlighting.** The interface adopts a brand periwinkle/indigo accent with a reharmonized selection tint, and code blocks now highlight with Catppuccin Mocha (dark) / Latte (light). Inline code, links, blockquotes, and list markers all render with terminal-native colours; user messages sit on a neutral grey block instead of the prior blue tint.
- **Homebrew updater no longer no-ops or false-reports success.** `pythinker update` on a Homebrew install now refreshes the tap before upgrading and re-checks the installed version afterwards, reporting a clear failure instead of "Updated successfully!" when the version did not actually advance.
- **Friendlier 429 messages and ChatGPT account switching.** Rate-limit responses now render a human-readable notice (plan name, reset window, dimmed server detail) instead of a raw error string. `/login` for ChatGPT uses `prompt=login` so you can switch accounts.
- **Agent phase-0 enhancements.** Adds a cross-session Recall tool, read-only MCP resources/prompts surfaced as tools, project-scoped `.pythinker/mcp.json` layering, subagent token/cost roll-up, and truncated tool output that spills to disk with a recovery hint.
- **Agent knows how to manage MCP servers.** The agent configures, lists, and tests MCP servers via the `pythinker mcp` CLI rather than refusing or citing wrong config paths. YAML `mcpServers` misplacements now log a diagnosable warning.
- **Read-only profile guard hardened.** Version-suffixed or absolute interpreter invocations (`python3.14 -c …`, `node20 -e …`) are now classified as mutating, closing a bypass in read-only subagent profiles.
- **Security: dependency vulnerability remediation.** `asyncssh` → 2.23.0, `starlette` → 1.2.1, JS lockfiles regenerated with `vitest` → ^3.2.6, clearing all critical/high/moderate Dependabot advisories.

Upgrade with `pythinker update`, `pip install --upgrade pythinker-code==0.38.0`, or use the native installer for your platform from the [Releases page](https://github.com/Pythoughts-labs/pythinker-code/releases/latest).
Upgrade with `pythinker update`, `pip install --upgrade pythinker-code==0.39.0`, or use the native installer for your platform from the [Releases page](https://github.com/Pythoughts-labs/pythinker-code/releases/latest).


---
Expand Down Expand Up @@ -147,7 +150,7 @@ matches your OS — no Python, Node, or `uv` prerequisite.

| Platform | Recommended install | Artifact source |
|---|---|---|
| **🪟 Windows** | `irm https://pythinker.com/install.ps1 \| iex` | `PythinkerSetup-0.38.0.exe` from [Releases](https://github.com/Pythoughts-labs/pythinker-code/releases/latest) |
| **🪟 Windows** | `irm https://pythinker.com/install.ps1 \| iex` | `PythinkerSetup-0.39.0.exe` from [Releases](https://github.com/Pythoughts-labs/pythinker-code/releases/latest) |
| **<img src="https://img.shields.io/badge/-macOS-000000?style=flat-square&logo=apple&logoColor=white" alt="macOS"> / <img src="https://img.shields.io/badge/-Linux-FCC624?style=flat-square&logo=linux&logoColor=black" alt="Linux">** | `curl -fsSL https://pythinker.com/install.sh \| bash` | native tarball from [Releases](https://github.com/Pythoughts-labs/pythinker-code/releases/latest) |
| **<img src="https://img.shields.io/badge/-macOS-000000?style=flat-square&logo=apple&logoColor=white" alt="macOS"> — Homebrew** | `brew install Pythoughts-labs/pythinker/pythinker-code` | auto-published Homebrew tap |
| **🐳 Docker** | `docker run --rm -it ghcr.io/pythoughts-labs/pythinker-code` | GHCR multi-arch image |
Expand Down Expand Up @@ -175,7 +178,7 @@ pythinker # start the interactive TUI

### 🪟 Windows — native installer

`PythinkerSetup-0.38.0.exe` is a signed* Inno Setup wizard. Installs per-user
`PythinkerSetup-0.39.0.exe` is a signed* Inno Setup wizard. Installs per-user
into `%LOCALAPPDATA%\Programs\Pythinker`, registers `pythinker` on your user
PATH (`HKCU\Environment`), broadcasts `WM_SETTINGCHANGE` so new shells see
the change. **No UAC prompt.**
Expand All @@ -186,13 +189,13 @@ irm https://pythinker.com/install.ps1 | iex

# Or manually download the installer + checksum from the Releases page,
# verify with Get-FileHash, then run:
.\PythinkerSetup-0.38.0.exe
.\PythinkerSetup-0.39.0.exe

# Open a fresh PowerShell
pythinker --version
```

**Per-machine install** (IT-managed boxes): `.\PythinkerSetup-0.38.0.exe /ALLUSERS`
**Per-machine install** (IT-managed boxes): `.\PythinkerSetup-0.39.0.exe /ALLUSERS`
installs to `%ProgramFiles%\Pythinker` and writes PATH to HKLM (requires admin).

**Upgrade:** `pythinker update` from inside the running app — it downloads
Expand Down Expand Up @@ -243,26 +246,26 @@ attached to every GitHub Release.

```sh
# Debian / Ubuntu (x86_64)
sudo dpkg -i pythinker-code_0.38.0_amd64.deb
sudo dpkg -i pythinker-code_0.39.0_amd64.deb
sudo apt-get install -f # only if dpkg reports missing deps

# Debian / Ubuntu (ARM64)
sudo dpkg -i pythinker-code_0.38.0_arm64.deb
sudo dpkg -i pythinker-code_0.39.0_arm64.deb

# Fedora / RHEL / openSUSE (x86_64)
curl -LO https://github.com/Pythoughts-labs/pythinker-code/releases/download/v0.38.0/pythinker-code-0.38.0.x86_64.rpm
curl -LO https://github.com/Pythoughts-labs/pythinker-code/releases/download/v0.38.0/pythinker-code-0.38.0.x86_64.rpm.sha256
sha256sum -c pythinker-code-0.38.0.x86_64.rpm.sha256
curl -LO https://github.com/Pythoughts-labs/pythinker-code/releases/download/v0.39.0/pythinker-code-0.39.0.x86_64.rpm
curl -LO https://github.com/Pythoughts-labs/pythinker-code/releases/download/v0.39.0/pythinker-code-0.39.0.x86_64.rpm.sha256
sha256sum -c pythinker-code-0.39.0.x86_64.rpm.sha256
# Fedora / RHEL:
sudo dnf install ./pythinker-code-0.38.0.x86_64.rpm
sudo dnf install ./pythinker-code-0.39.0.x86_64.rpm
# openSUSE:
sudo zypper install ./pythinker-code-0.38.0.x86_64.rpm
sudo zypper install ./pythinker-code-0.39.0.x86_64.rpm

# Fedora / RHEL (aarch64)
curl -LO https://github.com/Pythoughts-labs/pythinker-code/releases/download/v0.38.0/pythinker-code-0.38.0.aarch64.rpm
curl -LO https://github.com/Pythoughts-labs/pythinker-code/releases/download/v0.38.0/pythinker-code-0.38.0.aarch64.rpm.sha256
sha256sum -c pythinker-code-0.38.0.aarch64.rpm.sha256
sudo dnf install ./pythinker-code-0.38.0.aarch64.rpm
curl -LO https://github.com/Pythoughts-labs/pythinker-code/releases/download/v0.39.0/pythinker-code-0.39.0.aarch64.rpm
curl -LO https://github.com/Pythoughts-labs/pythinker-code/releases/download/v0.39.0/pythinker-code-0.39.0.aarch64.rpm.sha256
sha256sum -c pythinker-code-0.39.0.aarch64.rpm.sha256
sudo dnf install ./pythinker-code-0.39.0.aarch64.rpm
```

Both packages drop a small `/usr/bin/pythinker` launcher that execs the real
Expand All @@ -271,8 +274,8 @@ binary under `/usr/lib/pythinker/`, so your `$PATH` stays tidy.
**Verify before install:**

```sh
sha256sum -c pythinker-code_0.38.0_amd64.deb.sha256 # Debian/Ubuntu
sha256sum -c pythinker-code-0.38.0.x86_64.rpm.sha256 # Fedora/RHEL
sha256sum -c pythinker-code_0.39.0_amd64.deb.sha256 # Debian/Ubuntu
sha256sum -c pythinker-code-0.39.0.x86_64.rpm.sha256 # Fedora/RHEL
```

**Upgrade:** download the new `.deb`/`.rpm` from Releases and `dpkg -i` /
Expand Down
2 changes: 1 addition & 1 deletion docs/en/guides/getting-started.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ On Windows, run the PowerShell bootstrap. It downloads the native installer, ver
irm https://pythinker.com/install.ps1 | iex
```

You can also download `PythinkerSetup-0.38.0.exe` manually from the [latest release](https://github.com/Pythoughts-labs/pythinker-code/releases/latest).
You can also download `PythinkerSetup-0.39.0.exe` manually from the [latest release](https://github.com/Pythoughts-labs/pythinker-code/releases/latest).

Verify the installation:

Expand Down
4 changes: 4 additions & 0 deletions docs/en/release-notes/breaking-changes.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@ This page documents breaking changes in Pythinker Code releases and provides mig

## Unreleased

## 0.39.0 (2026-06-09)

No breaking changes. This release is compatible with 0.38.0 user configuration, native installs, and session data.

## 0.38.0 (2026-06-08)

No breaking changes. This release is compatible with 0.37.0 user configuration, native installs, and session data.
Expand Down
10 changes: 9 additions & 1 deletion docs/en/release-notes/changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,18 @@ GitHub Releases page; `0.8.0` is the new starting line.

## Unreleased

## 0.39.0 (2026-06-09)

- **Refreshed TUI theme and Catppuccin syntax highlighting.** The interface adopts a brand periwinkle/indigo accent (`#B3B9F4` dark / `#0B114E` light) with a reharmonized selection tint, and code blocks now highlight with Catppuccin Mocha (dark) / Latte (light), adaptive to the active theme — implemented as foreground-only Pygments styles with no new dependency. Markdown inline code and links render terminal-native cyan, blockquotes green, and ordered-list markers bright blue (so they adapt per terminal), and user messages sit on a neutral grey block instead of the prior blue tint.
- **Homebrew updater no longer no-ops or false-reports success.** `pythinker update` on a Homebrew install now runs `brew update` to refresh the tap before `brew upgrade`, so a stale local tap clone can't pin the old formula and silently no-op ("0.37.0 already installed"). After upgrading it re-checks the installed version via `brew list --versions` and reports a clear failure instead of "Updated successfully!" when the version did not actually advance.
- **Homebrew updater no longer no-ops or false-reports success.** `pythinker update` on a Homebrew install now runs `brew update` to refresh the tap before `brew upgrade`, so a stale local tap clone can't pin the old formula and silently no-op ("0.38.0 already installed"). After upgrading it re-checks the installed version via `brew list --versions` and reports a clear failure instead of "Updated successfully!" when the version did not actually advance.
- **Friendlier usage-limit (429) messages and ChatGPT account switching.** When a provider returns a 429, Pythinker now renders a human-readable notice — the plan name, the reset window, and a dimmed `Server:` detail line (all markup-escaped) — instead of a raw error string. `/login` for ChatGPT now uses `prompt=login`, so you can switch between ChatGPT accounts instead of being silently kept on the previous session.
- **Agent phase-0 enhancements.** Adds a model-invocable cross-session Recall tool (search and read prior sessions on demand, sanitized and read-only for subagents), read-only MCP resources/prompts surfaced as tools, project-scoped `.pythinker/mcp.json` layering, subagent token/cost roll-up to the orchestrator, and truncated tool output that spills to disk with a recovery hint instead of being lost.
- **No more spurious `coroutine … was never awaited` warnings.** Dropped Sentry's `AsyncioIntegration`, whose `create_task` monkeypatch wrapped every coroutine and — when a task was cancelled before its first step during turn/prompt teardown — orphaned the inner coroutine, printing `WireUISide.receive` and prompt_toolkit "never awaited" `RuntimeWarning`s to the console. The integration added no spans (tracing/profiling are off), and exception capture for async tasks is preserved by the existing asyncio exception handler.
- **Read-only profile guard hardened against version-pinned interpreters.** Inline-code interpreter invocations that use a version-suffixed or absolute binary (`python3.14 -c …`, `/usr/bin/python3.12 -c …`, `node20 -e …`) are now classified as mutating/destructive just like the bare `python`/`node` forms, so they can no longer bypass a read-only subagent profile or skip destructive deliberation.
- **The agent sets up and removes MCP servers on request instead of refusing.** Asked to add, remove, or set up an MCP server, the default agent now knows it runs in Pythinker: it configures the server with the `pythinker mcp add`/`remove` CLI (or by editing `~/.pythinker/mcp.json` / `./.pythinker/mcp.json`), verifies with `pythinker mcp list`/`test`, and tells you to restart or `/reload` to load the change — rather than refusing or citing Claude Code/Desktop config paths (`~/.claude.json`) it cannot use. The prompt now also hard-steers the agent away from writing `mcpServers` into `~/.pythinker/config.yaml` (YAML is never parsed for MCP, so such an entry is silently dropped and the server never appears in `/mcp`). As a backstop, MCP config loading now logs a warning when it finds an `mcpServers` block in a `config.yaml` (global or project), so a human or agent that misplaces it gets a diagnosable trace instead of a silent drop.
- **Security: dependency vulnerability remediation.** Cleared the open Dependabot advisories across all manifests. Python: `asyncssh` 2.22.0 → 2.23.0 (path-traversal in `AuthorizedKeysFile %u`) in the `pythinker-host` pin and both lockfiles, and `starlette` 1.0.0 → 1.2.1 (Host-header path poisoning). JS: regenerated the `web`, `vis`, and `install-counter-worker` lockfiles and bumped the worker's `vitest` to `^3.2.6` (critical Vitest UI arbitrary file read/exec), clearing all critical/high/moderate advisories. The only residual is a handful of low-severity transitive `elliptic`/`bn.js` advisories in `web`'s browser crypto polyfill chain, left unforced because the fix downgrades `vite-plugin-node-polyfills` and majors `ai`, breaking the build for marginal benefit.

Upgrade with `pythinker update`, `pip install --upgrade pythinker-code==0.39.0`, or use the native installer for your platform from the [Releases page](https://github.com/Pythoughts-labs/pythinker-code/releases/latest).

## 0.38.0 (2026-06-08)

Expand Down
Loading
Loading