Repository navigation
fix(coding-agent): resume after context-limited length stops - #7540
Conversation
Treat length stops as context overflow when prompt usage is within 1% of Pi's configured context window. Include cache-write tokens in that usage and allow non-zero output because OpenAI may emit reasoning tokens before returning an incomplete response. After compaction, remove any retryable error or truncated-length assistant message restored from persisted session history so the interrupted agent turn can continue. This is specifically for handling this case for openai models: https://developers.openai.com/api/docs/guides/reasoning > If the generated tokens reach the context window limit or the max_output_tokens value you’ve set, you’ll receive a response with a status of incomplete and incomplete_details with reason set to max_output_tokens. This might occur before any visible output tokens are produced, meaning you could incur costs for input and reasoning tokens without receiving a visible response. This detection currently assumes the reported prompt usage is within 1% of the context window configured in Pi. Its reliability therefore depends on Pi's model contextWindow metadata matching the provider's effective limit. Maybe we should consider treating OpenAI incomplete responses as requiring compaction regardless of the local context-window estimate? fixes #7020
|
This PR is trying to recover from Pi treats output as part of the context window: Pi therefore sends: Genuine output limitIf this returns Context-limited outputIf this returns The PR currently guesses that this happened when the prompt is at least 99% of the context window. That misses the reported example: The request was already context-limited, but the 99% test returns false. A fixed 4,096-token reserve cannot be represented by one percentage for every context size. Proposed solutionAgentSession has the model limits and provider-reported prompt usage, so it can infer whether context constrained the request: function isContextLimitedLength(message: AssistantMessage, model: Model<Api>): boolean {
if (message.stopReason !== "length" || model.contextWindow <= 0) return false;
const promptTokens = message.usage.input + message.usage.cacheRead + message.usage.cacheWrite;
const availableOutput = Math.max(1, model.contextWindow - promptTokens - CONTEXT_SAFETY_TOKENS);
return availableOutput < model.maxTokens;
}Then: After compaction, the next request should normally no longer be context-limited. Keep the one-recovery guard anyway, but do not reset it when the assistant returns For OpenAI Responses, only Please test the reported 268,009/272,000 and 81,217/84,500 cases, a genuine output-limit This comment is AI-generated by |
|
Superseding my earlier proposal after checking the provider behavior, including a live Codex request. The core problem is that
For example: OpenAI output usage includes reasoning tokens, so this comparison does not depend on visible text. The important value is the original desired output limit, before Pi clamps it to the remaining context. For the normal coding-agent path this is function isRecoverableLength(message: AssistantMessage, desiredMaxOutput: number): boolean {
if (message.stopReason !== "length") return false;
// Reaching the caller/model's intended cap is a genuine output-limit stop.
if (desiredMaxOutput > 0 && message.usage.output >= desiredMaxOutput) return false;
// It stopped below the intended cap. Context pressure or a provider-side
// truncation is the likely cause, so make one compact-and-retry attempt.
return true;
}This works for both provider categories:
The AgentSession state machine should be:
For OpenAI Responses, inspect
This covers the reported 268,009/272,000, 81,217/84,500, nonzero-reasoning-output, cache-write, and no- This comment is AI-generated by |
Classify length stops by comparing provider-reported output usage with the model's intended output limit. Compact and retry once when generation ends below that limit, avoiding unreliable context-window estimates while preserving genuine max-output stops. Normalize OpenAI Responses incomplete reasons so only max_output_tokens is treated as a length stop. Preserve qualified provider reasons for diagnostics, surface other reasons as errors, and use neutral truncation wording in the TUI.
> [0.84.1] - 2026-08-07 > > ### New Features > > - Qwen Token Plan Individual — Use the built-in provider for models documented for Individual subscriptions. See API Keys > (https://github.com/earendil-works/pi/blob/v0.84.1/packages/coding-agent/docs/providers.md#api-keys). > - Authentication readiness checks — Use pi auth check to verify provider or model credentials, optionally emitting the resolved credential. > - Improved fullscreen interaction — Select words and paragraphs with multiple clicks and configure half-page transcript scrolling. See TUI Fullscreen Viewport > (https://github.com/earendil-works/pi/blob/v0.84.1/packages/coding-agent/docs/keybindings.md#tui-fullscreen-viewport). > - Terminating blocked tool calls — Extension tool_call handlers can stop all-terminating batches without another model call. See Tool Events > (https://github.com/earendil-works/pi/blob/v0.84.1/packages/coding-agent/docs/extensions.md#tool-events). > > ### Added > > - Added Qwen Token Plan Individual as a built-in provider with its documented subscription model catalog and the shared international QWEN_TOKEN_PLAN_API_KEY. See API Keys > (https://github.com/earendil-works/pi/blob/v0.84.1/packages/coding-agent/docs/providers.md#api-keys) (#7659 (earendil-works/pi#7659) by @arasovic (https://github.com/arasovic)). > - Added pi auth check provider/model auth preflight with optional credential output (#7152 (earendil-works/pi#7152)). > - Added terminate support to blocked extension tool_call events so all-terminating batches can skip the automatic follow-up model call. See Tool Events > (https://github.com/earendil-works/pi/blob/v0.84.1/packages/coding-agent/docs/extensions.md#tool-events) (#7715 (earendil-works/pi#7715) by @muyiyr (https://github.com/muyiyr)). > - Added inherited double-click word and whitespace selection, granularity-aware drag selection, and triple-click paragraph selection in fullscreen mode (#7725 (earendil-works/pi#7725), > #7733 (earendil-works/pi#7733) by @volsa (https://github.com/volsa)). > - Added inherited unbound half-page transcript scrolling actions for fullscreen mode. See TUI Fullscreen Viewport > (https://github.com/earendil-works/pi/blob/v0.84.1/packages/coding-agent/docs/keybindings.md#tui-fullscreen-viewport) (#7735 (earendil-works/pi#7735)). > > ### Changed > > - Softened the bash tool's PI_* environment guideline in an attempt to reduce unnecessary inspection commands (#7128 (earendil-works/pi#7128)). > - Reduced worst-case automatic terminal theme detection delay from 200 ms to 100 ms by probing color-scheme and background support concurrently. > > ### Fixed > > - Fixed Bun standalone binaries crashing on startup when the cwd contains a bunfig.toml with preload by compiling with --no-compile-autoload-bunfig (#7685 (earendil-works/pi#7685) by > @geril07 (https://github.com/geril07)). > - Fixed extension TUI method wrappers recursing indefinitely when delegating to the original method (#7731 (earendil-works/pi#7731)). > - Fixed right-click not pasting clipboard text in fullscreen mode on Windows. > - Fixed inherited Agent.reset() clearing transcript and runtime state during active runs; it now rejects until the agent is idle (#7717 (earendil-works/pi#7717) by @wesleyzhangwq > (https://github.com/wesleyzhangwq)). > - Fixed inherited LaTeX relation, multiplication, and named-operator spacing, and matrix composition with stacked fractions, operator limits, and adjacent matrices. > - Reduced inherited fullscreen mouse event volume under tmux, Zellij, and GNU Screen by using button-motion tracking instead of all-motion tracking. > > [0.84.0] - 2026-08-06 > > ### New Features > > - Fullscreen TUI mode — Switch between regular and fullscreen modes at runtime, with a sticky editor and footer, independently scrollable transcript, and draggable scrollbars. See UI & Display > (https://github.com/earendil-works/pi/blob/v0.84.0/packages/coding-agent/docs/settings.md#ui-display). > - Mermaid and LaTeX rendering — Render Mermaid diagrams and terminal-friendly Unicode math in interactive transcripts. See Markdown settings > (https://github.com/earendil-works/pi/blob/v0.84.0/packages/coding-agent/docs/settings.md#markdown) and TUI Markdown (https://github.com/earendil-works/pi/blob/v0.84.0/packages/tui/README.md#markdown). > - Per-directory context overrides — Use AGENTS.override.md to replace context files for a specific directory. See Context Files > (https://github.com/earendil-works/pi/blob/v0.84.0/packages/coding-agent/docs/usage.md#context-files). > - Advanced custom model sampling — Configure arbitrary OpenAI-compatible samplingParams and opt-in vLLM thinking_token_budget values. See Sampling Parameters > (https://github.com/earendil-works/pi/blob/v0.84.0/packages/coding-agent/docs/models.md#sampling-parameters). > - Baseten provider — Use built-in Baseten authentication and model support. See API Keys (https://github.com/earendil-works/pi/blob/v0.84.0/packages/coding-agent/docs/providers.md#api-keys). > > ### Breaking Changes > > - Renamed the inherited pi-ai ModelsStreamTransforms interface to ModelsRequestTransforms because its header transformation now applies to all authenticated provider requests. > > - Changed JSON and RPC message_update events to emit only assistantMessageEvent deltas, removing the cumulative message and assistantMessageEvent.partial fields that caused quadratic output growth. Clients that > need partial messages must assemble deltas between message_start and message_end; the latter remains authoritative (#7290 (earendil-works/pi#7290)). > > - ModelRegistry.getApiKeyAndHeaders() now returns ProviderHeaders with string | null values and preserves null header-deletion markers. Extensions that inspect returned headers must handle null; extensions > forwarding them to pi-ai streams should pass them through unchanged. This prevents placeholder OpenAI credentials from being sent through Cloudflare AI Gateway (#7030 > (earendil-works/pi#7030)). > > - Changed ModelRegistry.refresh() to accept ModelsRefreshOptions and return ModelsRefreshResult instead of discarding cancellation and provider errors. > > - Changed ModelRuntime.setRuntimeApiKey() to accept auth cancellation options rather than catalog refresh options. Call refresh({ providers: [providerId], signal }) separately when remote freshness is required. > > - Required config-form extension OAuth refreshToken(credentials, signal) callbacks to accept and honor a concrete abort signal. > > - Replaced dynamic provider refresh context store access with the read-only context.stored snapshot and generation-checked context.publish() transaction. > > Providers built with createProvider({ fetchModels }): no catalog-publication migration is required. Before and after, return the fetched models and register the resulting provider; createProvider() owns > restoration, persistence, and in-memory publication. > > ```ts > // Before > const beforeProvider = createProvider({ > // ... > fetchModels: async ({ signal }) => { > const response = await fetch(catalogUrl, { signal }); > return parseModels(await response.json()); > }, > }); > pi.registerProvider(beforeProvider); > > // After: unchanged > const afterProvider = createProvider({ > // ... > fetchModels: async ({ signal }) => { > const response = await fetch(catalogUrl, { signal }); > return parseModels(await response.json()); > }, > }); > pi.registerProvider(afterProvider); > ``` > > Handwritten native Provider.refreshModels(): replace direct store access and pre-publication mutation with generation-guarded publications. > > ```ts > // Before > refreshModels: async (context) => { > const stored = await context.store.read(); > if (stored) currentModels = stored.models; > if (!context.allowNetwork) return; > > const refreshed = await fetchModels(context.signal); > currentModels = refreshed; > await context.store.write({ models: refreshed, checkedAt: Date.now() }); > }, > > // After > refreshModels: async (context) => { > if (context.stored) { > const restored = context.stored.models; > if (!(await context.publish({ > update: () => { currentModels = restored; }, > }))) return; > } > if (!context.allowNetwork) return; > > const refreshed = await fetchModels(context.signal); > if (context.signal.aborted) return; > await context.publish({ > persist: { models: refreshed, checkedAt: Date.now() }, > update: () => { currentModels = refreshed; }, > }); > }, > ``` > > For the config-form pi.registerProvider(name, { refreshModels }), callbacks that only return models remain unchanged; pi publishes the returned list. If such a callback previously used context.store for custom > persistence, read context.stored and call context.publish({ persist: entry }). In publish(), omit persist to leave storage unchanged, pass a ModelsStoreEntry to write it, or pass persist: null to delete it. > > - Replaced the inherited pi-agent-core harness session model with the v4 lane-based Session, SessionStorage, and SessionRepo APIs, including durable operation records, global facts, shared sequence numbers, and > tree-scoped lane views. > > - Promoted the inherited v2 session and AgentHarness API from pi-agent-core's experimental entrypoint to its default export and removed the experimental subpaths. > > - Removed the inherited legacy JSONL and in-memory repository APIs. Use pi-agent-core's v4 JsonlSessionRepo or InMemorySessionRepo, both implementing the new SessionRepo contract. > > - Added the inherited required pi-agent-core FileSystem.renameFile() operation for atomic JSONL publication; custom harness file-system implementations must provide same-filesystem replacement semantics (#7707 > (earendil-works/pi#7707) by @davidbrai (https://github.com/davidbrai)). > > - Replaced experimental remote-session list summaries with durable SessionMetadata; RemoteSession.sessions no longer exposes runtime phase, model, thinking, attachment, or lock state, which remains available > from acquired SessionSnapshot values (#7708 (earendil-works/pi#7708)). > > ### Added > > - Added built-in Baseten provider support with BASETEN_API_KEY authentication and zai-org/GLM-5.2 as the default model. > - Added experimental remote-session client APIs: the transport-neutral PiClient, CBOR protocol, Unix-socket transport, and @earendil-works/pi-coding-agent/client RemoteSession controller with transcript > reducers. See Pi Client (https://github.com/earendil-works/pi/blob/v0.84.0/packages/client/README.md) and Remote Protocol (https://github.com/earendil-works/pi/blob/v0.84.0/packages/protocol/README.md) (#7344 > (earendil-works/pi#7344), #7348 (earendil-works/pi#7348), #7371 (earendil-works/pi#7371), #7409 > (earendil-works/pi#7409)). > - Added CredentialSynchronizationError for credential changes that commit successfully but fail to synchronize local model state. > - Added chainable pi.registerMarkdownTransformer() hooks for display-only transformation of user and assistant Markdown. See pi.registerMarkdownTransformer() > (https://github.com/earendil-works/pi/blob/v0.84.0/packages/coding-agent/docs/extensions.md#piregistermarkdowntransformertransformer) (#7231 (earendil-works/pi#7231) by @xl0 > (https://github.com/xl0)). > - Added an experimental fullscreen TUI mode, selectable through --tui-mode fullscreen or /settings (#7304 (earendil-works/pi#7304)). > - Added runtime switching between regular and fullscreen TUI modes through /settings. > - Added a sticky editor, status, widget, and footer dock to fullscreen mode while keeping the transcript independently scrollable. > - Added a draggable transcript scrollbar to fullscreen mode with configurable auto, always, and hidden modes through /settings; always reserves the rightmost column. > - Added page scrolling and marked-message navigation shortcuts to fullscreen mode. > - Added an optional scrollbarThumb theme color for fullscreen scrollbar thumbs, falling back to selectedBg. > - Added configurable themed Unicode rendering for supported Mermaid diagrams in interactive messages, including optional rendering while streaming. See Markdown settings > (https://github.com/earendil-works/pi/blob/v0.84.0/packages/coding-agent/docs/settings.md#markdown) (#7624 (earendil-works/pi#7624) by @xl0 (https://github.com/xl0)). > - Added opt-in Ctrl+P/Ctrl+N prompt history navigation, with explicit history bindings taking precedence over application shortcuts while the editor is focused. > - Added per-directory AGENTS.override.md context files, which replace AGENTS.md or CLAUDE.md in the same directory while preserving context from other directories. See Context Files > (https://github.com/earendil-works/pi/blob/v0.84.0/packages/coding-agent/docs/usage.md#context-files) (#7681 (earendil-works/pi#7681) by @Marvae (https://github.com/Marvae)). > - Added AI_AGENT=pi to CLI and RPC child-process environments for generic agent attribution. See Environment Variables > (https://github.com/earendil-works/pi/blob/v0.84.0/packages/coding-agent/README.md#environment-variables) (#7493 (earendil-works/pi#7493) by @renaudhartert-db > (https://github.com/renaudhartert-db)). > - Added inherited terminal-friendly Unicode rendering for LaTeX expressions in Markdown. See TUI Markdown (https://github.com/earendil-works/pi/blob/v0.84.0/packages/tui/README.md#markdown). > - Added stacked transient notifications in fullscreen mode. > - Added arbitrary OpenAI-compatible model sampling parameters through samplingParams in models.json, model overrides, extension providers, and stream options. See Sampling Parameters > (https://github.com/earendil-works/pi/blob/v0.84.0/packages/coding-agent/docs/models.md#sampling-parameters) (#7568 (earendil-works/pi#7568) by @mrexodia (https://github.com/mrexodia)). > - Added inherited opt-in vLLM thinking_token_budget support for OpenAI-compatible models, reserving output tokens for the final answer (#7638 (earendil-works/pi#7638) by @bnsd55 > (https://github.com/bnsd55)). > - Added inherited support for OpenAI-compatible streams that omit finish_reason, using compat.supportsFinishReason to infer normal and tool-use stops when the stream ends. See OpenAI Compatibility > (https://github.com/earendil-works/pi/blob/v0.84.0/packages/coding-agent/docs/models.md#openai-compatibility). > - Added inherited deferred provider request contracts, durable response handles, authenticated fetch/cancel dispatch, and faux-provider support for pending, ready, failed, and cancelled responses (#7339 > (earendil-works/pi#7339) by @davidbrai (https://github.com/davidbrai)). > - Added inherited vendor-neutral telemetry contracts plus agent-owned typed AI-request and harness schemas, composed span starters, and callback helpers. See the agent telemetry schema reference > (https://github.com/earendil-works/pi/blob/v0.84.0/packages/agent/docs/telemetry-schema.md). > - Added inherited structured Amazon Bedrock failure diagnostics with HTTP status, modeled error code, and AWS request id when available (#7286 (earendil-works/pi#7286) by @brianstanley > (https://github.com/brianstanley)). > - Added inherited AgentOptions.shouldStopAfterTurn for gracefully stopping after a completed turn before queued messages or another model call are processed. See Agent Options > (https://github.com/earendil-works/pi/blob/v0.84.0/packages/agent/README.md#agent-options) (#7367 (earendil-works/pi#7367) by @acmerfight (https://github.com/acmerfight)). > - Added inherited v4 JsonlSessionRepo support for append-only JSONL harness sessions (#7611 (earendil-works/pi#7611) by @davidbrai (https://github.com/davidbrai)). > - Added inherited bounded branch-entry and indexed open-operation recovery queries to the v4 session API (#7448 (earendil-works/pi#7448), #7646 > (earendil-works/pi#7646)). > - Added the inherited compile-complete AgentHarness v2 scaffold; unfinished operation paths reject with HarnessNotImplemented while durable execution is implemented. > > ### Changed > > - Added inherited optional cancellation to pi-ai ModelsStore reads, writes, and deletions; catalog orchestration binds these waits to the provider refresh signal. > - Reduced the inherited default fullscreen mouse wheel step from three lines to one for finer scrolling. > > ### Fixed > > - Fixed the footer showing (sub) for generic OAuth/OpenID sign-ins without a known subscription; extension OAuth providers can opt in with isSubscription. > - Fixed inherited OAuth token refreshes so stalled requests release the credential-store lock (#7508 (earendil-works/pi#7508)). > - Fixed inherited tool argument validation to preserve values that already match an anyOf/oneOf union arm before coercion, avoiding nullable unions converting null to another primitive value (#7328 > (earendil-works/pi#7328)). > - Fixed inherited Fireworks GLM 5.2 requests sending the unsupported prompt_cache_retention field when long cache retention is enabled, and enabled session affinity for automatic prompt caching (#7676 > (earendil-works/pi#7676)). > - Fixed inherited JsonlSessionRepo enforcing session IDs globally across working directories; IDs are now unique within each working directory. > - Fixed inherited JSONL session forks and torn-tail repairs to publish atomically, avoiding partially written or corrupted sessions after interrupted writes (#7707 > (earendil-works/pi#7707) by @davidbrai (https://github.com/davidbrai)). > - Fixed path-containing find globs returning no results on Windows (#6817 (earendil-works/pi#6817)). > - Fixed messages queued during manual /compact failing instead of being sent after compaction completes. > - Fixed Git Bash, MSYS, Cygwin, and WSL drive paths passed to built-in file tools resolving against the current Windows drive instead of their native drive (#7064 > (earendil-works/pi#7064), #7547 (earendil-works/pi#7547)). > - Fixed project-level nested provider retry settings replacing unmodified global provider retry settings (#7572 (earendil-works/pi#7572)). > - Fixed inherited GitHub Copilot Grok 4.5 requests to use the supported Responses API (#7560 (earendil-works/pi#7560)). > - Fixed fullscreen shutdown leaking terminal capability-query replies into the parent shell prompt. > - Fixed bare exact --model IDs shared by multiple providers choosing the first catalog entry instead of the sole authenticated provider or a clear ambiguity error (#7327 > (earendil-works/pi#7327)). > - Fixed standalone x64 binaries requiring Haswell-era AVX2/BMI2 instructions by compiling release executables against Bun's baseline runtime (#7390 (earendil-works/pi#7390) by @davidbrai > (https://github.com/davidbrai)). > - Fixed Ctrl+X copy confirmations in fullscreen mode adding a transcript status line instead of showing the transient Copied! marker. > - Fixed Kitty image previews in fullscreen mode overlapping the sticky editor and footer dock while scrolling. > - Fixed image-heavy fullscreen sessions lagging when layout changes retransmitted visible Kitty image payloads and rendered the transcript twice per frame. > - Fixed spaces in /settings searches toggling the highlighted setting while typing multi-word queries such as TUI mode or Quiet startup. > - Fixed custom editors not inheriting the default editor's autocomplete dropdown item limit (#7333 (earendil-works/pi#7333)). > - Fixed malformed resource arrays in package manifests crashing session startup (#7187 (earendil-works/pi#7187)). > - Fixed the DOOM overlay example downloading its shareware WAD from a dead URL. > - Fixed setToolsExpanded(false) to be a no-op when tool output is already collapsed, avoiding redundant Tool output: collapsed startup notices from extensions (#7292 > (earendil-works/pi#7292)). > - Fixed extension-driven model calls in custom compaction, handoff, and Q&A examples to dispatch through the coding-agent model runtime so custom providers and resolved auth options are preserved (#7325 > (earendil-works/pi#7325)). > - Fixed long-running sessions using stale credentials after another process updates auth.json without serializing concurrent credential reads and delaying startup (#7319 > (earendil-works/pi#7319)). > - Fixed concurrent models-store.json reads forming a file-lock convoy and delaying startup. > - Updated the packaged brace-expansion dependency to 5.0.8 to address GHSA-mh99-v99m-4gvg (#7316 (earendil-works/pi#7316)). > - Fixed forced model availability refreshes remaining blocked behind a stalled earlier refresh (#7301 (earendil-works/pi#7301), #7421 (earendil-works/pi#7421) by > @a-yeyang (https://github.com/a-yeyang)). > - Fixed /model catalog refresh failures to identify every catalog that failed. > - Fixed provider login remaining stuck after saving credentials when a model catalog refresh stalls by separating local credential consistency from bounded background freshness (#7027 > (earendil-works/pi#7027), #7113 (earendil-works/pi#7113), #7418 (earendil-works/pi#7418)). > - Fixed /scoped-models waiting for remote catalogs before rendering instead of showing cached models and cancelling refresh on close (#7153 (earendil-works/pi#7153)). > - Fixed /model <name> waiting for catalog refresh before checking cached model matches (#7443 (earendil-works/pi#7443)). > - Fixed stale availability snapshots and errors publishing after a newer availability pass. > - Fixed stale pi.dev, Radius, llama.cpp, and extension catalog refreshes publishing after a newer provider refresh. > - Fixed cancellation while waiting for file-backed credential or model-catalog locks, preventing cancelled mutations from running or committing later. > - Fixed concurrent in-memory credential mutations losing unrelated provider updates by serializing their read-modify-write sections. > - Updated undici to 8.9.0 and the packaged brace-expansion to 5.0.9 to address GHSA-8xcm-r25x-g524, GHSA-4cwx-7wf7-3272, GHSA-m8rv-5g2x-5cg5, GHSA-jr45-8vmc-qm54, GHSA-v3r7-h72x-cjcm, and GHSA-rgw5-rvv9-x895. > - Fixed GitHub Copilot compaction and branch summaries using the Individual endpoint instead of the credential-resolved Business or Enterprise endpoint (#6768 (earendil-works/pi#6768)). > - Fixed extension model calls dropping credential-resolved endpoints when forwarding request authentication, including custom compaction with GitHub Copilot Business and Enterprise accounts (#7579 > (earendil-works/pi#7579)). > - Fixed fullscreen transcript navigation leaving no editor-accessible Home, End, PageUp, or PageDown variants by adding Ctrl-modified editor bindings (#7574 (earendil-works/pi#7574)). > - Fixed extension event-bus listeners surviving session reloads and disposal (#7656 (earendil-works/pi#7656) by @tudoroancea (https://github.com/tudoroancea)). > - Fixed /copy failing to read clipboard text on Wayland when no X11 clipboard is available (#7387 (earendil-works/pi#7387)). > - Fixed slow connections failing during the initial connection attempt by increasing the connect timeout (#7435 (earendil-works/pi#7435) by @muyiyr (https://github.com/muyiyr)). > - Fixed oversized images returned by extension and built-in tools bypassing automatic image resizing. See Image settings > (https://github.com/earendil-works/pi/blob/v0.84.0/packages/coding-agent/docs/settings.md#terminal--images) (#7330 (earendil-works/pi#7330) by @tizmagik (https://github.com/tizmagik)). > - Fixed session discovery missing sessions stored through symlinked directories (#7552 (earendil-works/pi#7552) by @muyiyr (https://github.com/muyiyr)). > - Fixed manual compaction racing with threshold auto-compaction (#7370 (earendil-works/pi#7370) by @davidbrai (https://github.com/davidbrai)). > - Fixed responses truncated below their intended output limit ending the run instead of compacting and retrying once (#7540 (earendil-works/pi#7540) by @davidbrai > (https://github.com/davidbrai)). > - Fixed Git package updates leaving dependencies missing when git clean cannot remove an ignored dependency directory (#7570 (earendil-works/pi#7570) by @mrexodia > (https://github.com/mrexodia)). > - Fixed find results from POSIX and Windows filesystem roots losing the first path segment or gaining duplicate trailing separators (#7569 (earendil-works/pi#7569) by @petrroll > (https://github.com/petrroll)). > - Fixed transient version-check, catalog, managed-tool, and package-management HTTP failures not being retried (#7632 (earendil-works/pi#7632) by @petrroll (https://github.com/petrroll)). > - Fixed interactive errors ignoring the configured output padding. > - Fixed the inherited OpenCode Go provider display name. > - Fixed inherited provider error normalization treating arrays and class instances as structured response bodies instead of preserving their original errors (#7205 > (earendil-works/pi#7205) by @erikogenvik (https://github.com/erikogenvik)). > - Fixed inherited Anthropic streams dropping text or thinking included in the initial content-block event (#7358 (earendil-works/pi#7358) by @davidbrai (https://github.com/davidbrai)). > - Fixed inherited Google history conversion dropping signed empty text and thinking blocks required for replay (#7362 (earendil-works/pi#7362) by @jingtao-wisdomgraph > (https://github.com/jingtao-wisdomgraph)). > - Fixed inherited OpenAI Codex cached WebSocket sessions being shared across different account credentials (#7364 (earendil-works/pi#7364)). > - Fixed inherited transient Google Generative AI and Vertex AI provider errors bypassing automatic retries (#7471 (earendil-works/pi#7471) by @vish-pr (https://github.com/vish-pr)). > - Fixed inherited Gemini 3 tool call ids being discarded during history conversion, breaking signed multi-turn replay (#7494 (earendil-works/pi#7494) by @muyiyr > (https://github.com/muyiyr)). > - Restored inherited GitHub Copilot models returned through account-specific policy responses (#7672 (earendil-works/pi#7672) by @muyiyr (https://github.com/muyiyr)). > - Replaced the inherited retired Qwen Token Plan qwen3.8-max-preview model with qwen3.8-max (#7670 (earendil-works/pi#7670) by @QuintinShaw (https://github.com/QuintinShaw)). > - Fixed inherited terminal width accounting for Indic conjunct grapheme clusters (#6987 (earendil-works/pi#6987) by @petrroll (https://github.com/petrroll)). > - Fixed inherited nested fullscreen stack layouts ignoring child minimum sizes. > - Fixed inherited batched terminal color-scheme reports being parsed as one malformed response (#7550 (earendil-works/pi#7550)). > - Fixed inherited terminal progress clearing to emit the complete OSC 9;4 sequence (#7581 (earendil-works/pi#7581)). > - Fixed inherited iTerm2 image payloads omitting the size metadata required by the xterm.js image addon (#7612 (earendil-works/pi#7612)). > - Fixed inherited width truncation leaving OSC 8 hyperlinks unterminated (#7657 (earendil-works/pi#7657) by @xXJSONDeruloXx (https://github.com/xXJSONDeruloXx)). > - Updated inherited GPT-5.6 Terra and Luna pricing across OpenAI and passthrough model catalogs. > - Fixed inherited Fireworks Kimi K3 models to use the OpenAI-compatible API with native reasoning-effort levels and deferred tools (#7199 (earendil-works/pi#7199), #7230 > (earendil-works/pi#7230) by @XBeg9 (https://github.com/XBeg9)). > - Updated the inherited Groq Qwen reasoning override for the replacement qwen/qwen3.6-27b model. > - Fixed inherited Windows Shift+Enter detection by reading modifier state from the native Win32 helper. > - Fixed the inherited pi-tui npm package omitting the source and build scripts needed to rebuild its Windows and Darwin native addons. > - Fixed inherited Windows console truecolor detection when Windows Terminal does not provide WT_SESSION to child shells. > - Fixed inherited phantom fullscreen text selection from unmatched mouse events when changing terminal pane focus. > - Fixed inherited keyboard input rendering latency on Windows by letting input preempt the throttled render timer. > - Fixed inherited agent harness path handling on Windows for file basenames, recursive skill loading, and prompt template names. Change-Id: uktsvuwukysuwmkowuzzxnylrvnoyxtu
…tion Backport bounded recovery from earendil-works/pi#7540 and add real-SDK synthetic regressions. Fixes CherryHQ#20160 Signed-off-by: colin <[email protected]>
…tion (#20163) <!-- Template from https://github.com/kubevirt/kubevirt/blob/main/.github/PULL_REQUEST_TEMPLATE.md?--> <!-- Thanks for sending a pull request! Consider opening it as draft: https://github.com/CherryHQ/cherry-studio/blob/main/CONTRIBUTING.md --> > ### Branch strategy > > - Active development targets `main`. ### What this PR does Before this PR: Pi Work could stop after successful compaction when context pressure clamped a response below the model's intended output limit. The user had to send another message to resume. Reporting `length` as an error in #19571 did not restore this recovery path. After this PR: The pinned coding-agent makes one compact-and-retry attempt for a length-stopped response whose output is below the model's intended output cap. A second truncated response does not reset the recovery guard. The rebuilt context excludes a retained trailing truncated assistant response so continuation can proceed. Genuine full-output-cap responses and cancelled compactions are not automatically continued. Fixes #20160 ### Why we need it and why it was done in this way The following tradeoffs were made: - Backport the three relevant `AgentSession` changes from [earendil-works/pi#7540](earendil-works/pi#7540) using the existing pnpm patched-dependency mechanism. - Keep the dependency pinned at 0.80.3 and inline the small recovery predicate to avoid requiring another Pi export/API change. - Add synthetic tests against the real SDK session rather than replacing the session with a mock. The following alternatives were considered: - A broader SDK upgrade also changes other integration contracts and is not required for this fix. - Unconditional auto-continuation would hide genuine output-cap stops or risk retry loops. - The later [post-tool compaction change, pi#8782](earendil-works/pi#8782), is useful prevention work but changes loop-hook timing and is kept out of this PR. Links to places where the discussion took place: #20160; related but distinct fixes #19457 and #19571; upstream pi#7540 linked above. ### Breaking changes None. No dependency version changes, new settings, schema changes or migration changes. ### Special notes for your reviewer Validation (Node 24.15.0, pnpm 11.8.0, Vitest 3.2.7): - The same new real-SDK test file against unpatched coding-agent 0.80.3: 3 failed / 1 passed, reproducing the missing recovery. - Against an independent copy of that SDK with this exact patch: 4 / 4 passed. The isolated Vitest config skips application-native setup, not the Pi SDK or its session loop. - TypeScript 5.9.3 strict type-check of the new test, Biome format, targeted `simple-import-sort`, `git diff --check`, and `git apply --check` against the unpatched SDK: passed. - `pnpm install --frozen-lockfile --lockfile-only --ignore-scripts --offline`: passed. - Full application lint/build/test suite was not completed: the full dependency download timed out. This PR does not claim full CI or a new long-running live-model task has passed. Maintainer-approved CI should run the normal repository checks. All reproduction data is synthetic. No private conversation content, task files, application logs, local paths, endpoint addresses or credentials are included. The example API key and `example.invalid` URL in the tests are inert fixtures; the custom stream handles requests in memory. ### Checklist This checklist is not enforcing, but it's a reminder of items that could be relevant to every PR. Approvers are expected to review this list. - [x] Branch: This PR targets `main` - [x] PR: The PR description is expressive enough and will help future contributors - [x] Code: [Write code that humans can understand](https://en.wikiquote.org/wiki/Martin_Fowler#code-for-humans) and [Keep it simple](https://en.wikipedia.org/wiki/KISS_principle) - [ ] Refactor: You have [left the code cleaner than you found it (Boy Scout Rule)](https://learning.oreilly.com/library/view/97-things-every/9780596809515/ch08.html) - [x] Upgrade: Impact of this change on upgrade flows was considered and addressed if required - [x] Documentation: A [user-guide update](https://docs.cherry-ai.com) was considered and is present (link) or not required. Check this only when the PR introduces or changes a user-facing feature or behavior. - [x] Self-review: I have reviewed my own code (e.g., via [`/gh-pr-review`](/.claude/skills/gh-pr-review/SKILL.md), `gh pr diff`, or GitHub UI) before requesting review from others Documentation note: this restores automatic recovery with no new user action or setting, so a separate user-guide update is not required. No unrelated refactoring is included. ### Release note ```release-note [Work] Resume Pi tasks after context-clamped length responses with one bounded compact-and-retry attempt. ``` --------- Signed-off-by: colin <[email protected]> Signed-off-by: suyao <[email protected]> Co-authored-by: suyao <[email protected]> Co-authored-by: Claude Opus 5 (1M context) <[email protected]>
…l-works#7540) * fix(coding-agent): resume after context-limited length stops Treat length stops as context overflow when prompt usage is within 1% of Pi's configured context window. Include cache-write tokens in that usage and allow non-zero output because OpenAI may emit reasoning tokens before returning an incomplete response. After compaction, remove any retryable error or truncated-length assistant message restored from persisted session history so the interrupted agent turn can continue. This is specifically for handling this case for openai models: https://developers.openai.com/api/docs/guides/reasoning > If the generated tokens reach the context window limit or the max_output_tokens value you’ve set, you’ll receive a response with a status of incomplete and incomplete_details with reason set to max_output_tokens. This might occur before any visible output tokens are produced, meaning you could incur costs for input and reasoning tokens without receiving a visible response. This detection currently assumes the reported prompt usage is within 1% of the context window configured in Pi. Its reliability therefore depends on Pi's model contextWindow metadata matching the provider's effective limit. Maybe we should consider treating OpenAI incomplete responses as requiring compaction regardless of the local context-window estimate? fixes earendil-works#7020 * fix(coding-agent): recover truncated responses after compaction Classify length stops by comparing provider-reported output usage with the model's intended output limit. Compact and retry once when generation ends below that limit, avoiding unreliable context-window estimates while preserving genuine max-output stops. Normalize OpenAI Responses incomplete reasons so only max_output_tokens is treated as a length stop. Preserve qualified provider reasons for diagnostics, surface other reasons as errors, and use neutral truncation wording in the TUI.
* fix(coding-agent): resume after context-limited length stops Treat length stops as context overflow when prompt usage is within 1% of Pi's configured context window. Include cache-write tokens in that usage and allow non-zero output because OpenAI may emit reasoning tokens before returning an incomplete response. After compaction, remove any retryable error or truncated-length assistant message restored from persisted session history so the interrupted agent turn can continue. This is specifically for handling this case for openai models: https://developers.openai.com/api/docs/guides/reasoning > If the generated tokens reach the context window limit or the max_output_tokens value you’ve set, you’ll receive a response with a status of incomplete and incomplete_details with reason set to max_output_tokens. This might occur before any visible output tokens are produced, meaning you could incur costs for input and reasoning tokens without receiving a visible response. This detection currently assumes the reported prompt usage is within 1% of the context window configured in Pi. Its reliability therefore depends on Pi's model contextWindow metadata matching the provider's effective limit. Maybe we should consider treating OpenAI incomplete responses as requiring compaction regardless of the local context-window estimate? fixes #7020 * fix(coding-agent): recover truncated responses after compaction Classify length stops by comparing provider-reported output usage with the model's intended output limit. Compact and retry once when generation ends below that limit, avoiding unreliable context-window estimates while preserving genuine max-output stops. Normalize OpenAI Responses incomplete reasons so only max_output_tokens is treated as a length stop. Preserve qualified provider reasons for diagnostics, surface other reasons as errors, and use neutral truncation wording in the TUI.
Treat length stops as context overflow when prompt usage is within 1% of Pi's configured context window. Include cache-write tokens in that usage and allow non-zero output because OpenAI may emit reasoning tokens before returning an incomplete response.
After compaction, remove any retryable error or truncated-length assistant message restored from persisted session history so the interrupted agent turn can continue.
This is specifically for handling this case for openai models: https://developers.openai.com/api/docs/guides/reasoning
This detection currently assumes the reported prompt usage is within 1% of the context window configured in Pi. Its reliability therefore depends on Pi's model contextWindow metadata matching the provider's effective limit.
Maybe we should consider treating OpenAI incomplete responses as requiring compaction regardless of the local context-window estimate?
fixes #7020