Commit graph

2249 commits

Author SHA1 Message Date
Armin Ronacher
4ccdc212e7 feat(agent,coding-agent): replace nestedOnly with tool exposure
AgentTool.nestedOnly is replaced by AgentContext.nestedTools, the tools callable through executeTool. Tool definitions declare an exposure (direct, model-only, codemode, deferred, hidden). The active set is now the declared set; codemode and deferred tools are callable from codemode whenever registered, so tree navigation, resume and fork cannot drop them.

MCP servers accept deferred and hidden exposure, withdraw tools by re-registering them as hidden, and mcp.json gains autoEnableCodemode.
2026-09-27 17:38:48 +02:00
Armin Ronacher
be49a2509d fix(mcp,coding-agent): bound SSE event data and report codemode spill errors
The SSE parser only limited the partial line, so a stream of short data: lines without a blank line could grow without bound. The event data size is now checked as lines arrive.

When saving a truncated codemode return value to a temp file fails, the truncation notice now names the error.
2026-09-27 17:38:40 +02:00
Armin Ronacher
d20d3ada42 fix(coding-agent): keep codemode MCP tools on tree navigation, cap codemode memory
Restoring tools from the transcript dropped nestedOnly tools because they are never declared to the model, so /tree navigation turned off codemode-exposed MCP tools. Active nestedOnly tools are now kept.

Codemode scripts now run with a 256 MiB QuickJS memory limit instead of growing up to the 4 GiB wasm32 ceiling inside pi's process.
2026-09-27 13:59:40 +02:00
Armin Ronacher
423b99797e fix(coding-agent): validate MCP server URLs and re-prompt sign-in on repeated 401
An invalid url made the OAuth store throw while creating connections, which
failed MCP startup for every server. OAuth servers that still answer 401
after a refresh now show as needing sign-in instead of failing each call.
2026-09-27 12:44:42 +02:00
Armin Ronacher
b9bbc35844 fix(coding-agent): make MCP connections and OAuth refresh reliable
- Share one OAuth refresh between concurrent requests and skip it when the
  token was already replaced, so rotating refresh tokens do not sign the
  user out; refresh tokens before they expire
- Treat insufficient_scope as needs-sign-in and request the new scope on
  /mcp login instead of refreshing
- Only list tools for servers that declare the tools capability
- Retry HTTP connects that fail transiently; show dropped connections as
  disconnected
- Deactivate tools a server withdraws on list_changed and restore them
- Keep sanitized tool names unique; default missing input properties
2026-09-27 12:41:07 +02:00
Armin Ronacher
6e6c5a9fe3 Merge branch 'main' into codemode-and-mcp
# Conflicts:
#	packages/coding-agent/install-lock/package-lock.json
#	packages/coding-agent/npm-shrinkwrap.json
2026-09-27 12:26:43 +02:00
Armin Ronacher
2b0a123de9 feat(coding-agent): remove themes section from startup banner 2026-09-26 14:37:30 +02:00
Armin Ronacher
bf8e4b9531
feat(coding-agent,tui): System theme (#10067)
* feat(coding-agent,tui): add system theme derived from terminal colors

The new default system theme builds pi's colors from the terminal's reported foreground, background, and ANSI palette. Tokens take their hue and relative saturation from a palette slot; lightness is placed by OKLab lightness difference and WCAG 2 contrast minimums. Terminals that report only a background get built-in hues, and terminals that report nothing get ANSI indices with faint secondary text.

The TUI queries OSC 10, 11, and 4 in one burst ended by DA1, so replies complete in one round trip, and reports replies that arrive after the timeout. Startup never waits: the system theme starts in grayscale and updates when colors arrive. Light/dark detection now uses the reported colors instead of the ?996 query; mode 2031 notifications trigger a new query.

* fix(coding-agent): wait for terminal colors before building the startup header

The header and startup notices bake theme colors into their text. When the color replies arrived after they were built, as in Windows Terminal, they stayed grayscale. Startup now waits for the first color query, which ends at the DA1 reply or after 100 ms.

* fix(coding-agent): rebuild header and notices on theme changes

The startup header, loaded resources, and chat notices baked theme colors into their text, so they kept the old colors after a theme switch or when the system theme received the terminal's colors. They now use ThemedText, which rebuilds its text from a function whenever the UI is invalidated.

* fix(tui): keep focus on components that forward mouse events to children

A component that forwards a mouse event to a child it hosts, such as SettingsList with an open submenu, left keyboard focus on the child. When the host removed the child, focus stayed on a detached component and all keys were lost. The forwarding component now keeps focus, like delegating containers do.

* feat(coding-agent): describe the system theme in the theme selector

* feat(coding-agent): list the system theme above automatic in the theme selector

* refactor(coding-agent,tui): remove leftovers of the light/dark startup detection

Theme detection only reports dark or light now; the source and confidence fields only served saving the detected theme. The first-time setup no longer shows the detected appearance. Removes the TUI's unused queryTerminalColorScheme(), queryTerminalBackgroundColor(), queryTerminalForegroundColor(), and parseOsc11BackgroundColor(); queryTerminalColors() covers them.

* feat(coding-agent): match the reviewed system and light/dark theme design

The system theme now follows the reviewed design: color families with OKHSL saturation curves, palette slots per family, contrast rules per token and panel, relaxation for mid-gray backgrounds, and the terminal foreground for body text. Each contrast level is a target-lightness curve fitted to the reviewed output. The built-in dark and light themes use the reviewed Pi dark and light colors.

* feat(coding-agent): show the pi logo in the startup header

A two-line pixel logo replaces the app name. Its first line carries the version, its second line the first line of key hints.

* feat(tui,coding-agent): support OKHSL colors in themes

parseColor() accepts okhsl(H S L), and okhslColor() and colorToOkhsl() construct and read OKHSL colors. OKHSL saturation is relative to the sRGB gamut, so every value is in gamut. Theme files accept okhsl() values; HTML exports convert them to hex. The OKHSL code moves from coding-agent into pi-tui, where colors.ts now shares its Oklab conversion instead of keeping a second copy.

* refactor(coding-agent): write the built-in themes in OKHSL

The built-in dark and light themes use okhsl() values, with variables for colors that several roles share, so they read as color families and serve as editable templates. Near-identical values collapsed into one; no color changes visibly.

* refactor(coding-agent,tui): simplify terminal color and theme code

Share the terminal color query between startup and the theme controller, merge the query's resolve/late-reply state into one callback, keep a single global for terminal colors, use oklab.ts arrays directly in colors.ts, and drop leftover helpers and exports.

* fix(coding-agent): use one terminal light/dark decision everywhere

Theme pairs, the system theme, and Theme.appearance now share getTerminalTheme(): the reported background decides, then the terminal's light/dark report, then COLORFGBG, then dark.

COLORFGBG is classified by palette index like Vim (0-6 and 8 dark) and only reads the last field, so rxvt's "default" no longer picks up the foreground index.

Simplify the tests added on this branch.

* fix(ai): use an OpenRouter model that still exists in beta test

OpenRouter removed anthropic/claude-3-haiku, which broke type checking in CI after model regeneration.
2026-09-26 13:33:47 +02:00
Armin Ronacher
7799d796df fix: harden nested tool calls, codemode, and MCP connections
- Serialize nested calls to sequential tools (or all nested calls in sequential mode) per tool batch.
- Let codemode run without a session manager, starting from an empty store.
- Resolve the MCP OAuth client secret only on token refresh, so one bad secret no longer blocks all servers.
- Report MCP transport errors without failing pending requests; a broken POST SSE stream fails only its request.
- Start a new MCP session and retry once when the server reports the session expired.
2026-09-25 17:42:07 +02:00
David Brailovsky
ff72faba28 fix(coding-agent): save new session file at the first user message
A new session was only written to disk once the first assistant message
existed. If pi exited during the first turn (Ctrl+C twice while streaming,
or the process was killed), the user's prompt was lost and the session
never appeared in /resume.

The file is now created as soon as the session has a user or assistant
message. A session with only setup entries (model, thinking level) still
stays in memory, so starting pi and quitting without chatting leaves no
file. Forking uses the same rule through a shared helper, so the two paths
cannot drift apart and write the header twice (#1672).

closes #10000
2026-09-25 16:27:51 +02:00
Christian Klotz
ddba596187
fix(coding-agent): honor truecolor in custom themes (fixes #9973) (#10039) 2026-09-25 14:44:41 +01:00
Armin Ronacher
362e2bdc80 feat(coding-agent): spill truncated codemode results to a JSON temp file
Like bash output, a codemode result over 50KB or 2000 lines keeps its head in the tool result and writes the full return value as JSON to a pi-codemode-<id>.json temp file, referenced in the output and in details.fullOutputPath.
2026-09-25 15:02:51 +02:00
Armin Ronacher
350aa4674d feat(coding-agent): expose the model catalog and classifiers to codemode
Scripts get models.getModelsOfType/getAvailableOfType/getModelOfType/classify, mirroring ModelRuntime. The host resolves models by provider and id so scripts cannot redirect credentials, strips headers from listed models, and runs at most four classifications per script at once. pi-codemode gains namespaced globals, spread arguments, and explicit signatures.
2026-09-25 15:02:51 +02:00
Armin Ronacher
9163a000f2 feat(coding-agent): add @options source format and session store to codemode
Codemode input is now the script itself, optionally starting with a // @options {"timeout": N} line, and the tool declares a Lark grammar so capable models write raw JavaScript. Scripts can keep JSON values with store()/load(); successful writes are appended as codemode-store custom entries and read back from the current branch.
2026-09-25 15:02:51 +02:00
Armin Ronacher
de3491ff12 perf(coding-agent): load MCP and codemode runtimes on first use
The MCP client, transports, and OAuth code load only when mcp.json lists a server, and connecting starts after the first render. The codemode sandbox loads on the first script; the tool description only needs the new pi-codemode/declarations entry. TUI startup matches main again.
2026-09-25 15:02:51 +02:00
Armin Ronacher
b16d985d42 feat(codemode): run scripts in a QuickJS wasm VM inside the worker
Replaces the node:vm context with quickjs-wasi, so the sandbox is a separate wasm instance instead of a same-process V8 context. The worker stays to keep the host thread responsive; a shared interrupt flag stops spinning scripts on Bun, where worker.terminate() cannot interrupt wasm.

The Node bundle and the Bun binary build the worker as a separate entrypoint, and the Bun binary embeds quickjs.wasm.
2026-09-25 15:02:51 +02:00
Armin Ronacher
8cd0ed48de feat(coding-agent): add OAuth sign-in for remote MCP servers
HTTP servers without an Authorization header use OAuth. Connections send the stored token and refresh it after a 401; /mcp login runs the browser authorization code flow (PKCE, dynamic client registration) with a loopback callback or a pasted redirect URL, and /mcp logout removes the credentials. Tokens are stored per server URL in mcp-auth.json. Pre-registered clients are configured with the oauth block.
2026-09-25 15:02:51 +02:00
Armin Ronacher
e5a252c102 feat(coding-agent): highlight JSON return values in codemode output 2026-09-25 15:02:51 +02:00
Armin Ronacher
27d2914457 feat(coding-agent): connect MCP servers and expose them through codemode
Adds a built-in mcp extension that reads mcp.json (agent dir, and .pi/mcp.json for trusted projects) in the common mcpServers format, connects stdio and streamable HTTP servers at session start, and registers their tools as mcp__<server>__<tool>. Calls go through the regular tool pipeline, so hooks and permission extensions apply. /mcp shows server status.

By default a server's tools are codemode-only: the new nestedOnly tool flag keeps them executable for other tools but out of the model's tool declarations, and pi activates the codemode tool for them. "exposure": "direct" declares them to the model as well. structuredContent from tools with an outputSchema reaches codemode scripts as data.
2026-09-25 15:02:51 +02:00
Armin Ronacher
138771cd8a feat(coding-agent): add codemode tool
Adds a built-in, opt-in codemode tool that runs model-written JavaScript in the codemode sandbox. Scripts call the other active tools as tools.<name>(args), including concurrently with Promise.all; only the return value, console output, and images attached with image() reach the model.

Nested calls run through the agent loop via a new AgentToolContext (5th execute argument, ctx.executeTool for extension tools), so argument validation and the beforeToolCall/afterToolCall hooks apply. Hooks and tool_call/tool_result events carry the parent call id.

Tools can declare outputSchema and return structuredContent; codemode passes that to scripts and falls back to text content otherwise. The codemode package gains globals, declaration rendering from JSON Schema, and optional deadlines.
2026-09-25 15:02:51 +02:00
David Brailovsky
e473b5cd8b feat(coding-agent): report prompt disposition in RPC responses
Successful RPC prompt, steer, and follow_up responses include
data.disposition ("handled", "queued", or "started" for prompt), so clients
know whether to wait for agent_settled.

fixes #9098
2026-09-25 14:53:11 +02:00
Armin Ronacher
ca7460d16b feat: build with TypeScript 7 and run sources with plain node
Replace the tsgo native preview with typescript@7.0.2 and port the check scripts to the TS 7 API. Target ES2024, drop useDefineForClassFields: false and unused decorator options, and enable verbatimModuleSyntax. Replace tsx with node plus the source resolver hook, passed to --import as a file URL.

closes #9965
2026-09-25 13:14:33 +02:00
David Brailovsky
49681e1b71 fix(coding-agent): hide line range for full-file read calls with null offset/limit
Strict tool schemas make models send null for omitted optional fields.
The read renderer only treated undefined as missing, so full-file reads
rendered as "path:1".

fixes #9996
2026-09-25 11:36:43 +02:00
David Brailovsky
92e8d4f02a fix(coding-agent): stop RpcClient skipping listeners on unsubscribe
closes #9990
2026-09-25 11:27:10 +02:00
David Brailovsky
f444ea5eaf fix(coding-agent): use per-ref cache folders for pinned temporary git extensions
Temporary git extensions (-e git:...@ref) were cached in a folder keyed
only by host and repo path. After changing the pinned ref, pi reused the
old checkout without refreshing it and kept loading the first downloaded
commit. Include the ref in the temporary folder hash so each ref gets
its own checkout. Unpinned sources keep their existing folder.

closes #9982
2026-09-25 10:53:32 +02:00
Ramiz Wachtler
b2bd111f2d
feat(coding-agent): add hidden-message toggle to HTML exports (#10020) 2026-09-24 23:18:25 +02:00
Armin Ronacher
5674690966
feat(tui,coding-agent): add color values and theme styling (#8398)
Expose theme colors as values and add theme.style() for combined styling.

- @earendil-works/pi-tui gains a Color type (palette index, sRGB, OKLCH) with parseColor(), mixColors(), colorToHex(), colorToRgb(), styleText() and related helpers.
- Theme JSON accepts #rgb and oklch(...) values and an optional appearance ("dark" or "light"), detected from the theme colors when omitted.
- theme.style() combines tokens or concrete colors with text attributes; theme.colors exposes concrete colors, including the terminal's reported default colors (OSC 10/11) for tokens set to "".
- Terminals with TERM=*-direct are detected as truecolor.
2026-09-24 14:42:22 +02:00
Armin Ronacher
8676a0dcd8 fix(coding-agent): require advertised X11 clipboard images
closes #9786
2026-09-24 09:15:58 +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
David Brailovsky
d192bd6dca
fix(coding-agent): avoid Fable split-turn summary refusals (#9908)
Separate conversation content from instructions and replace prefix/suffix wording with continuation-oriented summarization guidance.

Hopefully this avoids the refusals.

Fixes #9652
2026-09-22 16:52:07 +02:00
Christian Klotz
25cc5c7bf4
docs(coding-agent): refresh documentation (#9898)
* docs(coding-agent): improve getting started documentation

* docs(coding-agent): correct getting started details

* docs(coding-agent): clarify SDK entry point

* docs(coding-agent): restructure guides and references

* docs(coding-agent): improve getting started guides

* docs(coding-agent): refresh integration guides

* docs(coding-agent): improve terminal and CLI guides

* docs(coding-agent): refresh customisation guides

* docs(coding-agent): clarify project trust terminology

* docs(coding-agent): simplify customisation guidance

* docs(coding-agent): improve runtime and reference guidance

* Fix settings reference

* feat(coding-agent): add Crowdin documentation sync

* docs(coding-agent): separate CLI and slash command references

* docs(coding-agent): correct compaction reference

* docs(coding-agent): streamline package documentation

* docs(coding-agent): split RPC reference documentation

* Update configuration docs

* Shorten config docs

* docs(coding-agent): refine configuration references

* docs(coding-agent): streamline settings reference

* docs(coding-agent): clarify configuration reference

* docs(coding-agent): clarify project trust exception

* docs(coding-agent): simplify keybindings reference

* docs(coding-agent): remove Crowdin integration

* docs(coding-agent): turn themes reference into guide

* docs(coding-agent): consolidate model and authentication docs

* docs(tui): require Component.invalidate() (fixes #9358)

* docs(coding-agent): document offline catalog behavior (fixes #8684)

* docs(coding-agent): preserve established documentation routes

* docs(coding-agent): reorganize documentation navigation

* docs(coding-agent): correct audited behavior

Clarify provider, session, local-model, Termux, TUI, SDK, debug, and extension behavior. Simplify the documentation audit to report only clear user-visible contradictions.

* docs(coding-agent): fix broken documentation links
2026-09-22 16:48:19 +02:00
Ramiz Wachtler
e40126f578 fix(coding-agent): reject invalid --mode values
fixes #9045
2026-09-22 08:29:57 +02:00
Armin Ronacher
1a584a7a56 feat(ai,coding-agent): add Grok 4.7 support 2026-09-22 00:07:34 +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
Mario Zechner
10d1ad621f feat: add transactional replicated state 2026-09-21 16:07:59 +02:00
Christian Klotz
b6419322e6
fix(coding-agent): report invalid prompt frontmatter (#9830)
Fixes #9354

Co-authored-by: Geet Khosla <geetkhosla@gmail.com>
2026-09-21 15:22:17 +02:00
Christian Klotz
1e0fe20497
fix(coding-agent): allow offline bug report exports (#9841) 2026-09-21 14:54:57 +02:00
Armin Ronacher
c7cdb460aa fix(coding-agent): reject bug reports offline 2026-09-21 10:49:12 +02:00
David Brailovsky
47a18e37b1 fix: require complete GIF image signatures
Require GIF87a or GIF89a headers to avoid classifying text files beginning with GIF as images.

Fixes #9755
2026-09-21 10:30:42 +02:00
Armin Ronacher
63787ee6ba feat(coding-agent): identify extensions in crash stacks 2026-09-21 01:00:43 +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
3390bd9363 fix(coding-agent): skip late cache warming refreshes 2026-09-20 15:53:22 +02:00
Armin Ronacher
6dff740fab fix(coding-agent): restore OSC 52 clipboard fallback for headless sessions
3349e1db1 (#9618) limited OSC 52 to SSH/mosh so a desktop terminal that ignores
it no longer reports a false success. That also disabled the only clipboard
route for containers and WSL without WSLg, which have no display to gate on.

Emit OSC 52 again on display-less Linux. On WSL, write the Windows clipboard
through PowerShell (verified, no OSC 52 size cap), preferring OSC 52 in
Windows Terminal where it is known to work. Desktop sessions with a display
still report the failure.

closes #9688
2026-09-20 12:42:15 +02:00
Armin Ronacher
d875512cc4 fix(coding-agent): suppress bug hints for expected failures 2026-09-20 12:06:14 +02:00
Alexey Zaytsev
b73412a378
feat(ai,coding-agent): add Meta provider with Muse subscription OAuth (#9096)
Device authorization flow against auth.meta.com mints a Model API key via the Muse Code key-mint endpoint. Identity token stored as refresh, minted key as access; daily re-mint via the standard OAuth scheduler. Identity is non-renewable (no refresh grant), so mint 401/403 directs to /login meta. Models sourced from models.dev; default muse-spark-1.3.
2026-09-20 11:13:43 +02:00
Armin Ronacher
d1230ea200 fix(coding-agent): preserve multiline bug descriptions 2026-09-20 01:40:27 +02:00
Armin Ronacher
dd01f5b240 fix(coding-agent): speed up recent session discovery 2026-09-20 00:50:10 +02:00