Repository navigation
Releases: AlexParamonov/pi-subagents-lite
Release list
v1.17.1
Fixed
- Extension startup avoids Jiti resolution overhead. Relative imports in the source now use explicit
.tsspecifiers, avoiding repeated failed.jspath probes. - Performance optimization of widget Finished and queued rows repaint only when their visible output changes
v1.17.0
Added
parentis a selectable Thinking level. Agent files,Subagent default thinkingand the spawn wizard accept it, and the Subagent then runs at the parent session's current level. It sits in the position you set it in, so a file'sparentbeats pi's per-model level but loses to a wizard pick, and it resolves before the Subagent exists, so nothing downstream can show the word. Nothing changes unless you select it.- Pre-spawn menus name what decided the Thinking level. Model settings and the spawn wizard read
high (frontmatter)orminimal (parent)instead of a bare level, so an unexpected effort is traceable before you spawn. The widget, viewer and stats stay bare, because a running session stores only its number. - Subagents are announced to Subagent-aware extensions. Creation, binding and disposal are broadcast on pi's event bus, so a permission gate can raise an
askfrom inside a Subagent on the parent session. An announcement can never fail a spawn or a teardown. - New
MessageAgenttool feeds input to an existing agent. A running agent takes it at its next turn boundary; a settled agent with a live session continues on it, context intact, with no second record. - Short agent IDs work in
StopAgentandMessageAgent. The 8-character ID the tools print is accepted when it matches one agent; an ambiguous prefix acts on none and names every candidate.
Changed
- The setting row is now
Subagent default thinking. Label only, the key staysdefaultThinking, and it no longer collides with pi's owndefaultThinkingLevel. Unset readspi default, andpi defaultin the list removes the key at the chosen layer.
Fixed
- An untrusted spawn target no longer hides your global per-model Thinking level. The gate discarded pi's whole
modelThinkingLevelsmap rather than only the untrusted project's file, so the run ignored a level that Model settings printed. - Both Thinking level annotations follow the same parent level. Model settings fell back to the current session context and the wizard did not, so the two rows disagreed about one run.
- A Thinking level picked in the spawn wizard is clamped to the model the Subagent gets. Choosing
(inherits parent)was the one model change that skipped the clamp. - The spawn wizard reads pi's per-model level for the model the Subagent actually runs on. It used the parent's model even where the agent file pins another, so it offered levels that model cannot run.
v1.16.0
Added
- Extension tool aliases accept
extension/allas well asextension/*. Both forms include or exclude all tools from the named extension. - New config setting
loadToolsImplicitly(default ON,/agents> System Prompt). When frontmatter omits the tool fields, ON makes the Subagent behave like a normal session: pi'sdefaultToolsapplies unchanged and inactive tools stay registered for dispatcher tools. OFF starts it with no tools. Explicit frontmatter always wins.
Changed
- Child sessions load pi's built-in extensions (codemode, tool-search, mcp; llama.cpp excluded). They are addressable by bare name (
codemode) fromdefaultTools, settingsextensions, and frontmatterextensions/exclude_extensions, exactly as in a normal session. Requires pi >= 0.99.0. - A silent agent config no longer snapshots
defaultToolsinto a registry allowlist. pi owns tool fallbacks, so dispatcher tools can reach inactive and late-registered tools.
Fixed
- Extension tool aliases use the owning package name. Package extension entries under paths like
src/index.tsnow resolve to their declared package name instead ofsrc. - No more child-session leaks. Every child session terminates through one idempotent disposal (abort,
session_shutdown, dispose) — whether it settles, stops, is cleared, outlives its record, or fails during setup — releasing built-in extension resources exactly once.
v1.15.1
Fixed
- OpenAI Responses token injection preserves ChatGPT sign-in compatibility. The subagent output-limit hook now overrides pi's existing
max_output_tokensbut doesn't restore the field when pi omitted it for Sign in with ChatGPT credentials. - Context percentage respects its own widget visibility setting. It remains visible when input and output token counts are hidden.
v1.15.0
Changed
- The conversation viewer no longer shows tool results. Each tool call renders as a single status-colored line (tool name + args summary, pending → success/error background); result content never renders, inline under a call or as a standalone result block. Thinking, assistant text, steering, stop, and scrolling are unchanged, as is the parent chat's Agent tool display and the text the model receives.
v1.14.0
Fixed
Agent,StopAgent, andAgentStatusregistered withdescription: ".". Some gateways rejected description-less tools.
Added
- Opt-in agent descriptions in the Agent tool schema. A new
agent.exposeDescriptionssetting (defaultfalse) makes theAgenttool'sagentparameter description list each visible agent's name together with its Markdown description (Available agent types:followed by onename: descriptionline), 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
modelThinkingLevelsentry in pi's settings.json (keyedprovider/modelId, project layer over global) now participates in subagent thinking resolution at the position above thedefaultThinkingsetting: explicit spawn param > agent frontmatterthinking> pi's per-model level for the resolved model >defaultThinking> pi's own fallback (defaultThinkingLevelsetting, then medium, clamped to the model's supported levels). Previously the per-model level was ignored everywhere:defaultThinkingsilently 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.defaultThinkingkeeps its purpose — overriding pi's global default — but no longer overrides an explicit per-model choice. @earendil-works/pi-coding-agentfloor raised to>=0.84.3. The per-model thinking setting and itsSettingsManageraccessors 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-levelmessage_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/agentstypes loaded unconditionally, and the spawn runner treated the target as trusted (projectTrusteddefaulted 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 explicitprojectTrusteddecision is forwarded to the runner, untrusted targets'.pi/agentstypes stay hidden, and the untrusted-project warning reaches the user through the same shared notify policy as live spawns. Calls without aworktree_pathare 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
modelThinkingLevelsat the spawn target through an ungatedSettingsManager, so an untrusted cross-repoworktree_pathtarget'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.
v1.13.1
Changed
- Running Agents menu shows readable durations. Each row now shows a formatted run duration (
5m 37s,1h 1m 1s) instead of a raw second count. Finished rows freeze the duration at completion and append how long ago the run settled (... — my task 2m ago). - Schemas migrated to pi's
typebox1.x line, declared as a peer dependency. Tool parameter schemas and config validation now build on the unscopedtypeboxpackage instead of@sinclair/typebox0.34 — a package the pi host does not ship, so the extension and host previously maintained different schema libraries.typebox(>= 1.3.7) joins the three pi packages as a peer: pi's extension loader aliases it to the host's own copy in every runtime mode, dev/CI gets it via npm peer auto-install (lockfile-pinned), and the extension ships no schema-library copy at all. Emitted schemas are unchanged JSON data; the full suite passes without behavior changes. - Dev dependency on pi dropped; the peer declaration is the single contract. The
@earendil-works/pi-coding-agentdevDependency entry is removed — npm provides the package in dev/CI by auto-installing the existing peer dependency (>=0.82.0), so typecheck and tests are unchanged while the version floor is declared once instead of twice. The lockfile keeps pinning the resolved version. Dev-only: no impact on the published package.
Fixed
- Manual spawn runs in background by default. The spawn wizard Background toggle now defaults to ON, so the parent session gets the result via nudge. Foreground menu spawns had no tool return to deliver through, so their result never reached the main session.
- Tool count marker renders reliably across terminal fonts. Replaced the forced text-presentation emoji with a one-cell text symbol, avoiding the Unicode replacement glyph when that text variant is unavailable.
- Subagent output-limit injection follows pi's per-API algorithm. When an agent sets
max_tokens, the injected provider field is now resolved exactly the way pi resolves it for the model's API —max_output_tokenson OpenAI Responses APIs, nested fields on bedrock, Google, mistral, and pi-messages, pi's compat-chain field on openai-completions, and none on Codex — and it is re-resolved per request, so a mid-run model change stays in sync with pi. Previously the extension sent a top-levelmax_tokensfield whenever the model's compat was silent, which those providers ignore or reject, so the author's cap silently dropped. Models on unknown future APIs keep the previousmax_tokensinjection. - Config files validate on load. Every value in the global and project config files is checked against a runtime schema at load. A wrong-typed value is dropped from the effective config (built-in defaults apply), valid keys are kept, the file on disk is left unchanged, and one warning per bad value names the file, the key, what was got, what was expected, and how to fix it in the
/agentsmenu or by editing or deleting the file. Fork-shaped object model values are dropped with a warning, never migrated, and a bad value can no longer crash the load with an unhandled error.
v1.13.0
Added
- Agent
colorfrontmatter. Agent.mdfiles can setcolor: <named-color>orcolor: #RRGGBBin frontmatter. The agent's status icon is tinted with that color across all UI surfaces, including widget connector lines and a new toggle in General settings. - Background agent status indicators. When an agent is scheduled to run in the background, the UI now clearly shows its status in the call-line icon:
◆(accent) when queued,◈(accent) when running,✓(success) when completed or turn-limited,✗(error) on error or abort, and■(dim) when stopped; foreground call lines show▸. The result line shows the model tag and stats for finished foreground agents and the description only for background agents (icon lives in the call line). Live status updates via invalidation map — the icon flips as the agent progresses. - Model picker prioritizes configured models. The model picker (via
/model, model settings, concurrency settings, and spawn wizard) now shows models sorted: current model first, then models fromsubagents-lite.jsonagent config (default + per-type overrides), then all remaining models. This makes configured models easy to find without searching. Search/filter still works correctly with the new sort order.
Changed
- Flattened settings menu. Reworked setting menu into 5 top-level categories for easier navigation.
- Unified agent status icons across all UI surfaces. Tool call lines, the subagent status widget, and the conversation viewer now share one status→icon map (
statusIconinformat.ts):◆queued,◈running,✓completed (success),✓turn-limited (warning),✗error/aborted,■stopped (dim),▸when no status yet.
v1.12.0
Added
- Restart last agents from debug menu. A new "Restart last agents" command in the debug menu finds the most recent Agent tool call(s) in session history and replays them, spawning fresh agents with the same configuration. Useful when agents are cancelled by mistake or lost after reload. Running agents are skipped. Uses current config model (not historical) and spawns as background for steer support.
- Limit-bounded AgentStatus output. The AgentStatus tool now always lists in-progress agents (running, queued) and then shows settled agents (completed, turn_limited, aborted, stopped, error) most-recently-settled first, capped at
agentStatusLimitsettled agents; when settled agents are hidden, the output ends with "and N more settled agents". The newagentStatusLimitconfig key (Widget settings > Behavior, numeric entry) defaults to 0 = auto: 2 × the configured default concurrency (8 at the built-in default of 4), so the cap scales with how many agents can run at once. Records are unaffected — the limit only changes what the tool prints. - ext/none syntax suppresses extension warning. Agent tool configs can now use
ext/nonein the tools list to explicitly register zero extension tools, suppressing the warning about missing extensions. Previouslytools: []meant zero built-in tools but extensions were still warned about;ext/nonenow makes the intent explicit.
Changed
- No explicit
anytype usage remains in test code.typecheckalready coveredtest/; every explicitanyannotation across the test suite is now replaced with the realsrc/or pi-package type, or with a structural fake asserted at a single call boundary. Type-level only: all 1592 tests behave identically. - Test
anyregression gate.npm run test:any-gatescanstest/for explicitanyannotations and fails if any are found (whitelisting the two documented load-bearing sites andexpect.any(...)vitest matchers). Import specifiers in test files unified to.js(no.tsextensions in import paths). - Typed test context helpers.
fakeCtx()andcreateMockCtx()intest/fixtures.tsnow return properly typedExtensionContext/ExtensionCommandContextwith typed defaults and an options parameter for overrides, eliminating the two documentedanyreturn annotations. subscribeToSessionEventsannotation corrected. The function's parameter type now referencesRunCallbacks(the interface that defines the callback keys) instead ofRunOptions(which carries extra fields the function never reads). Purely defensive; no call sites changed.- TypeScript 7 toolchain and test typechecking. The development toolchain now uses TypeScript 7.0.2 (the native compiler,
tsc); the package swap is behavior-neutral for the extension itself.npm run typechecknow coverstest/as well assrc/(tests were previously transpiled by vitest but never typechecked); the type errors this surfaced were fixed in test code only (stale mock typings, fixtures, and imports), with no change to extension behavior. - Subagents honor pi's
defaultToolssetting. Agent types without explicit tool config now use pi'sdefaultTools(global~/.pi/agent/settings.json+ project.pi/settings.json) as their registered built-in tool set. Unconfigured keeps the hardcodedread/bash/edit/writeset, explicit[]means zero built-in tools, and explicit agent tool config (whitelist,exclude_tools,tools: false, read-only sets) still wins. Extension tools remain always-enabled. On pi < 0.84.2 the setting is honored via the merged-settings read; only thegetDefaultToolsAPI is missing (pi ≤ 0.84.1 lacks the accessor — 0.84.2 ships it — so the read feature-detects and falls back to the merged settings field). - Model settings grouped by resolved model. Per-type overrides are grouped alphabetically by the model they resolve to; each row shows the spawn-effective (clamped) thinking level and the winning layer's tag (
[session]/[project], global-won rows untagged). Only explicit per-type overrides are listed; frontmatter-only and inheriting types stay hidden (hint arrows gone). The session default is a session-wide override that beats config per-type overrides and frontmatter models. Concurrency settings share the style: rows set targets inline with a nested Clear, section headers in bold accent, and clear/remove pickers offer only the levels that carry the setting ("All levels" only when at least two do), andj/knavigate list submenus. - Debug menu shows each agent type's effective tool set. The Agent types listing and the Agent briefing now display the tools an agent actually gets: the explicit
registeredToolswhen configured, otherwise pi'sdefaultToolssetting, otherwise the hardcodedread/bash/edit/writeset. The generic "all built-in tools" placeholder is gone, the briefing always includes a Tools line, and an explicitly empty set renders as(none). The menu readsdefaultToolsthrough the same version-tolerant accessor as the spawn path, so the two displays and the session gate cannot diverge.tools: []in an agent config now means zero built-in tools everywhere — no consumer silently falls back to the default set.
Fixed
- Agent tool error display shows ✗ instead of ✓. Agent and StopAgent tools now throw on errors instead of returning
errorResult(), matching how built-in tools (bash, edit, read, write) handle errors. Agent-loop's catch block setsisError: true, so the renderResult callbacks usecontext?.isError(from the agent-loop's correct error flag) instead ofresult.isError, which is absent from the production data flow. Failed tool calls now correctly display a red cross (✗) and error background color. - nanoid bumped to 3.3.18. The dev-only transitive dependency (via postcss) is now locked at 3.3.18, clearing the high-severity
npm auditfinding for nanoid's zero-size generator loop (GHSA-2v37-7h3g-55p8). No runtime or extension behavior change. - Agents status line stays visible for the session. The status line's visibility is now: after the last agent finishes and its row ages out, the line keeps showing the session done count and cost in its dimmed form, and it hides only when no agent records exist.
- Git-root discovery during skill loading is constant-time per ancestor level.
findGitRootnow probes.gitwith a singleexistsSyncper level instead of reading the full directory listing - Tool-argument summaries truncate with the ellipsis character. Long single string arguments to arbitrary tools now end with
…(U+2026) like bash commands, instead of three ASCII dots. - Write-tool summaries show the real file path.
summarizeToolArgsnow reads thepathargument key that pi's write tool actually sends, so summaries render aswrite("/path/to/file", N chars)instead ofwrite("", N chars).
v1.11.0
Added
- Parent interrupt forwarding. Foreground subagents are now bound to the parent's interrupt signal. Stopping the parent stops all foreground children. Background agents are not affected.
- Project-level config.
.pi/subagents-lite.jsonin a trusted project is an override layer over the global~/.pi/agent/subagents-lite.json: it may hold only model and concurrency settings, and each key it sets overrides the global value; clearing a project value falls back to global./agentsmenu changes now pick a write target — session, global, or project — and persist only that level's keys; the merged config is never written to a file. Unknown keys in a hand-edited project file are ignored with a warning; a malformed project file is ignored and the project level is not offered. Loaded only in trusted projects, same as.pi/agents. - Agent menu clear actions. Individual
Clearaction removes a settled agent.Clear all/Clear donebulk-removes all/done agents from the widget. - Time-based finished retention. Replaced turn-based eviction with a configurable time window. Finished agents stay visible for
finishedRetentionMinutes(default 1 min) instead of a fixed number of turns. - Transient transport error retry. Brief stream failures (ECONNRESET, EPIPE, ETIMEDOUT, EAI_AGAIN) are retried automatically instead of failing the run.
- Continue settled agents.
steer()now resumes a settled agent (completed, errored, aborted, stopped, turn-limited) that still has a live session, instead of requiring a re-spawn. The viewer footer/composer switches from "steer" to "continue" for settled agents. - Per-agent context and prompt inclusion. New
include_context_filesandinclude_system_promptfrontmatter fields on agent definition files override the global settings per agent: whether AGENTS.md/CLAUDE.md context files load as<project_context>, and whether the parent's system prompt is included (inherit, replace, or global mode). - Stop notes for never-started agents. Agents stopped before they started (queued stop, aborted spawn) now report that the task was NOT attempted instead of claiming partial output. Applies to tool results and background nudges.
Removed
deltaInputTokenssetting and delta estimation. Removed the vLLM-specific workaround that estimated input token deltas by subtracting consecutiveusage.inputvalues.
Changed
- Running Agents menu bulk actions grouped. The stop row sits above the clear-actions group.
- Case-insensitive agent type resolution. The
Agenttool'sagentparameter now resolves type names case-insensitively: the exact registered name wins; a single case-insensitive match resolves; two types differing only by case produce an error naming both candidates instead of a silent pick, and nothing spawns. Applies to the initial lookup, the mid-session re-scan, and worktree-targeted spawns.
Fixed
-
Model settings per-type provenance tag. When the session default shadows a project key, the per-type row now shows
[session](the value's true source) instead of a misleading[project]. -
Spawn options menu refreshes after a change. Setting or clearing any spawn option now rebuilds the row immediately, so "Default max turns" and "Default thinking level" show their new value and
[project]tag without reopening the menu. -
Default concurrency limit removable per target. The "Default concurrency limit" row now offers Edit limit / Remove limit like the per-provider and per-model rows, so the value can be cleared at the chosen level (session, global, project, or all) and fall through to the next layer.
-
Default max turns clearable per target. The "Default max turns" row's target picker now offers "Clear...", leading to a nested per-level picker (global, project, or all levels) so the value can be removed at a chosen level and fall through to the next layer, instead of requiring an empty submission.
-
Model settings "Set globally" label aligned. The entry now reads "Set globally (saves to config)", matching the target picker's "saves to" phrasing.
-
Target-picker wording. The global and project entries now read "Global (saves to config)" / "Project (saves to project config)", parallel with "Session (not saved)".
-
"(inherits parent)" no longer stored as a model value. In the Model Settings menu, picking "(inherits parent)" now deletes the key at the chosen level (session, global, or project) instead of persisting the literal sentinel string into the config file or session overrides; the effective model falls through to the next layer.
-
"All levels" clears never create a project file. Clearing a model or concurrency key at all levels in a trusted project without
.pi/subagents-lite.jsonpreviously wrote an empty project file out of nothing. A clear now skips the project layer entirely when no project file exists (only a set creates the file); an existing project file keeps today's behavior. -
Conversation viewer freeze from running agents menu. Viewer overlay now uses
{ overlay: true }so closing it restores the menu instead of clobbering it and freezing all input. -
View result bottom border. Fixed mirrored corner characters in the text viewer frame.
-
Running Agents menu skips separator rows.
Up/down navigation no longer lands on the blank separator rows between the agent list and the bulk actions; the cursor jumps from the last agent straight to the first bulk action row. The separator-skip mechanism is now a shared helper used by both the settings-menu wrapper and the Running Agents menu. -
defaultMaxTurnsfallback in tool execution path. Prevents failures when max turns is not explicitly set. -
Stale concurrency slots cleaned up. Removing a concurrency limit from config now frees the orphaned slots in-session.
-
outputThinkingBufferSizechanges apply live. The thinking-buffer size is now read from the config store at run time, so changing the setting takes effect without restarting pi. -
Rejected abort/steer promises swallowed. Session abort and steer calls no longer throw unhandled rejections when the session is already closed.
-
Qwen quota retry. Qwen
insufficient_quotaerrors containing "Allocated quota exceeded" are retried instead of failing immediately. These may be transient false positives when the quota check is eventually consistent.