test(natives): gave timeout drain repro a spawn-proof deadline

The 50ms budget raced external-process spawn on cold CI runners: cancel
could fire before yes produced output, so the builtin tail flushed an
empty ring buffer (0 lines instead of 5, Linux x64 modern). 750ms keeps
the post-cancel drain scenario while outlasting spawn latency.
This commit is contained in:
can1357
2026-07-17 06:09:51 +02:00
parent 1b267ad3fe
commit 731a2cb5b2
10 changed files with 658 additions and 215 deletions
+9 -2
View File
@@ -563,16 +563,23 @@ mod tests {
async fn timeout_drains_pipeline_output_before_stopping_reader() {
let shell = CoreShell::new(None);
let (tx, rx) = flume::unbounded::<String>();
// `tail` runs as an in-process builtin, so cancellation kills only the
// external `yes`; tail then sees EOF and flushes its final 5 lines into
// the post-cancel reader grace window. The deadline must be generous
// enough that `yes` has demonstrably spawned and produced before the
// timeout fires — a 50ms budget lost that race on cold CI runners and
// tail flushed an empty ring buffer.
const TIMEOUT_MS: u32 = 750;
let result = shell
.run(
CoreShellRunOptions {
command: "yes x | tail -5".to_string(),
cwd: None,
env: None,
timeout_ms: Some(50),
timeout_ms: Some(TIMEOUT_MS),
},
Some(tx),
CancelToken::new(Some(50)),
CancelToken::new(Some(TIMEOUT_MS)),
)
.await
.expect("shell run");
+2 -2
View File
@@ -4,8 +4,8 @@
### Fixed
- Surfaced provider stream failures through the normal assistant message lifecycle so interactive clients show the terminal error instead of leaving users with a silent working spinner.
- Fixed Cursor provider contexts omitting host-supplied MCP tools from main and side-channel requests ([#5650](https://github.com/can1357/oh-my-pi/issues/5650)).
- Improved error visibility in interactive clients by surfacing provider stream failures through the assistant message lifecycle, preventing silent loading spinners.
- Fixed an issue where Cursor provider contexts omitted host-supplied MCP tools from main and side-channel requests.
## [17.0.0] - 2026-07-15
+7 -7
View File
@@ -4,13 +4,13 @@
### Fixed
- Automatically invalidate and rotate OAuth credentials when an "invalidated oauth token" error occurs
- Fixed auth-broker snapshot validation rejecting API keys stored via the `/login` flow (`credentials[N].credential.source must be removed`): the wire schema now accepts the `source: "login"` marker on `api_key` credentials, so gateway/broker setups serving login-sourced keys (e.g. custom hosts) work again.
- Fixed leaked-thinking healing consuming a literal reasoning tag (e.g. `` `<think>` ``) inside a Markdown inline-code span or fenced code block as a reasoning boundary, which split the visible text into `text` + `thinking` blocks and corrupted the rendered Markdown ([#5665](https://github.com/can1357/oh-my-pi/issues/5665)).
- Classified HTTP 402 and `balance exhausted` quota responses as persistent usage limits, rotating multi-account requests to a sibling credential.
- Fixed `kimi-code` Anthropic-format requests ignoring custom provider base URLs ([#5722](https://github.com/can1357/oh-my-pi/issues/5722)).
- Fixed GPT-5.6 Codex Responses-Lite requests leaving a forced top-level `tool_choice` (e.g. `{ type: "web_search" }`) after the Lite rewrite moves tools into an `additional_tools` developer item and drops top-level `tools`, which the ChatGPT Codex endpoint rejected with `HTTP 400 Tool choice '…' not found in 'tools' parameter`. `applyCodexResponsesLiteShape` now downgrades forced hosted choices to `tool_choice: "auto"` while preserving explicit tool-use constraints ([#5771](https://github.com/can1357/oh-my-pi/issues/5771)).
- Fixed Cursor streams reporting success before late CONNECT or gRPC terminal failures were observed, and rejecting transport ends without `turnEnded` ([#5634](https://github.com/can1357/oh-my-pi/issues/5634)).
- Automatically invalidate and rotate OAuth credentials when an "invalidated oauth token" error occurs.
- Fixed auth-broker snapshot validation rejecting API keys stored via the `/login` flow, restoring support for gateway/broker setups serving login-sourced keys on custom hosts.
- Fixed an issue where literal reasoning tags (e.g., `<think>`) inside Markdown code blocks or inline code were incorrectly treated as reasoning boundaries, which corrupted the rendered Markdown.
- Classified HTTP 402 and "balance exhausted" quota responses as persistent usage limits, enabling automatic rotation of multi-account requests to a sibling credential.
- Fixed `kimi-code` Anthropic-format requests ignoring custom provider base URLs.
- Fixed an issue where GPT-5.6 Codex Responses-Lite requests failed with an HTTP 400 error due to invalid `tool_choice` parameters after tools were rewritten, by automatically downgrading forced hosted choices to `tool_choice: "auto"` while preserving explicit tool-use constraints.
- Fixed Cursor streams prematurely reporting success before late CONNECT or gRPC terminal failures were observed, and resolved issues rejecting transport ends without a `turnEnded` signal.
## [17.0.1] - 2026-07-16
+4 -4
View File
@@ -4,13 +4,13 @@
### Changed
- Increased maxTokens from 32,768 to 65,536 for Kimi K2.7-Code models on Fireworks
- Increased the maximum output tokens (maxTokens) from 32,768 to 65,536 for Kimi K2.7-Code models on Fireworks.
### Fixed
- Fixed `openai-codex` GPT-5.6 Luna/Sol/Terra `contextWindow` regressing from 372000 to 272000: when upstream omits `context_window`, Codex discovery fell back to the generic `DEFAULT_CONTEXT_WINDOW` (272000), which both overwrote the bundled hard capacity on regen and — for logged-in Codex users — re-overwrote it on every live discovery refresh. Codex discovery now falls back to the upstream-declared 372000 for GPT-5.6 SKUs, and `applyOpenAICatalogPolicy` pins the same value at generation time ([#5705](https://github.com/can1357/oh-my-pi/issues/5705)).
- Fixed Umans PAYG models showing as "Free" in `/models` by sourcing the provider's published per-token rates instead of the all-zero coding-plan catalog ([#5733](https://github.com/can1357/oh-my-pi/issues/5733)).
- Fixed native `moonshot/kimi-k3` being labeled "Free" with no capabilities: the discovered id has no bundled/models.dev reference, so it fell through to zero cost, null limits, text-only input, and no reasoning. It now carries Moonshot's official K3 pricing (`$3` input / `$0.30` cache-hit / `$15` output), a 1,048,576-token context window, image input, and reasoning that routes through OpenAI-style `reasoning_effort: "max"` (K3 does not use the K2.x `thinking` block). Native K3 is also exempt from the Kimi forced-tool-choice reasoning suppression (a K2.x-only Moonshot conflict), so plan-mode forced tool turns keep the mandatory `max` effort; its documented 131,072-token output cap is allowed through the Chat Completions request clamp instead of being reduced to the generic 64,000-token ceiling ([#5756](https://github.com/can1357/oh-my-pi/issues/5756)).
- Fixed a regression where the context window for openai-codex GPT-5.6 models (Luna, Sol, Terra) incorrectly fell back to 272,000 instead of preserving its 372,000 capacity.
- Fixed Umans PAYG models incorrectly displaying as "Free" in /models by correctly sourcing their published per-token rates.
- Fixed native moonshot/kimi-k3 capabilities and pricing, ensuring it correctly reflects its official pricing, 1M context window, image input support, reasoning capabilities, and 128k output token limit.
## [17.0.1] - 2026-07-16
+559 -120
View File
@@ -3036,11 +3036,11 @@
},
"glm-4.5": {
"id": "glm-4.5",
"name": "glm-4.5",
"name": "GLM-4.5",
"api": "openai-completions",
"provider": "aimlapi",
"baseUrl": "https://api.aimlapi.com/v1",
"reasoning": false,
"reasoning": true,
"input": [
"text"
],
@@ -3051,7 +3051,17 @@
"cacheWrite": 0
},
"contextWindow": 131072,
"maxTokens": 98304
"maxTokens": 98304,
"thinking": {
"mode": "effort",
"efforts": [
"minimal",
"low",
"medium",
"high",
"xhigh"
]
}
},
"glm-4.5-air": {
"id": "glm-4.5-air",
@@ -3084,7 +3094,7 @@
},
"glm-4.6": {
"id": "glm-4.6",
"name": "glm-4.6",
"name": "GLM-4.6",
"api": "openai-completions",
"provider": "aimlapi",
"baseUrl": "https://api.aimlapi.com/v1",
@@ -12876,7 +12886,7 @@
"cacheRead": 0.16999999999999998,
"cacheWrite": 0
},
"contextWindow": 1048576,
"contextWindow": 131000,
"maxTokens": 32768
},
"zai-org/GLM-4.7": {
@@ -17694,48 +17704,6 @@
"contextWindow": 200000,
"maxTokens": 64000
},
"MODEL_SWE_1_5": {
"id": "MODEL_SWE_1_5",
"name": "SWE-1.5 Fast",
"api": "devin-agent",
"provider": "devin",
"baseUrl": "https://server.codeium.com",
"reasoning": true,
"input": [
"text",
"image"
],
"supportsTools": true,
"cost": {
"input": 0,
"output": 0,
"cacheRead": 0,
"cacheWrite": 0
},
"contextWindow": 128000,
"maxTokens": 64000
},
"MODEL_SWE_1_5_SLOW": {
"id": "MODEL_SWE_1_5_SLOW",
"name": "SWE-1.5",
"api": "devin-agent",
"provider": "devin",
"baseUrl": "https://server.codeium.com",
"reasoning": true,
"input": [
"text",
"image"
],
"supportsTools": true,
"cost": {
"input": 0,
"output": 0,
"cacheRead": 0,
"cacheWrite": 0
},
"contextWindow": 200000,
"maxTokens": 64000
},
"nemotron-3-ultra-nvfp4": {
"id": "nemotron-3-ultra-nvfp4",
"name": "Nemotron 3 Ultra",
@@ -18074,9 +18042,9 @@
"text"
],
"cost": {
"input": 0,
"output": 0,
"cacheRead": 0,
"input": 1.4,
"output": 4.4,
"cacheRead": 0.26,
"cacheWrite": 0
},
"contextWindow": 1048576,
@@ -18259,7 +18227,7 @@
"cacheWrite": 0
},
"contextWindow": 262144,
"maxTokens": 65536,
"maxTokens": 262144,
"thinking": {
"mode": "effort",
"efforts": [
@@ -19782,7 +19750,8 @@
"minimal",
"low",
"medium",
"high"
"high",
"xhigh"
]
}
},
@@ -24804,6 +24773,25 @@
]
}
},
"~x-ai/grok-latest": {
"id": "~x-ai/grok-latest",
"name": "Grok Latest",
"api": "openai-completions",
"provider": "kilo",
"baseUrl": "https://api.kilo.ai/api/gateway",
"reasoning": false,
"input": [
"text"
],
"cost": {
"input": 0,
"output": 0,
"cacheRead": 0,
"cacheWrite": 0
},
"contextWindow": null,
"maxTokens": null
},
"ai21/jamba-large-1.7": {
"id": "ai21/jamba-large-1.7",
"name": "Jamba Large 1.7",
@@ -28227,6 +28215,25 @@
"contextWindow": null,
"maxTokens": null
},
"kwaipilot/kat-coder-pro-v2.5:free": {
"id": "kwaipilot/kat-coder-pro-v2.5:free",
"name": "KAT-Coder-Pro V2.5 (free)",
"api": "openai-completions",
"provider": "kilo",
"baseUrl": "https://api.kilo.ai/api/gateway",
"reasoning": false,
"input": [
"text"
],
"cost": {
"input": 0,
"output": 0,
"cacheRead": 0,
"cacheWrite": 0
},
"contextWindow": null,
"maxTokens": null
},
"liquid/lfm-2-24b-a2b": {
"id": "liquid/lfm-2-24b-a2b",
"name": "LFM2-24B-A2B",
@@ -29728,6 +29735,25 @@
]
}
},
"moonshotai/kimi-k3": {
"id": "moonshotai/kimi-k3",
"name": "Kimi K3",
"api": "openai-completions",
"provider": "kilo",
"baseUrl": "https://api.kilo.ai/api/gateway",
"reasoning": false,
"input": [
"text"
],
"cost": {
"input": 0,
"output": 0,
"cacheRead": 0,
"cacheWrite": 0
},
"contextWindow": 1048576,
"maxTokens": 131072
},
"morph-warp-grep-v2": {
"id": "morph-warp-grep-v2",
"name": "WarpGrep V2",
@@ -34978,6 +35004,36 @@
]
}
},
"x-ai/grok-4.5": {
"id": "x-ai/grok-4.5",
"name": "Grok 4.5",
"api": "openai-completions",
"provider": "kilo",
"baseUrl": "https://api.kilo.ai/api/gateway",
"reasoning": true,
"input": [
"text",
"image"
],
"cost": {
"input": 0,
"output": 0,
"cacheRead": 0,
"cacheWrite": 0
},
"contextWindow": 500000,
"maxTokens": 500000,
"thinking": {
"mode": "effort",
"efforts": [
"minimal",
"low",
"medium",
"high",
"xhigh"
]
}
},
"x-ai/grok-build-0.1": {
"id": "x-ai/grok-build-0.1",
"name": "Grok Build 0.1",
@@ -35622,9 +35678,43 @@
}
},
"kimi-code": {
"k3": {
"id": "k3",
"name": "K3",
"api": "openai-completions",
"provider": "kimi-code",
"baseUrl": "https://api.kimi.com/coding/v1",
"reasoning": true,
"input": [
"text",
"image"
],
"cost": {
"input": 0,
"output": 0,
"cacheRead": 0,
"cacheWrite": 0
},
"contextWindow": 1048576,
"maxTokens": 32000,
"thinking": {
"mode": "effort",
"efforts": [
"minimal",
"low",
"medium",
"high"
]
},
"compat": {
"thinkingFormat": "zai",
"reasoningContentField": "reasoning_content",
"supportsDeveloperRole": false
}
},
"kimi-for-coding": {
"id": "kimi-for-coding",
"name": "K2.7 Code",
"name": "K2.7 Coding",
"api": "openai-completions",
"provider": "kimi-code",
"baseUrl": "https://api.kimi.com/coding/v1",
@@ -35653,6 +35743,45 @@
"medium",
"high"
]
},
"compat": {
"thinkingFormat": "zai",
"reasoningContentField": "reasoning_content",
"supportsDeveloperRole": false
}
},
"kimi-for-coding-highspeed": {
"id": "kimi-for-coding-highspeed",
"name": "K2.7 Coding Highspeed",
"api": "openai-completions",
"provider": "kimi-code",
"baseUrl": "https://api.kimi.com/coding/v1",
"reasoning": true,
"input": [
"text",
"image"
],
"cost": {
"input": 0,
"output": 0,
"cacheRead": 0,
"cacheWrite": 0
},
"contextWindow": 262144,
"maxTokens": 32000,
"thinking": {
"mode": "effort",
"efforts": [
"minimal",
"low",
"medium",
"high"
]
},
"compat": {
"thinkingFormat": "zai",
"reasoningContentField": "reasoning_content",
"supportsDeveloperRole": false
}
},
"kimi-k2": {
@@ -37742,6 +37871,36 @@
]
}
},
"kimi-k3": {
"id": "kimi-k3",
"name": "Kimi K3",
"api": "openai-completions",
"provider": "moonshot",
"baseUrl": "https://api.moonshot.ai/v1",
"reasoning": true,
"input": [
"text",
"image"
],
"cost": {
"input": 3,
"output": 15,
"cacheRead": 0.3,
"cacheWrite": 0
},
"contextWindow": 1048576,
"maxTokens": 131072,
"thinking": {
"mode": "effort",
"efforts": [
"minimal",
"low",
"medium",
"high",
"xhigh"
]
}
},
"moonshot-v1-128k": {
"id": "moonshot-v1-128k",
"name": "moonshot-v1-128k",
@@ -47022,6 +47181,25 @@
"contextWindow": 262144,
"maxTokens": 262144
},
"moonshotai/kimi-k3": {
"id": "moonshotai/kimi-k3",
"name": "moonshotai/kimi-k3",
"api": "openai-completions",
"provider": "nanogpt",
"baseUrl": "https://nano-gpt.com/api/v1",
"reasoning": false,
"input": [
"text"
],
"cost": {
"input": 0,
"output": 0,
"cacheRead": 0,
"cacheWrite": 0
},
"contextWindow": 1048576,
"maxTokens": 131072
},
"moonshotai/kimi-latest": {
"id": "moonshotai/kimi-latest",
"name": "Kimi Latest",
@@ -52955,6 +53133,36 @@
"contextWindow": null,
"maxTokens": null
},
"thinkingmachines/inkling": {
"id": "thinkingmachines/inkling",
"name": "Inkling",
"api": "openai-completions",
"provider": "nanogpt",
"baseUrl": "https://nano-gpt.com/api/v1",
"reasoning": true,
"input": [
"text",
"image"
],
"cost": {
"input": 1,
"output": 4.05,
"cacheRead": 0.16999999999999998,
"cacheWrite": 0
},
"contextWindow": 1048576,
"maxTokens": 32768,
"thinking": {
"mode": "effort",
"efforts": [
"minimal",
"low",
"medium",
"high",
"xhigh"
]
}
},
"THUDM/GLM-4-32B-0414": {
"id": "THUDM/GLM-4-32B-0414",
"name": "THUDM/GLM-4-32B-0414",
@@ -61261,7 +61469,7 @@
},
"glm-4.6": {
"id": "glm-4.6",
"name": "glm-4.6",
"name": "GLM-4.6",
"api": "ollama-chat",
"provider": "ollama-cloud",
"baseUrl": "https://ollama.com",
@@ -64473,6 +64681,36 @@
]
}
},
"grok-4.5": {
"id": "grok-4.5",
"name": "Grok 4.5",
"api": "openai-completions",
"provider": "opencode-go",
"baseUrl": "https://opencode.ai/zen/go/v1",
"reasoning": true,
"input": [
"text",
"image"
],
"cost": {
"input": 2,
"output": 6,
"cacheRead": 0.5,
"cacheWrite": 0
},
"contextWindow": 500000,
"maxTokens": 500000,
"thinking": {
"mode": "effort",
"efforts": [
"minimal",
"low",
"medium",
"high",
"xhigh"
]
}
},
"kimi-k2.5": {
"id": "kimi-k2.5",
"name": "Kimi K2.5",
@@ -64566,6 +64804,36 @@
]
}
},
"kimi-k3": {
"id": "kimi-k3",
"name": "Kimi K3",
"api": "openai-completions",
"provider": "opencode-go",
"baseUrl": "https://opencode.ai/zen/go/v1",
"reasoning": true,
"input": [
"text",
"image"
],
"cost": {
"input": 3,
"output": 15,
"cacheRead": 0.3,
"cacheWrite": 0
},
"contextWindow": 1048576,
"maxTokens": 131072,
"thinking": {
"mode": "effort",
"efforts": [
"minimal",
"low",
"medium",
"high",
"xhigh"
]
}
},
"mimo-v2-omni": {
"id": "mimo-v2-omni",
"name": "MiMo-V2-Omni",
@@ -65471,7 +65739,7 @@
},
"glm-4.6": {
"id": "glm-4.6",
"name": "glm-4.6",
"name": "GLM-4.6",
"api": "openai-completions",
"provider": "opencode-zen",
"baseUrl": "https://opencode.ai/zen/v1",
@@ -67159,12 +67427,12 @@
"image"
],
"cost": {
"input": 0.66,
"output": 3.41,
"cacheRead": 0.15,
"input": 3,
"output": 15,
"cacheRead": 0.3,
"cacheWrite": 0
},
"contextWindow": 262144,
"contextWindow": 1048576,
"maxTokens": 262144,
"thinking": {
"mode": "effort",
@@ -68785,7 +69053,7 @@
"cost": {
"input": 0.098,
"output": 0.196,
"cacheRead": 0.02,
"cacheRead": 0.0196,
"cacheWrite": 0
},
"contextWindow": 1048576,
@@ -69366,8 +69634,8 @@
"image"
],
"cost": {
"input": 0.08,
"output": 0.44999999999999996,
"input": 0.09999999999999999,
"output": 0.3,
"cacheRead": 0.04,
"cacheWrite": 0
},
@@ -70005,6 +70273,35 @@
"contextWindow": 10000000,
"maxTokens": 16384
},
"meta/muse-spark-1.1": {
"id": "meta/muse-spark-1.1",
"name": "Muse Spark 1.1",
"api": "openrouter",
"provider": "openrouter",
"baseUrl": "https://openrouter.ai/api/v1",
"reasoning": true,
"input": [
"text",
"image"
],
"cost": {
"input": 1.25,
"output": 4.25,
"cacheRead": 0.15,
"cacheWrite": 0
},
"contextWindow": 1048576,
"maxTokens": 1048576,
"thinking": {
"mode": "effort",
"efforts": [
"minimal",
"low",
"medium",
"high"
]
}
},
"minimax/minimax-m1": {
"id": "minimax/minimax-m1",
"name": "MiniMax M1",
@@ -70159,9 +70456,9 @@
"text"
],
"cost": {
"input": 0.3,
"output": 1.2,
"cacheRead": 0.06,
"input": 0.25,
"output": 1,
"cacheRead": 0.049999999999999996,
"cacheWrite": 0
},
"contextWindow": 204800,
@@ -70498,8 +70795,8 @@
"text"
],
"cost": {
"input": 0.02,
"output": 0.04,
"input": 0.019000000000000003,
"output": 0.03,
"cacheRead": 0,
"cacheWrite": 0
},
@@ -70856,9 +71153,9 @@
"image"
],
"cost": {
"input": 0.66,
"output": 3.41,
"cacheRead": 0.144,
"input": 0.95,
"output": 4,
"cacheRead": 0.16,
"cacheWrite": 0
},
"contextWindow": 262144,
@@ -70914,9 +71211,9 @@
"image"
],
"cost": {
"input": 0.719,
"output": 3.49,
"cacheRead": 0.149,
"input": 0.75,
"output": 3.5,
"cacheRead": 0.16,
"cacheWrite": 0
},
"contextWindow": 262144,
@@ -70931,6 +71228,35 @@
]
}
},
"moonshotai/kimi-k3": {
"id": "moonshotai/kimi-k3",
"name": "Kimi K3",
"api": "openrouter",
"provider": "openrouter",
"baseUrl": "https://openrouter.ai/api/v1",
"reasoning": true,
"input": [
"text",
"image"
],
"cost": {
"input": 3,
"output": 15,
"cacheRead": 0.3,
"cacheWrite": 0
},
"contextWindow": 1048576,
"maxTokens": 131072,
"thinking": {
"mode": "effort",
"efforts": [
"minimal",
"low",
"medium",
"high"
]
}
},
"nex-agi/deepseek-v3.1-nex-n1": {
"id": "nex-agi/deepseek-v3.1-nex-n1",
"name": "DeepSeek V3.1 Nex N1",
@@ -73693,13 +74019,13 @@
"text"
],
"cost": {
"input": 0.12,
"input": 0.09999999999999999,
"output": 0.24,
"cacheRead": 0,
"cacheWrite": 0
},
"contextWindow": 131702,
"maxTokens": 16384,
"maxTokens": 40960,
"thinking": {
"mode": "effort",
"efforts": [
@@ -74042,7 +74368,7 @@
"text"
],
"cost": {
"input": 0.12,
"input": 0.11,
"output": 0.7999999999999999,
"cacheRead": 0.07,
"cacheWrite": 0
@@ -74491,8 +74817,8 @@
"image"
],
"cost": {
"input": 0.44999999999999996,
"output": 3,
"input": 0.39,
"output": 2.34,
"cacheRead": 0.22499999999999998,
"cacheWrite": 0
},
@@ -76136,13 +76462,13 @@
"text"
],
"cost": {
"input": 0.060500000000000005,
"input": 0.06,
"output": 0.39999999999999997,
"cacheRead": 0.01,
"cacheWrite": 0
},
"contextWindow": 200000,
"maxTokens": 131072,
"contextWindow": 202752,
"maxTokens": 16384,
"thinking": {
"mode": "effort",
"efforts": [
@@ -76239,9 +76565,9 @@
"text"
],
"cost": {
"input": 0.9786,
"output": 3.0755999999999997,
"cacheRead": 0.18174,
"input": 1.2166,
"output": 3.8236000000000003,
"cacheRead": 0.22594,
"cacheWrite": 0
},
"contextWindow": 1048576,
@@ -77555,38 +77881,6 @@
"escapeBuiltinToolNames": true
}
},
"umans-deepseek-v4-pro-dspark": {
"id": "umans-deepseek-v4-pro-dspark",
"name": "Umans DeepSeek V4 Pro DSpark (experimental)",
"api": "anthropic-messages",
"provider": "umans",
"baseUrl": "https://api.code.umans.ai",
"reasoning": true,
"thinking": {
"mode": "budget",
"efforts": [
"minimal",
"low",
"medium",
"high",
"xhigh"
]
},
"input": [
"text"
],
"cost": {
"input": 0,
"output": 0,
"cacheRead": 0,
"cacheWrite": 0
},
"contextWindow": 393216,
"maxTokens": 131071,
"compat": {
"escapeBuiltinToolNames": true
}
},
"umans-flash": {
"id": "umans-flash",
"name": "Umans Flash",
@@ -79280,6 +79574,28 @@
"supportsUsageInStreaming": false
}
},
"inkling": {
"id": "inkling",
"name": "inkling",
"api": "openai-completions",
"provider": "venice",
"baseUrl": "https://api.venice.ai/api/v1",
"reasoning": false,
"input": [
"text"
],
"cost": {
"input": 0,
"output": 0,
"cacheRead": 0,
"cacheWrite": 0
},
"contextWindow": null,
"maxTokens": null,
"compat": {
"supportsUsageInStreaming": false
}
},
"kimi-k2-5": {
"id": "kimi-k2-5",
"name": "Kimi K2.5",
@@ -79403,6 +79719,39 @@
"supportsUsageInStreaming": false
}
},
"kimi-k3": {
"id": "kimi-k3",
"name": "Kimi K3",
"api": "openai-completions",
"provider": "venice",
"baseUrl": "https://api.venice.ai/api/v1",
"reasoning": true,
"input": [
"text",
"image"
],
"cost": {
"input": 0,
"output": 0,
"cacheRead": 0,
"cacheWrite": 0
},
"contextWindow": 1048576,
"maxTokens": 131072,
"thinking": {
"mode": "effort",
"efforts": [
"minimal",
"low",
"medium",
"high",
"xhigh"
]
},
"compat": {
"supportsUsageInStreaming": false
}
},
"llama-3.2-3b": {
"id": "llama-3.2-3b",
"name": "Llama 3.2 3B",
@@ -84313,6 +84662,36 @@
]
}
},
"moonshotai/kimi-k3": {
"id": "moonshotai/kimi-k3",
"name": "Kimi K3",
"api": "anthropic-messages",
"provider": "vercel-ai-gateway",
"baseUrl": "https://ai-gateway.vercel.sh",
"reasoning": true,
"input": [
"text",
"image"
],
"cost": {
"input": 3,
"output": 15,
"cacheRead": 0.3,
"cacheWrite": 0
},
"contextWindow": 1000000,
"maxTokens": 131072,
"thinking": {
"mode": "budget",
"efforts": [
"minimal",
"low",
"medium",
"high",
"xhigh"
]
}
},
"nvidia/nemotron-3-nano-30b-a3b": {
"id": "nvidia/nemotron-3-nano-30b-a3b",
"name": "Nemotron 3 Nano 30B A3B",
@@ -88988,7 +89367,7 @@
},
"glm-4.6": {
"id": "glm-4.6",
"name": "glm-4.6",
"name": "GLM-4.6",
"api": "anthropic-messages",
"provider": "zai",
"baseUrl": "https://api.z.ai/api/anthropic",
@@ -91702,6 +92081,66 @@
]
}
},
"moonshotai/kimi-k3": {
"id": "moonshotai/kimi-k3",
"name": "Kimi K3",
"api": "openai-completions",
"provider": "zenmux",
"baseUrl": "https://zenmux.ai/api/v1",
"reasoning": true,
"input": [
"text",
"image"
],
"cost": {
"input": 3,
"output": 15,
"cacheRead": 0.3,
"cacheWrite": 0
},
"contextWindow": 1048576,
"maxTokens": 131072,
"thinking": {
"mode": "effort",
"efforts": [
"minimal",
"low",
"medium",
"high",
"xhigh"
]
}
},
"moonshotai/kimi-k3-free": {
"id": "moonshotai/kimi-k3-free",
"name": "Kimi K3 (Free)",
"api": "openai-completions",
"provider": "zenmux",
"baseUrl": "https://zenmux.ai/api/v1",
"reasoning": true,
"input": [
"text",
"image"
],
"cost": {
"input": 0,
"output": 0,
"cacheRead": 0,
"cacheWrite": 0
},
"contextWindow": 1048576,
"maxTokens": 131072,
"thinking": {
"mode": "effort",
"efforts": [
"minimal",
"low",
"medium",
"high",
"xhigh"
]
}
},
"openai/chat-latest": {
"id": "openai/chat-latest",
"name": "Chat Latest (GPT-5.5 Instant)",
@@ -94538,7 +94977,7 @@
"zhipu-coding-plan": {
"glm-4.5": {
"id": "glm-4.5",
"name": "glm-4.5",
"name": "GLM-4.5",
"api": "openai-completions",
"provider": "zhipu-coding-plan",
"baseUrl": "https://open.bigmodel.cn/api/coding/paas/v4",
@@ -94599,7 +95038,7 @@
},
"glm-4.6": {
"id": "glm-4.6",
"name": "glm-4.6",
"name": "GLM-4.6",
"api": "openai-completions",
"provider": "zhipu-coding-plan",
"baseUrl": "https://open.bigmodel.cn/api/coding/paas/v4",
@@ -94852,4 +95291,4 @@
}
}
}
}
}
+61 -69
View File
@@ -2,80 +2,74 @@
## [Unreleased]
### Changed
- Bash command timeouts now render with a warning (yellow) border instead of an error (red) border, reflecting that the timeout ran its course rather than the command failed. `isError` remains `true` on the result so the model still knows the command did not complete normally. The `timedOut` flag is now propagated from the bash executor to distinguish timeouts from user aborts.
### Added
- Added native Warp CLI-agent events for rich session status, tool approvals, and completion notifications ([#5592](https://github.com/can1357/oh-my-pi/pull/5592) by [@metaphorics](https://github.com/metaphorics)).
- Added Codex (ChatGPT subscription) support to `generate_image`. The tool now resolves a connected `openai-codex` OAuth credential and drives OpenAI's hosted `image_generation` tool through the ChatGPT backend (`chatgpt.com/backend-api/codex/responses`, `chatgpt-account-id` header) **independent of the active chat model** — so image generation works on a ChatGPT/Codex subscription with no metered `OPENAI_API_KEY`, even when the active model is Claude/Gemini/etc. A new `providers.image: "openai-codex"` option forces it; `auto` now auto-detects a connected subscription (priority: active GPT image tool > Codex subscription > Antigravity > xAI > OpenRouter > Gemini), and the `openai` preference falls back to it when no `OPENAI_API_KEY`/active GPT model is present.
- Added an optional `provider` parameter to `generate_image` (`auto` | `openai` | `openai-codex` | `antigravity` | `xai` | `gemini` | `openrouter`) that overrides the `providers.image` setting **for a single request** — so "generate this using gemini / codex / xai" routes per-call without changing the global setting. Absent → the `providers.image` setting applies, unchanged; the named provider uses the same resolution semantics (falls back to auto-detect if it has no credentials). File: `tools/image-gen.ts` (`imageProviderSchema`, `findImageApiKey` `preference` arg).
- Added OpenTelemetry log and metric export alongside the existing trace export. When `OTEL_EXPORTER_OTLP_LOGS_ENDPOINT` (or the shared `OTEL_EXPORTER_OTLP_ENDPOINT`) is set, `omp` registers a `LoggerProvider` and forwards every centralized-logger event as an OTLP log record (severity + attributes + active span context for log↔trace correlation, min level via `OTEL_LOG_LEVEL`, plus a structured `agent run completed` summary event). When `OTEL_EXPORTER_OTLP_METRICS_ENDPOINT` (or the shared endpoint) is set, it registers a `MeterProvider` with a `PeriodicExportingMetricReader` and records GenAI-semconv `gen_ai.client.token.usage` plus `pi.omp.agent.*` counters/histograms (runs, steps, chat/tool calls by name+status+finish reason, latencies, estimated cost, errors) from the agent run summary and per-chat usage hooks. Each signal honors its own `OTEL_*_EXPORTER=none` kill switch, the global `OTEL_SDK_DISABLED`, and declines non-`http/protobuf` protocols independently ([#4604](https://github.com/can1357/oh-my-pi/issues/4604)).
- `retry.fallbackChains` wildcards now support id-prefixed targets and keys: a chain entry like `"openrouter/google/*"` re-prefixes the failing model's bare id (`google-antigravity/gemini-x` → `openrouter/google/gemini-x`), a plain `"provider/*"` entry falling back *from* an aggregator strips the vendor prefix when the target provider only knows the bare id (`openrouter/google/x` → `google-vertex/x`), and an id-prefixed key (`"openrouter/google/*"`) scopes a chain to that provider's ids under the prefix.
- Added native Warp CLI-agent events for rich session status, tool approvals, and completion notifications.
- Added support for ChatGPT/Codex subscriptions in the `generate_image` tool, allowing image generation without a metered `OPENAI_API_KEY` even when using other active models.
- Added an optional `provider` parameter to `generate_image` to override the global `providers.image` setting for a single request.
- Added OpenTelemetry log and metric export support alongside existing trace exports, enabling forwarding of centralized-logger events and GenAI-semconv metrics when configured.
- Enhanced `retry.fallbackChains` wildcards to support id-prefixed targets and keys, allowing more flexible model fallback routing across different providers.
- Added an opt-in per-project model role storage mode with global fallback from the model selector.
### Changed
- Made the hashline seen-line guard opt-in and off by default (see `edit.enforceSeenLines`), and stopped excluding column-clipped (>512-char) lines from a snapshot's seen set: a displayed line now counts as seen even when its display was column-truncated, so single-line edits on long lines found via `read`/`grep` apply without a separate full-width re-read.
- Changed the default `astGrep.enabled` setting to `false`
- Batched todo operations with real tool calls to prevent solo todo turns and extra round trips
- Changed every bundled TTSR rule to warn without interrupting generation.
- Renamed the system prompt's project-context section wrapper from `<context>` to `<repo-rules>` to stop it colliding with the `task` tool's `context` parameter under in-band XML tool dialects: models were closing `<parameter name="context">` with a stray `</context>` (primed by the ambient section tag) and emitting sibling params as bare `<tasks>` elements, so `tasks` arrived missing.
- Rendered `read xd://` calls in the compact grouped read view instead of a full tool-execution card; other internal URLs (`skill://`, `agent://`, …) still render full so their resolved content stays visible.
- Changed Bash command timeouts to render with a warning (yellow) border instead of an error (red) border, while still indicating to the model that the command did not complete normally.
- Made the hashline seen-line guard opt-in and off by default via `edit.enforceSeenLines`, and improved handling of column-clipped lines so single-line edits on long lines apply without a full-width re-read.
- Changed the default `astGrep.enabled` setting to `false`.
- Batched todo operations with real tool calls to prevent solo todo turns and extra round trips.
- Changed bundled TTSR rules to warn without interrupting generation.
- Renamed the system prompt's project-context section wrapper from `<context>` to `<repo-rules>` to prevent collisions with the `task` tool's `context` parameter.
- Rendered `read xd://` calls in a compact grouped read view instead of a full tool-execution card.
### Fixed
- Fixed linked legacy pi extensions failing to load when they import `DefaultPackageManager` or linkedom: the coding-agent compatibility shim now enumerates OMP extension paths with plugin metadata, and extension-graph CommonJS modules load through synchronous default-export bridges with linkedom's bundled canvas fallback. ([#5658](https://github.com/can1357/oh-my-pi/issues/5658))
- Fixed the advisor retrying terminal, non-retriable provider failures (e.g. blocked prompts) three times before giving up; such failures now drop the bounded batch after a single attempt while transient failures keep the 3-attempt retry path ([#5468](https://github.com/can1357/oh-my-pi/pull/5468)).
- Fixed reassigning the `plan` role model mid-planning not taking effect on the active planning turn; the change now applies at the next turn boundary instead of only the next plan-mode entry ([#5657](https://github.com/can1357/oh-my-pi/issues/5657)).
- Added managed `ctx.setInterval` / `ctx.setTimeout` / `ctx.clearTimer` helpers on the extension context. Callbacks scheduled through them run with the same isolation as handler dispatch — a throw or rejected promise is logged and reported through the extension error channel instead of escaping as a process-fatal `uncaughtException` — and every outstanding timer is `unref`'d and cleared automatically on `session_shutdown` ([#5664](https://github.com/can1357/oh-my-pi/issues/5664)).
- Fixed an extension's self-scheduled `setInterval`/`setTimeout` callback throwing being able to tear down the whole session. Such callbacks ran outside the handler-dispatch try/catch, surfaced as a process-level `uncaughtException`, and the global postmortem handler treated them as fatal; extension authors now have sanctioned managed timers (see Added), and the constraint is documented in `docs/extensions.md` / `docs/skills/authoring-extensions.md` ([#5664](https://github.com/can1357/oh-my-pi/issues/5664)).
- Fixed `/quit` and `/exit` leaving failed or stalled automatic title-generation requests alive during session teardown; disposal now aborts both online provider and local tiny-model title requests ([#5666](https://github.com/can1357/oh-my-pi/issues/5666)).
- Fixed `startup.quiet` still rendering the `xdev: xd://: mounted …` status line when MCP tools connect; quiet startup now suppresses only the user-visible mount notice while retaining the hidden model-facing device update ([#5670](https://github.com/can1357/oh-my-pi/issues/5670)).
- Fixed command error in `hub` tool with a non-POSIX shell ([#5682](https://github.com/can1357/oh-my-pi/pull/5682))
- Fixed xdev-routed checkpoint and rewind writes not tracking checkpoint state and leaving rewinding results in rebuilt provider and session context.
- Fixed the built-in advisor silently doing nothing when its model routes through the `cursor` provider: the advisor runs in its own `Agent` that was constructed without `cursorExecHandlers`, so on Cursor — where every tool executes server-side and is dispatched back through the client's exec handlers — each advisor tool call (including the MCP `advise` tool) came back `toolNotFound`/"tool not available" and no advice was ever routed. The advisor `Agent` now gets a Cursor exec bridge scoped to its own granted tool set, mirroring the primary agent. The bridge's native `delete` frame is gated so a read-only advisor cannot delete workspace files it was never granted a mutating tool for ([#5680](https://github.com/can1357/oh-my-pi/issues/5680)).
- Fixed the fullscreen plan-review overlay staying visible until the approved execution turn finished, so after picking "Approve and keep context" (or any approve option) work proceeded underneath while the operator was stuck on the plan-review screen. The overlay is now hidden once execution begins — after the async transcript rebuild, before the blocking synthetic prompt is dispatched — instead of only after the whole turn returns ([#5688](https://github.com/can1357/oh-my-pi/issues/5688)).
- Fixed MCP tools repeatedly unmounting and remounting mid-session when server names have overlapping sanitized prefixes (e.g. `atlassian` alongside an imported `atlassian:atlassian`), and stale tools remaining registered after disconnecting a server with special characters in its name.
- Fixed the `/usage show` `in use by this session:` marker showing only the login email, so two same-email Anthropic credentials in different orgs (a Team seat and a personal Max plan) were indistinguishable. The marker now suffixes the active organization (`email (OrgName)`) via a shared `formatActiveAccountLabel`, matching the account list and login-success surfaces ([#5691](https://github.com/can1357/oh-my-pi/issues/5691)).
- Fixed Windows stdio MCP servers launched through `.cmd`/`.bat` shims failing with `Transport closed`; the launch now builds a `cmd.exe /d /e:ON /v:OFF /c` command line escaped for `cmd.exe`'s parser and spawned with `windowsVerbatimArguments`, so the resolved command path and arguments (including `%VAR%`, quotes, and shell metacharacters) reach the server intact and cannot inject commands (BatBadBut / CVE-2024-24576) ([#5696](https://github.com/can1357/oh-my-pi/issues/5696)).
- Fixed the TUI usage panel truncating organization suffixes from same-email account labels even when the terminal has enough width ([#5701](https://github.com/can1357/oh-my-pi/issues/5701)).
- Fixed a startup crash on Windows when running from a drive root (e.g. `R:\`): `fs.realpath` throws `EISDIR` there, but `canonicalProjectDir` in `launch/presence.ts` and `launch/client.ts` only recovered `ENOENT`. It now also falls back to `path.resolve()` on `EISDIR` ([#5708](https://github.com/can1357/oh-my-pi/issues/5708) by [@ve3xone](https://github.com/ve3xone)).
- Fixed unknown `__omp_worker_*` CLI selectors exiting 0 with empty output instead of erroring; an unrecognized worker-host selector now writes `Error: unknown worker selector: …` to stderr and exits nonzero, so a stale or mistyped selector can no longer look healthy to a parent process or install smoke path ([#5712](https://github.com/can1357/oh-my-pi/issues/5712)).
- Fixed Plan Review capturing mouse drags as pointer events, preventing native terminal text selection ([#5711](https://github.com/can1357/oh-my-pi/issues/5711)).
- Fixed orphaned TUI processes with revoked terminal descriptors remaining alive after a fatal error and amplifying shared log-rotation races into runaway memory, file-descriptor, swap, and disk consumption ([#5716](https://github.com/can1357/oh-my-pi/issues/5716)).
- Fixed approved-plan execution looping through filesystem searches when a model rewrites the required `local://<slug>-plan.md` read as a same-basename working-directory path; a missing cwd-root alias now recovers the active session-local plan while preserving any real working-tree file ([#5704](https://github.com/can1357/oh-my-pi/issues/5704)).
- Fixed Ask dialogs immediately accepting their highlighted single-select answer when they appear while the user is typing a space in the prompt editor ([#5717](https://github.com/can1357/oh-my-pi/issues/5717)).
- Stopped post-compaction auto-continue from opening another primary turn after a terminal text answer with no queued work, and moved automatic auto-learn capture into an abortable private agent with only `manage_skill` and `learn` tools ([#5715](https://github.com/can1357/oh-my-pi/issues/5715)).
- Fixed the `write` approval gate misclassifying `xd://` device writes as `exec` when the mounted tool declared a function-valued (argument-dependent) `approval`: the gate discarded the function and never decoded the device JSON payload, so read/write device operations prompted in non-yolo modes their approval mode permits. It now parses valid object payloads and evaluates the mounted tool's normal approval decision, while malformed JSON, non-object payloads, and unknown devices still fall back to `exec` and prompt ([#5727](https://github.com/can1357/oh-my-pi/issues/5727)).
- Fixed custom LSP servers such as `roslyn-language-server` crashing after initialization when they request unconfigured `workspace/configuration` sections; missing settings now receive the spec-required `null` instead of `{}` ([#5745](https://github.com/can1357/oh-my-pi/issues/5745)).
- Fixed late user-initiated bash results and minimized-output artifacts being recorded in whichever session or branch was active when execution finished; bash now retains its originating transcript across `new_session`/`switch_session`/`branch`/tree navigation, and an intentionally dropped session stays deleted instead of being recreated by a straggling result ([#5743](https://github.com/can1357/oh-my-pi/issues/5743)).
- Fixed Claude Code marketplace plugins with `scope: "local"` leaking skills, hooks, tools, commands, and MCP servers into unrelated projects ([#5750](https://github.com/can1357/oh-my-pi/issues/5750)).
- Fixed headless `omp -p` waiting indefinitely after a completed turn when final mnemopi consolidation stalls; print mode now applies the same bounded consolidation shutdown budget as interactive exit and reaps the embed worker ([#5753](https://github.com/can1357/oh-my-pi/issues/5753)).
- Fixed explicit-tool sessions bypassing `xd://` presentation for ambient discoverable custom and MCP tools, which sent their schemas top-level and could exceed provider tool limits or trigger schema-compatibility errors.
- Fixed `providers.webSearch: kimi` sending a Moonshot Open Platform credential (`MOONSHOT_API_KEY` / stored `moonshot` auth) to the Kimi Code search endpoint (`api.kimi.com/coding/v1/search`), which rejects it with `401` and silently falls back to another provider. Kimi web search now resolves and advertises Kimi Code credentials only — a Kimi Code Console key via `KIMI_SEARCH_API_KEY` / `MOONSHOT_SEARCH_API_KEY` or `omp /login kimi-code` ([#5762](https://github.com/can1357/oh-my-pi/issues/5762)).
- Fixed extension/SDK/RPC `registerTool` demoting essential built-ins (`read`/`write`/`bash`/`edit`/`glob`/…) to `discoverable` when a re-registration omitted `loadMode`, which — with `tools.xdev` on — unmounted them from the top-level schema and broke the `xd://` transport (`read xd://`/`write xd://`), leaving the model with no callable coding essentials. Omitted `loadMode` now defaults to `"essential"` for known essential built-in names at every adapter boundary, and `read`/`write` (the transport itself) are never mounted under xdev regardless of `loadMode` ([#5764](https://github.com/can1357/oh-my-pi/issues/5764)).
- Fixed the advisor skipping the next real user instruction after auto-learn accepted and pruned a terminal empty assistant stop; advisor transcript cursors now detect rewritten prefixes and re-prime before slicing the next update ([#5731](https://github.com/can1357/oh-my-pi/issues/5731)).
- Fixed built-in advisors retrying a quota- or rate-limited provider until becoming unavailable instead of applying the matching `retry.fallbackChains` model chain; advisor fallbacks now emit the same applied and succeeded lifecycle events as primary-agent fallbacks ([#5740](https://github.com/can1357/oh-my-pi/issues/5740)).
- Made the model selector status messages use the role tag (`SMOL`, `SLOW`) instead of the display name (`Fast`, `Thinking`), matching the rest of the TUI and CLI/env role terminology ([#5585](https://github.com/can1357/oh-my-pi/issues/5585)).
- Fixed Cursor models receiving only top-level tools by forwarding mounted `xd://` devices, including user-configured MCP servers, through Cursor's request-context MCP catalog and execution bridge ([#5650](https://github.com/can1357/oh-my-pi/issues/5650)).
- Fixed Windows bash crashes when a piped command times out while flushing output; explicit-timeout watchdogs now wait for bounded native teardown instead of returning mid-drain. ([#5316](https://github.com/can1357/oh-my-pi/issues/5316))
- Fixed a race where hub/IRC `send` and `ensureLive` could hand out or inject into a subagent session mid-`park` dispose: park now detaches and flips status to `parked` before `session.dispose()`, concurrent `ensureLive` cancels a pre-detach park or waits then revives, and IRC delivery always gates through `ensureLive` so receipts/unread counts stay truthful ([#5633](https://github.com/can1357/oh-my-pi/issues/5633)).
- Migrated legacy `dev.autoqa.consent` → `dev.autoqaConsent` and `todo.reminders.max` → `todo.remindersMax` on settings load so pre-v17 nested or quoted-dotted config no longer leaves the parent path as an object (which made `dev.autoqa` truthy and enabled Auto QA, and discarded the reminder limit). Explicit new keys win, a separately configured parent boolean is preserved, an irrecoverable object parent falls back to the schema default, and only the new keys persist on save ([#5632](https://github.com/can1357/oh-my-pi/issues/5632)).
- Fixed all keyboard input dying after the first keypress when a `~/.claude/tools` (or `.omp/tools`) module attaches a stdin consumer at import time — e.g. an MCP `StdioServerTransport` constructed at module top level, or a bare `process.stdin.resume()`. The custom-tool/extension/hook/plugin loader guard now snapshots and restores `process.stdin` (listeners, paused state, raw mode) around third-party module evaluation, so a hijacked stdin reader can no longer starve the TUI's own listener ([#5618](https://github.com/can1357/oh-my-pi/issues/5618)).
- Fixed the ask tool's "Other" custom-input dialog rendering the title, options, and hint one column to the right of the `> ` input gutter; the prompt-style editor chrome now aligns to column 0 ([#5313](https://github.com/can1357/oh-my-pi/issues/5313))
- Fixed advisor context maintenance undercounting the provider context: the compaction decision now anchors on the advisor's provider-reported context usage (cached input + generated output) floored by a full local estimate that includes the advisor system prompt and tool schemas, rejects stale provider usage retained across advisor compaction, and recovers a provider overflow by clearing only the advisor's own context at the current primary cursor — retrying the bounded failing batch once against a fresh context without replaying old primary history and keeping later updates eligible ([#5282](https://github.com/can1357/oh-my-pi/issues/5282))
- Fixed RPC mode (`--mode rpc`) crashing the whole process with an uncaught `SyntaxError: Failed to parse JSONL` on any non-JSON stdin line. Malformed lines are now reported via a `Failed to parse command` error frame and the frame loop keeps running. ([#5194](https://github.com/can1357/oh-my-pi/issues/5194))
### Removed
- Fixed `/clear` autocomplete selecting `/autoresearch`; `/clear` now starts a new session as an alias for `/new` ([#5349](https://github.com/can1357/oh-my-pi/issues/5349))
- Fixed `/review` aborting entirely when GitHub rejects a pull request's aggregate diff with HTTP 406 for exceeding the 20,000-line limit: `gh pr diff` now falls back to the paginated per-file endpoint (`/repos/{owner}/{repo}/pulls/{n}/files`) and reassembles a synthetic unified diff, keeping files with omitted (binary/too-large) patches visible with an explicit marker ([#5350](https://github.com/can1357/oh-my-pi/issues/5350))
- Fixed `/q` + Enter running `/queue` instead of `/quit`: the newer `/queue` command is registered before `/quit`, and the editor's sync slash-completion applies the first same-prefix match on Enter, so `/q` shadowed to `/queue`. Added an explicit `q` alias to `/quit` (exact matches outrank prefix matches) so `/q` deterministically quits ([#5335](https://github.com/can1357/oh-my-pi/issues/5335))
- Fixed Ctrl+L (`app.display.reset`) not refreshing the dark/light theme on terminals without an end-to-end DEC Mode 2031 notification path (e.g. iTerm2 under tmux): the explicit reset gesture now issues one bounded OSC 11 background re-query before repainting, so a mid-session appearance switch is picked up without restarting. No timers or periodic polling are reintroduced ([#5352](https://github.com/can1357/oh-my-pi/issues/5352))
- Added an opt-in per-project model role storage mode with global fallback from the model selector.
### Fixed
- Local llama.cpp Qwen-family models (including the Qwen3.6-based PrismLM Ternary Bonsai GGUFs) now honor `--thinking off`. Discovery routes them through the chat-completions API with the `qwen-template-false` disable dialect, `qwenPreserveThinking`, and a `/v1` base URL (models kept on a custom transport such as `pi-native` retain their gateway URL so the suffix is not doubled). The upgrade is re-applied as the outermost step after discovery merges, provider `baseUrl` overrides, and cache fallbacks, so a configured native-root base URL or a pre-fix cached row cannot leave the model on the old `openai-responses` / `reasoning: false` spec.
- Fixed loading issues for linked legacy extensions importing `DefaultPackageManager` or `linkedom`.
- Fixed the advisor retrying terminal, non-retriable provider failures (e.g., blocked prompts), ensuring they fail immediately while transient failures still retry.
- Fixed an issue where reassigning the `plan` role model mid-planning did not take effect until the next plan-mode entry; it now applies at the next turn boundary.
- Added managed timer helpers (`ctx.setInterval`, `ctx.setTimeout`, `ctx.clearTimer`) to the extension context to prevent self-scheduled callbacks from throwing uncaught exceptions and crashing the session.
- Fixed `/quit` and `/exit` leaving stalled automatic title-generation requests alive during session teardown.
- Fixed `startup.quiet` still rendering the `xdev: xd://: mounted` status line when MCP tools connect.
- Fixed command errors in the `hub` tool when using a non-POSIX shell.
- Fixed xdev-routed checkpoint and rewind writes not tracking checkpoint state.
- Fixed the built-in advisor silently failing when its model routes through the Cursor provider by adding a Cursor execution bridge scoped to its granted tool set.
- Fixed the fullscreen plan-review overlay staying visible until the approved execution turn finished; it is now hidden as soon as execution begins.
- Fixed MCP tools repeatedly unmounting and remounting mid-session due to overlapping sanitized prefixes, and resolved stale tools remaining registered after disconnecting a server with special characters.
- Fixed the `/usage show` marker and TUI usage panel to display and preserve the active organization suffix (`email (OrgName)`) to distinguish between multiple credentials with the same email.
- Fixed Windows stdio MCP servers launched through `.cmd` or `.bat` shims failing with `Transport closed` by properly escaping arguments and spawning with `windowsVerbatimArguments`.
- Fixed a startup crash on Windows when running from a drive root (e.g., `R:\`).
- Fixed unknown `__omp_worker_*` CLI selectors exiting with code 0 instead of throwing an error.
- Fixed Plan Review capturing mouse drags as pointer events, which prevented native terminal text selection.
- Fixed orphaned TUI processes remaining alive after a fatal error and causing high resource consumption.
- Fixed approved-plan execution looping through filesystem searches when a model rewrites the required plan read path.
- Fixed Ask dialogs immediately accepting highlighted answers when they appear while the user is typing a space.
- Stopped post-compaction auto-continue from opening another primary turn after a terminal text answer with no queued work.
- Fixed the `write` approval gate misclassifying `xd://` device writes as `exec` when the mounted tool declared a function-valued approval.
- Fixed custom LSP servers (such as `roslyn-language-server`) crashing when requesting unconfigured workspace configuration sections.
- Fixed late user-initiated bash results being recorded in whichever session or branch was active when execution finished; they now retain their originating transcript.
- Fixed Claude Code marketplace plugins with `scope: "local"` leaking skills, hooks, tools, commands, and MCP servers into unrelated projects.
- Fixed headless `omp -p` waiting indefinitely after a completed turn when final consolidation stalls.
- Fixed explicit-tool sessions bypassing `xd://` presentation for ambient discoverable custom and MCP tools.
- Fixed `providers.webSearch: kimi` incorrectly sending Moonshot credentials instead of Kimi Code credentials.
- Fixed `registerTool` demoting essential built-in tools to `discoverable` when a re-registration omitted `loadMode`.
- Fixed the advisor skipping the next user instruction after auto-learn accepted and pruned a terminal empty assistant stop.
- Fixed built-in advisors retrying quota- or rate-limited providers instead of applying the matching `retry.fallbackChains` model chain.
- Updated model selector status messages to use role tags (`SMOL`, `SLOW`) instead of display names (`Fast`, `Thinking`) for consistency.
- Fixed Cursor models receiving only top-level tools by forwarding mounted `xd://` devices through Cursor's request-context MCP catalog.
- Fixed Windows bash crashes when a piped command times out while flushing output.
- Fixed a race condition where hub/IRC `send` and `ensureLive` could inject into a subagent session during disposal.
- Migrated legacy nested/dotted configuration keys (`dev.autoqa.consent` and `todo.reminders.max`) to flat keys (`dev.autoqaConsent` and `todo.remindersMax`) on settings load.
- Fixed keyboard input dying after the first keypress when a custom tool module attaches a stdin consumer at import time.
- Fixed the alignment of the ask tool's custom-input dialog to start at column 0.
- Fixed advisor context maintenance undercounting the provider context by anchoring compaction decisions on provider-reported context usage.
- Fixed RPC mode (`--mode rpc`) crashing on non-JSON stdin lines; malformed lines are now reported as errors while the frame loop continues.
- Fixed local llama.cpp Qwen-family models not honoring the `--thinking off` flag.
- Documented the `ultrathink`, `orchestrate`, and `workflowz` magic keywords, including their effects, matching rules, and settings.
- Fixed the Bash tool hanging when in-process commands read process substitution operands.
- Fixed `/share` and `/export` web views rendering inline Markdown inside list items as literal text.
- Fixed `/clear` autocomplete selecting `/autoresearch` and updated `/clear` to start a new session as an alias for `/new`.
- Fixed `/review` aborting entirely when GitHub rejects a pull request's aggregate diff for exceeding the line limit by falling back to the paginated per-file endpoint.
- Fixed `/q` + Enter running `/queue` instead of `/quit` by adding an explicit `q` alias to `/quit`.
- Fixed Ctrl+L (`app.display.reset`) not refreshing the dark/light theme on certain terminals by issuing a background re-query before repainting.
## [17.0.1] - 2026-07-16
@@ -108,12 +102,10 @@
- Fixed xAI web search bypassing configured `xai` / `xai-oauth` proxy endpoints and headers, while preventing official OAuth tokens from being sent to custom endpoints ([#5599](https://github.com/can1357/oh-my-pi/issues/5599)).
- Fixed `models.yml` rejecting the Anthropic `compat.supportsEagerToolInputStreaming` override for custom endpoints ([#5572](https://github.com/can1357/oh-my-pi/issues/5572)).
- Fixed long streamed table responses duplicating in terminal scrollback when later rows widened an earlier column.
- Documented the `ultrathink`, `orchestrate`, and `workflowz` magic keywords, including their effects, matching rules, and settings ([#5590](https://github.com/can1357/oh-my-pi/issues/5590)).
- Fixed Bash internal URLs remaining unresolved when used as unquoted arguments inside command substitutions ([#5535](https://github.com/can1357/oh-my-pi/issues/5535)).
- Fixed the built-in `fd` printing `fd: Broken pipe (os error 32)` when a downstream pipeline reader exited early (e.g. `fd … | head`); it now exits silently with 141 (128+SIGPIPE), matching real fd.
- Fixed prewalk repeatedly continuing after a bash-only task such as `commit` had already completed ([#5551](https://github.com/can1357/oh-my-pi/issues/5551)).
- Fixed the Bash tool hanging when in-process commands read process substitution operands such as `<(cmd)` ([#5557](https://github.com/can1357/oh-my-pi/issues/5557)).
- Fixed `/share` and `/export` web views rendering inline Markdown inside list items as literal text ([#5567](https://github.com/can1357/oh-my-pi/issues/5567)).
### Added
- Fixed the Codex `config.toml` MCP importer dropping `cwd` and leaving relative `command` values unrooted, which broke the bundled Codex Computer Use server (`ENOENT` on spawn); relative `command`/`cwd` now resolve against the Codex config directory like the claude-plugins/omp-plugins providers ([#5561](https://github.com/can1357/oh-my-pi/issues/5561)).
+2 -2
View File
@@ -4,8 +4,8 @@
### Fixed
- Fixed `uv run --extra <package> pytest ...` bypassing native pytest minimization because the wrapper parser mistook the `--extra` value for the executable.
- Fixed timed-out shell pipelines cancelling their output reader while the final stage was still flushing, which dropped captured output and could terminate Windows hosts during teardown. ([#5316](https://github.com/can1357/oh-my-pi/issues/5316))
- Fixed an issue where running `uv run --extra <package> pytest` bypassed native pytest minimization due to a wrapper parsing error.
- Fixed a bug where timed-out shell pipelines dropped captured output and could cause Windows hosts to terminate during teardown. (#5316)
## [17.0.1] - 2026-07-16
+1 -1
View File
@@ -4,7 +4,7 @@
### Fixed
- Recent Errors now honors the selected dashboard time range before returning the newest 50 failures ([#5282](https://github.com/can1357/oh-my-pi/issues/5282))
- Fixed the Recent Errors list to honor the selected dashboard time range before returning the newest 50 failures.
## [16.4.7] - 2026-07-12
+5 -5
View File
@@ -4,14 +4,14 @@
### Added
- Added a fullscreen overlay mouse-tracking opt-out so selection-first dialogs can preserve native terminal text selection ([#5711](https://github.com/can1357/oh-my-pi/issues/5711)).
- Added an optional `Terminal.refreshAppearance()` that issues a single bounded OSC 11 background re-query through the existing query/DA1 pipeline, letting consumers refresh the detected dark/light appearance on an explicit user gesture without reintroducing periodic polling ([#5352](https://github.com/can1357/oh-my-pi/issues/5352))
- Added a fullscreen overlay mouse-tracking opt-out to allow selection-first dialogs to preserve native terminal text selection.
- Added `Terminal.refreshAppearance()` to allow consumers to manually trigger a refresh of the detected dark/light terminal appearance without periodic polling.
### Fixed
- Fixed Enter accepting a mid-prompt `/skill:<name>` autocomplete from submitting and clearing the draft; acceptance now inserts the skill token and leaves the prompt open ([#4773](https://github.com/can1357/oh-my-pi/issues/4773)).
- Fixed Markdown rendering turning local file paths into HTTP links when a `www.` or `http(s)://`/`ftp://` sequence was glued to a preceding character (e.g. `~/meta/www.share/blog/index.dj`); extended autolinks now require a valid GFM left boundary (start of line, whitespace, or one of `*_~(`) ([#5652](https://github.com/can1357/oh-my-pi/issues/5652)).
- Restored the alternate-screen borrow for non-multiplexer resize drag frames: v17.0.1 rewrote the normal buffer in place per SIGWINCH, letting the terminal's own width reflow push wrapped fragments into native scrollback mid-drag. Throwaway drag frames paint on the alt buffer again and the settled authoritative replay fuses the buffer exit into its destructive paint, keeping the [#5319](https://github.com/can1357/oh-my-pi/issues/5319) overlay-exit flicker fix intact.
- Fixed an issue where pressing Enter to accept a mid-prompt `/skill:<name>` autocomplete would submit and clear the draft; it now correctly inserts the skill token and leaves the prompt open.
- Fixed Markdown rendering incorrectly turning local file paths containing `www.` or protocol sequences into HTTP links by requiring a valid GFM left boundary for autolinks.
- Fixed terminal resize behavior by restoring alternate-screen rendering during drag frames, preventing wrapped fragments from polluting native scrollback while preserving the overlay-exit flicker fix.
## [17.0.1] - 2026-07-16
+8 -3
View File
@@ -4,11 +4,16 @@
### Added
- Added a structured log sink API to the centralized logger (`registerLogSink`, `LogEvent`, `LogLevel`) so out-of-band consumers (e.g. OpenTelemetry log export) receive every `error`/`warn`/`info`/`debug` event after the local transport path runs, without disturbing existing file/console logging ([#4604](https://github.com/can1357/oh-my-pi/issues/4604)).
- Added a structured log sink API (`registerLogSink`, `LogEvent`, `LogLevel`) to the centralized logger, enabling out-of-band consumers (such as OpenTelemetry) to receive log events without affecting local file or console logging.
### Changed
- Bounded default `ptree.ChildProcess` stderr retention to a 32 KiB tail to prevent memory leaks in long-lived subprocesses. Full stderr capture must now be explicitly requested at spawn time using `{ stderr: "full" }` on `spawn` or `exec`.
### Fixed
- Fixed fatal cleanup failing to reach `process.exit()` when terminal stderr is revoked, and isolated rotating log files/audit state per process to prevent concurrent OMP instances from racing compression and rotation ([#5716](https://github.com/can1357/oh-my-pi/issues/5716)).
- Bounded default `ptree.ChildProcess` stderr retention to the existing 32 KiB tail instead of retaining every raw chunk; long-lived subprocesses (LSP/DAP/RPC) no longer grow OMP memory with their stderr volume. Full capture must now be selected at spawn time via `spawn(cmd, { stderr: "full" })` / `exec(cmd, { stderr: "full" })`, and a retroactive `wait({ stderr: "full" })` on a default child throws instead of returning truncated data ([#5759](https://github.com/can1357/oh-my-pi/issues/5759)).
- Fixed fatal cleanup failing to reach `process.exit()` when terminal stderr is revoked.
- Isolated rotating log files and audit state per process to prevent concurrent instances from racing during compression and rotation.
## [17.0.1] - 2026-07-16