You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Agent, StopAgent, and AgentStatus registered with description: ".". Some gateways rejected description-less tools.
Added
Opt-in agent descriptions in the Agent tool schema. A new agent.exposeDescriptions setting (default false) makes the Agent tool's agent parameter description list each visible agent's name together with its Markdown description (Available agent types: followed by one name: description line), so SDK/RPC/print-mode hosts get routing-relevant information at the decision point without any TUI interaction. Empty descriptions degrade to the bare agent name and hidden agents stay excluded. Default behavior (name-only, minimal tokens) is unchanged; the value is read when the tool registers, so toggling it takes effect on the next session. Toggle lives in Agent settings > Tools ("Expose agent descriptions").
Changed
AgentStatus no longer requests constrained sampling. Its empty, closed parameter schema remains unchanged, while providers are free to handle the status call without strict JSON schema mode.
Subagents respect pi's per-model thinking level setting. A modelThinkingLevels entry in pi's settings.json (keyed provider/modelId, project layer over global) now participates in subagent thinking resolution at the position above the defaultThinking setting: explicit spawn param > agent frontmatter thinking > pi's per-model level for the resolved model > defaultThinking > pi's own fallback (defaultThinkingLevel setting, then medium, clamped to the model's supported levels). Previously the per-model level was ignored everywhere: defaultThinking silently overrode it, and session creation never consulted it. The Model settings menu, the spawn wizard, and the Agent tool call display show the same spawn-effective chain. The wizard's thinking value is now a Derived/UserSet state: it shows the level the spawn will actually run with and re-derives when you switch the model, while any explicit pick (including Inherit) is kept across model switches and only clamped to the new model. defaultThinking keeps its purpose — overriding pi's global default — but no longer overrides an explicit per-model choice.
@earendil-works/pi-coding-agent floor raised to >=0.84.3. The per-model thinking setting and its SettingsManager accessors shipped in pi 0.84.3, so the per-model read calls the accessor directly instead of degrading through raw settings reads for older versions. Lockfile regenerated through npm.
Fixed
Conversation viewer no longer loses streamed content at block boundaries. While watching a subagent run, each completed streaming block (thinking, then response text) vanished the moment the next block started and only reappeared when a tool result landed minutes later. pi's agent loop replaces the last messages-array slot on every streaming delta, so the viewer's per-index render cache — keyed on array reference, count, and width — never went stale while a message streamed and stayed frozen at its first, near-empty snapshot; the streaming accumulators, the only other copy, are cleared at each *_end. The viewer now re-renders the in-flight message's cache entry from the session transcript synchronously at exactly the accumulator-clearing boundaries (thinking_start/thinking_end/text_start/text_end) and at the session-level message_end (pi's final-message slot swap), where the finished block exists only in the transcript — so it can never duplicate the live streaming suffix. Completed text stays on screen the moment it completes, content shown is never retroactively changed when the tool result re-renders the message, and the debounced streaming render cadence, ctrl+T thinking visibility (with the "Thinking..." label while hidden), tool-result inlining, and scroll behavior are unchanged.
Restart last agents obeys the project-trust gate. Restarting agents from session history skipped every check the live Agent tool applies to worktree_path: the historical path was neither validated nor trust-resolved, the target project's .pi/agents types loaded unconditionally, and the spawn runner treated the target as trusted (projectTrusted defaulted to true) — so a restart into an untrusted cross-repo worktree ran with that project's agent types and settings, contradicting the warning live spawns surface. Each historical call now resolves through the same shared spawn-target computation as a live spawn: the path is validated (an invalid one is reported in the skipped list with the self-correctable error), cross-repo trust is resolved, the explicit projectTrusted decision is forwarded to the runner, untrusted targets' .pi/agents types stay hidden, and the untrusted-project warning reaches the user through the same shared notify policy as live spawns. Calls without a worktree_path are unaffected, and a malformed one (a non-string value from history or a tool call) counts as omitted exactly as the live tool treats it instead of failing with a TypeError; restarted agents now also show the target's worktree label in the widget like live spawns.
Agent tool call thinking injection obeys the project-trust gate. The pre-execution injection read pi's modelThinkingLevels at the spawn target through an ungated SettingsManager, so an untrusted cross-repo worktree_path target's settings file could set the spawn's thinking level — the injected value runs as the explicit param, above every configured source, while pi's trust warning says the project's .pi/ settings are ignored. The listener now resolves the spawn target exactly as execution does (validation plus the same trust decision, silently, without duplicate warnings) and skips the per-model term for untrusted targets; the runner's own trust-gated read still decides. The read also now uses the validated target path instead of the raw tool argument.
Spawn wizard no longer passes its derived thinking level as an explicit override. The Derived display value is a prediction read at the parent cwd; passing it as the explicit param shadowed a worktree target's own per-model entry and pi's per-model fallback. In the Derived state the wizard now spawns with nothing — frontmatter, per-model, and defaultThinking are exactly the runner's chain, resolved at the actual target cwd — and re-reads the pi settings snapshot when the selected worktree changes, so the displayed level keeps tracking the spawn target. A user-chosen level (including Inherit) is still passed as chosen.