Skip to content

v1.14.0

Choose a tag to compare

@github-actions github-actions released this 16 Sep 23:23
· 121 commits to main since this release

Fixed

  • 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.