Skill slash commands store a structural <skill>...</skill> wrapper in raw
user messages. The TUI uses parseSkillBlock() to split this into separate
SkillInvocationMessageComponent and UserMessageComponent siblings, but the
HTML export renderer passed the full raw text through markdown, causing
broken/dangling XML tags to appear in exported HTML.
Add parseSkillBlock() to the export template and render skill-invocation
and user-message as separate sibling blocks:
- Sidebar tree shows skill name + user prompt separately
- Content area shows a clickable skill-invocation block (collapsed by
default, markdown content on expand) followed by the user message
- Copy-link button preserved on the wrapper element
- Toggle tools (O key) expands/collapses skill invocations alongside
compaction and tool output blocks
Previously, registerProvider() overwrote the stored config for a provider,
so a models registration followed by a baseUrl/headers-only override lost
the models. After refresh(), only the override-only config was replayed,
causing extension-provided models to disappear.
Added upsertRegisteredProvider() that merges defined fields into the
existing stored config instead of replacing it. Fields absent from the
incoming config are preserved from the stored config.
Also adds regression tests for dynamic provider override persistence
across refresh.
Strip `index.ts` and `index.js` from extension display paths in both
compact and expanded views of the startup banner. This makes the list more
readable by removing redundant filename noise.
Changes:
- Add `formatExtensionDisplayPath()` helper to centralize path formatting
- Update `getCompactExtensionLabels()` to strip index files from segments
- Update expanded view formatting to use the new helper
- Add comprehensive tests for both views
Fixes#3549Fixes#3559
Add getCommandDiagnostics and getShortcutDiagnostics mocks to fix
'Cannot read properties of undefined' errors in InteractiveMode tests.
regression from 32a305cb
promptGuidelines bullets are appended flat to the Guidelines section
with no tool name prefix. Using 'Use this tool when...' is ambiguous
because the LLM cannot tell which tool 'this' refers to. Updated docs
and examples to use explicit tool names instead.
Rename BUILTIN_TOOLS to TEMPLATE_RENDERED_TOOLS to match what the set
actually represents: tools rendered directly by the HTML template instead of
pre-rendered through the TUI→ANSI→HTML pipeline.
Move grep and find off the template-rendered exclusion path so they use their
existing TUI renderCall/renderResult output in HTML export.
Add a dedicated HTML renderer for ls and keep it in the template-rendered set.
Unlike grep and find, rendering ls through the terminal-oriented Text component
introduced spacing artifacts in exported HTML due to full-width line padding,
so ls is rendered natively in the export template instead.
* feat(agent,coding-agent): add per-tool executionMode field to AgentTool and ToolDefinition
Add optional executionMode?: ToolExecutionMode to AgentTool and
ToolDefinition interfaces. Propagate through wrapToolDefinition and
createToolDefinitionFromAgentTool. No behavioral change yet — agent
loop will read this field in a follow-up.
* feat(agent): support per-tool executionMode override for sequential execution
When a tool defines executionMode='sequential', the agent loop
forces sequential execution of all tool calls in that batch,
even if the global config is parallel.
* feat(coding-agent): re-export ToolExecutionMode from @mariozechner/pi-agent-core
Makes the type available to extensions that want to set
executionMode on tool definitions.
* feat(coding-agent): add tic-tac-toe extension example with executionMode: sequential
Demonstrates per-tool executionMode: the agent plays via move/play
tool calls that share a cursor. Without sequential execution, play
can resolve before earlier moves finish, landing on the wrong cell.
* fix(coding-agent): surface models.json load errors on stderr in --list-models
When models.json has validation errors, --list-models silently
discarded custom models and overrides without any user-visible
feedback. Now prints the error to stderr via chalk.yellow warning
before listing available models.
* fix(coding-agent): allow custom models for built-in providers in models.json
Built-in providers (openrouter, anthropic, etc.) already have api and
baseUrl on every model, and auth comes from env vars / auth storage.
Relax validation so custom models under built-in providers don't need
redundant baseUrl, apiKey, or api fields. Inherit them from the first
built-in model for that provider.
fixes#2921
---------
Co-authored-by: Mario Zechner <badlogicgames@gmail.com>
Previously, getLatestNpmVersion() hardcoded a fetch to
registry.npmjs.org, which 404s for packages on alternate
registries (private, Verdaccio, GitHub Packages, etc.).
The error was silently swallowed, so users never saw update
notifications for these packages.
Replace the direct fetch with
via the existing runCommandCapture helper. This uses the same
registry resolution as npm install (reads .npmrc config chain),
respects the npmCommand setting, and runs with this.cwd for
correct .npmrc lookup.
Tests assumed renders complete synchronously after requestRender() +
nextTick + flush(), but commit 6f5f37f8 changed requestRender() to
schedule via setTimeout with a 16ms minimum interval. Tests reading
viewport state before doRender() runs saw stale data.
Add VirtualTerminal.waitForRender() helper that waits for the throttled
render to settle (nextTick + 20ms + xterm flush), and replace all
terminal.flush() calls after render-triggering actions with it.
Fixes 8 failing tests across overlay-short-content, tui-render, and
markdown test suites.
Update extensions.md and rpc.md to accurately reflect that ctx.hasUI is
true in RPC mode. Document missing unsupported/degraded ExtensionUIContext
methods: pasteToEditor, getAllThemes, getTheme, setTheme.
Co-authored-by: Mario Zechner <badlogicgames@gmail.com>
Do not overwrite editor text with the rewound user message after
navigateTree completes if the user has already typed something during
the summarization wait. Applies to both the /tree selector and the
extension-driven navigateTree handler.
docs: update changelog for PR #1169
Error messages for missing credentials and shell config now use
getAuthPath() and getSettingsPath() instead of hardcoded ~/.pi/agent/
paths, so they correctly reflect PI_CODING_AGENT_DIR when set.
* fix(tui): expand paste markers when opening external editor
Add getExpandedText() method to Editor that substitutes paste markers
with actual content. Use it in Ctrl-G external editor flow so users
see full pasted content instead of [paste #N ...] placeholders.
* docs: add changelog entries for #444
When cwd is `~/.pi/agent/` or a subdirectory, the global AGENTS.md file
was included twice in the system prompt.
`loadProjectContextFiles()` loads context files in two steps:
1. Explicitly loads from `getAgentDir()` (`~/.pi/agent/`)
2. Walks from cwd up to root, collecting all AGENTS.md/CLAUDE.md files
There was no deduplication. When cwd is at or below `~/.pi/agent/`, the
ancestor walk includes that directory again.
Fix: track seen paths with a Set and skip duplicates.