Commit graph

220 commits

Author SHA1 Message Date
robopipi[bot]
c1810bf70f
feat(coding-agent): let inline ctx.ui.custom() components report blocked program status (#11471)
Inline `ctx.ui.custom()` components never report pi as blocked through
OSC 7501 program status. This is on purpose, because the same API hosts
loaders. As a result, a custom dialog that waits for the user (an
approval prompt, the `question.ts` example) shows up as `working`, and
the terminal cannot tell that pi needs input.

The extension dialog stack already stores a blocked status for each
dialog and reports the visible one. This change adds an optional
`blocked` option to `ctx.ui.custom()`:

```ts
ctx.ui.custom(factory, { blocked: { kind: "question", message: "Pick a color" } });
```

The inline branch of `showExtensionCustom()` passes it to
`pushExtensionDialog()`. Components without the option behave as before.
Overlays ignore the option because they are not part of the dialog
stack. `docs/tui.md` documents the option.

Testing:
- Added a test to `test/interactive-mode-extension-dialogs.test.ts`:
  - A custom component that opts in reports `blocked`.
- A plain custom component stacked on top of it clears the blocked
status.
  - Closing the plain component restores the blocked status.
  - Closing the opted-in component clears it.
- The test fails without the change to `interactive-mode.ts` and passes
with it.
- `npm run check`: biome and lint pass, and there are no type errors in
coding-agent. The only errors are existing type errors in
`packages/ai/test` from locally generated model data. They are not
related to this change.

Fixes #11428

Requested by @badlogic

Co-authored-by: triagent <triagent@localhost>
2026-10-27 09:27:28 +01:00
Ville Penttinen
64627838b2
feat(coding-agent): add messageId and timestamp to markdown transformer context
* feat(coding-agent): add messageId and timestamp to markdown transformer context

* fix(coding-agent): update compaction render test for messageMeta argument

---------

Co-authored-by: Petr Houška <houskape@gmail.com>
2026-10-22 20:49:38 +02:00
Petr Houška
22dc6c26f3 fix(coding-agent): expose @earendil-works/pi-ai/models in the extension loader
Extensions importing the public /models subpath (e.g. clampThinkingLevel)
failed with "Cannot find module" because the loader aliased/virtualized
only the pi-ai root, /compat, /oauth, and /providers/all entrypoints.
Add /models to the jiti aliases and the embedded virtual module map,
plus a regression test importing it without a local pi-ai install.

Closes #11156

Co-authored-by: Dante-dan <dantedan@users.noreply.github.com>
2026-10-20 21:47:52 +02:00
David Brailovsky
a447ba11f3
fix(coding-agent): emit before_agent_start for runs started by custom messages (#10739)
Runs started by pi.sendMessage(..., { triggerTurn: true }) skipped before_agent_start. After their first tool call, the next-turn refresh fell back to the base prompt options and patched away the sections handlers had added, changing the system prompt mid-run and breaking the provider prompt cache.

These runs now go through the same setup as prompt(): compaction check, before_agent_start, tool loadout, nextTurn messages, handler messages, and the system patch. BeforeAgentStartEvent is a union on messageType ("user" or "custom"); custom events carry the starting message.

The session counts as busy from the start of setup, so messages sent while handlers run go into the starting run instead of starting a second one, and an abort requested meanwhile aborts the run once it starts.

closes #10267, closes #5581, closes #10639, closes #10289
partly fixes #10606
2026-10-12 09:53:24 +02:00
Armin Ronacher
24382bedd0 refactor(codemode,coding-agent): decouple MCP from codemode
Tools that reach other tools declare it with reachesTools(input); MCP uses it to wait for the servers a call needs and to decide which codemode or tool_search tool to activate, instead of parsing codemode scripts and comparing parameter schemas. Namespaces get aliases, replacing codemode's MCP-specific __ suffix rule.

pi-codemode no longer knows MCP: MCP_TYPESCRIPT_PREAMBLE and mcpStructuredContentSchema() are removed, and the MCP result schema describes itself, with the server's local $refs relocated so they resolve as before.
2026-10-12 09:19:30 +02:00
Mario Zechner
503c605528 feat(tui,coding-agent): report program status via OSC 7501
Report idle, working, blocked, done, and error to terminals that support
the Program Status Protocol. ProcessTerminal sends the support query with
the keyboard query and reports only after the terminal answers before DA1;
PI_PROGRAM_STATUS=1|0 overrides detection. Interactive mode reports runs,
compaction, extension dialogs, and logins. agent_settled now carries
aborted so cancelled runs report idle.

closes #10607
2026-10-07 19:05:41 +00:00
Mario Zechner
36a686ee8d feat: record response, tool execution, and durable task times
pi-ai's AssistantMessageEventStream sets AssistantMessage.durationMs with a
monotonic clock for every API implementation. The agent loop and the durable
tool task set ToolResultMessage.durationMs around execute(). Durable task
records carry startedAt/endedAt stamped by the Session. The coding agent's bash
renderer shows Took from the recorded duration, also after a reload.

closes #10549
2026-10-06 19:28:54 +02:00
Ramiz Wachtler
18336987ad
fix(coding-agent): apply outputPad to all transcript blocks (#10557) 2026-10-06 17:27:55 +02:00
Armin Ronacher
c30840c2eb fix(coding-agent): keep hidden tools out of prompt rules and skills hint
Rules and the tool list follow the declared tools (active minus
hiddenDeclarations). The skills hint names no tool when the reader is
hidden. Codemode shows each tool's prompt guidelines with its
declaration, via the new ToolLoadout.getPromptGuidelines().

closes #10343
2026-10-05 18:50:17 +02:00
Armin Ronacher
11449730c8 fix(coding-agent): render MCP tool calls before their server connects
Add pi.registerToolRenderer((toolName, next) => renderers), which chooses the
renderers for calls to any tool, including tools that are not registered.
Resolvers run in extension load order; next() returns what the remaining
resolvers, then the registered tool, would use. Interactive mode and HTML
export both resolve through it.

The MCP extension uses it to render every mcp__<server>__<tool> call with the
MCP renderers, so calls in a resumed session no longer render fully expanded
before their server connects, or for good if it never does.

closes #10285
2026-10-03 13:54:18 +02:00
Armin Ronacher
b29db895c5 fix(coding-agent): align MCP tool names with codemode identifiers
MCP tool and namespace names now replace - with _ like Codex, so the
pi tool name is also the codemode identifier. Tools of a server whose
names collide all get a hash suffix, and server names that differ only
in - and _ are rejected.

closes #10239
2026-09-30 18:40:06 +02:00
David Brailovsky
dc83372f8f fix(coding-agent): validate extension command registration
Reject extension commands without a non-empty string name or a handler
at registration, instead of letting them crash the editor when typing /.

fixes #10054
2026-09-30 15:02:08 +02:00
Armin Ronacher
1c7e7df765 feat(coding-agent): list MCP servers instead of their tools in codemode
MCP codemode exposure no longer lists tools, tool counts, or server
instructions in the codemode description. Servers are listed by name and
an optional mcp.json description; scripts find tools with searchTools()
and read instructions with describeNamespace(). codemode-deferred is an
alias for codemode.

refs #10212
2026-09-30 13:54:02 +02:00
Armin Ronacher
4259686d92
refactor(coding-agent): resolve built-in extensions as builtin:<name> paths (#10159)
Built-in extensions (mcp, llama.cpp, codemode, tool-search) are now extension resources like files: the package manager resolves them as builtin:<name>, the extensions setting disables them with -builtin:<name> (per project too), pi config lists them, and --no-extensions turns them off unless loaded with -e builtin:<name>. They load after project trust is resolved and after file and package extensions.

Built-in extensions and tools are named builtin:<name> in errors, diagnostics, RPC source info, and bug reports.
2026-09-29 10:51:01 +02:00
Armin Ronacher
8562bcf66a feat(coding-agent): codemode and MCP
This adds codemode and MCP support to pi. Codemode (packages/codemode) runs
model-written JavaScript in a QuickJS wasm VM inside a worker. From there the
script calls pi's tools as async functions, uses a per-session store, and can
read the model catalog and run classifiers. The codemode tool in coding-agent
is compatible with Codex's exec tool, and codemode.mode works like Codex's
tool modes (on or only). Large results are written to a JSON temp file. MCP
(packages/mcp) is a standalone client for stdio and streamable HTTP servers,
with OAuth.

The core only gets general mechanisms; codemode, tool_search and MCP are
built-in extensions that use them. Other extensions can replace these
built-ins. Tools declare an exposure: direct, model-only, codemode, deferred
or hidden. prepareLoadout() lets an orchestrating tool change which tool
declarations the model sees. ctx.executeTool() runs nested calls through
validation and the tool_call/tool_result hooks. Those calls emit events with
parentToolCallId and are recorded as bounded nestedCalls on the parent
result, which compaction and HTML export use. Tools can also return
structuredContent with an outputSchema, and can report errors with isError
instead of throwing. MCP servers come from mcp.json (global, or per project
after the project is trusted) or from pi.registerMcpServer(). They are
managed with /mcp and pi mcp list|login|logout, and their runtimes load on
first use.

Closes #10040
2026-09-29 09:12:50 +02:00
Armin Ronacher
540e174c72
feat(coding-agent): Virtual models (#10035)
This adds experimental support for virtual models. A virtual model is a catalog entry that an extension registers with pi.registerVirtualModel(). It does not talk to a provider itself; for every request it picks a physical model and thinking level. The motivation is to make routing policies pluggable: plan on a strong model and implement on a cheap one, pick a model with a classifier, or move to a larger window when the context grows. Today this needs model switching by hand or hacks in prepareRequest.

The selection stays virtual: model_change records it, resume restores it, and each response records the physical model and thinking level that produced it. Router state can be stored on the session branch, so it follows /tree and forks and survives compaction. Context limits, compaction and image sizing use the physical model a request was routed to. examples/extensions/jev-router.ts shows a full router that uses the Jev classifier to pick Sol or Terra for planning and hands off to Luna after the first edit. docs/virtual-models.md describes the API.
2026-09-28 23:30:45 +02:00
Armin Ronacher
a328aa89ad
feat(ai,coding-agent): unify image and classifier model infrastructure (#9948) 2026-09-23 17:41:19 +02:00
David Brailovsky
002fc83852
feat: expose provider stream events to extensions (#9901)
Add onProviderStreamEvent through pi-ai and agent core, and surface
provider_stream_event to coding-agent extensions.

Closes #9784
2026-09-23 16:03:30 +02:00
Armin Ronacher
8d897edaa6 fix(coding-agent): prevent duplicate extension runtimes (closes #9863) 2026-09-23 15:33:56 +02:00
Armin Ronacher
aef5fc429b
fix(coding-agent): keep prompt and tool state across context handlers (#9846)
Since 0.86 the prompt and tool declarations live in transcript system
messages, so a context handler that filters or slices messages could drop
them. After extension-driven compaction this sent requests without built-in
tools and made Codex emit raw tool-call text.

context handlers now see the conversation only. An unchanged list keeps the
transcript as is; a changed list gets the replayed prompt sections and tool
declarations as one leading system message. Handler-added system messages
are kept after it.

Add context_with_system, which runs after every context handler on the full
transcript and sends its result verbatim, for extensions that need to edit
system messages per request. Dropping the leading system message is reported
as an extension error.

closes #9789, closes #9822
2026-09-21 17:14:22 +02:00
Mario Zechner
466db0fecd feat: add canonical session context boundaries
Make SessionManager projections authoritative for provider requests, add append-only context edits and actionable turn boundaries, and preserve existing queue scheduling during continuation and recovery.
2026-09-21 16:59:20 +02:00
Armin Ronacher
f5c946480c feat(ai,coding-agent): add image input limits (closes #9631) 2026-09-20 22:59:16 +02:00
Armin Ronacher
40c256cccb feat(coding-agent): defer extension loader dependencies
Load ordinary jiti lazily on Node while retaining jiti/static for Bun and SEA binaries. This closes #9540.
2026-09-19 23:25:47 +02:00
Armin Ronacher
c596d09d9c
feat(coding-agent): add prompt cache warming (#9668) 2026-09-19 21:18:15 +02:00
Ramiz Wachtler
46c9de402b
feat(coding-agent): add event handler unsubscribe (#9630) 2026-09-17 21:44:26 +02:00
Christian Klotz
509ee2bd0b
fix(coding-agent): fail closed on user bash hook errors (#9662)
* fix(coding-agent): fail closed on user bash hook errors

Prevent failed execution-routing hooks from falling back to the local shell.

Fixes #9068

* fix(coding-agent): validate user bash hook results

* docs(coding-agent): clarify user bash result semantics

* docs(coding-agent): streamline user bash semantics

* fix(coding-agent): strengthen user bash regressions

* docs(coding-agent): clarify user bash breaking change
2026-09-16 17:21:17 +01:00
Armin Ronacher
9e05370b29
Mid conversation system messages (#9548)
This change makes system prompt text and tool changes part of the transcript rather than silently rewriting its starting conditions. This lets Pi record when instructions changed or tools became available, restore that state after resuming or navigating branches, and preserve cached prompt prefixes where the upstream supports it.
2026-09-16 15:54:07 +02:00
Christian Klotz
4c2d91339a
fix(coding-agent): export extension event hook types (#9642)
* fix(coding-agent): export extension event hook types

Fixes #9511

* fix(ai): stabilize Bedrock cache cost regression

* fix(ai): honor Bedrock profile pricing in cache test
2026-09-15 22:47:59 +01:00
David Brailovsky
acaa253cc8 fix(coding-agent): validate extension tool parameter schemas
Reject malformed extension tools during registration instead of allowing them to break provider request serialization.

Fixes #9300
2026-09-09 12:15:18 +02:00
David Brailovsky
8c08d0645a Merge remote-tracking branch 'origin/main' into dev 2026-09-03 07:58:51 +00:00
Ramiz Wachtler
8d1b1178cd
docs(coding-agent): clarify session-scoped model/thinking-level changes (#9009)
- fixes #8976
2026-09-02 14:53:49 +02:00
Cristina Poncela Cubeiro
758a0ee9b7 Merge branch 'main' into dev
# Conflicts:
#	packages/agent/CHANGELOG.md
#	packages/ai/scripts/generate-models.ts
#	packages/ai/src/providers/cloudflare-ai-gateway.ts
#	packages/ai/test/zai-coding-plan-models.test.ts
#	packages/coding-agent/src/modes/interactive/interactive-mode.ts
#	packages/tui/src/tui-alt-screen.ts
2026-08-28 13:19:43 +02:00
Cristina Poncela Cubeiro
ccfe79ed23
feat(extensions): ui prompt events (#8355)
* feat(extensions): ui prompt events

* fix: handlers should not delay the prompt
2026-08-27 11:28:05 +02:00
Armin Ronacher
a789067a0d fix(coding-agent): support bundled experimental processes 2026-08-24 14:17:17 +02:00
Armin Ronacher
80e62761f7
feat(coding-agent): add optional PowerShell tool (#8512) 2026-08-24 12:27:03 +02:00
Petr Houška
81152d88bb
docs(coding-agent): clarify custom footer usage APIs (#8482)
Fixes #8392
2026-08-23 23:34:08 +02:00
yaogangqiang
a69bef789b
fix(coding-agent): discard failed extension factory state (#8424) 2026-08-23 12:39:42 +02:00
Armin Ronacher
7d4c0e05dd
feat(coding-agent): bundle Node runtime (#8474) 2026-08-22 21:19:38 +02:00
Mario Zechner
c061328981 fix(coding-agent): load extensions in Node SEA hosts, closes #8237 2026-08-18 16:48:18 +02:00
Cristina Poncela Cubeiro
a6b1dbceb1
fix(extensions): emit compaction failed for extensions (#8241)
* fix(extensions): emit compaction failed

* changelog yeet
2026-08-17 13:10:08 +02:00
Cristina Poncela Cubeiro
f47faf459f
fix: register flag type mismatch (#8123) 2026-08-17 09:42:51 +02:00
Duncan Ogilvie
b987ead358
feat(agent): expose expandPromptTemplates in sendUserMessage (#7857) 2026-08-11 11:14:28 +02:00
muyiyr
1eb988cfe8
feat(agent): allow blocked tool calls to terminate (#7715)
Closes #5998
2026-08-06 17:14:48 +02:00
Armin Ronacher
b0bd0ff9d5 fix(coding-agent): only label known subscriptions in footer 2026-08-06 07:47:35 +02:00
Ted
6ca423447f
event bus leak fix (#7656) 2026-08-05 22:23:44 +02:00
muyiyr
f27aaf66c0
docs(coding-agent): document streamSimple hook contract (#7576)
closes #7372
2026-08-04 08:44:41 +02:00
Mario Zechner
fed6009cc9 fix(coding-agent): make model refresh cancellation caller-owned
Add generation-safe catalog publication, cancellable auth and storage operations, locally consistent credential mutations, and cache-first interactive model flows.
2026-08-04 00:03:52 +02:00
Mario Zechner
74caa2649f fix(coding-agent): validate package manifests
closes #7187
2026-07-30 22:43:22 +02:00
Alexey Zaytsev
714978bf51
Markdown api (#7231)
* feat(tui): export bundled Marked parser

* feat(coding-agent): add width-aware Markdown transformers

---------

Co-authored-by: Mario Zechner <badlogicgames@gmail.com>
2026-07-30 22:39:04 +02:00
Christian Klotz
32f3a97282
feat(coding-agent): add comparative Pi eval harness 2026-07-30 01:17:54 +03:00