6548 Commits
Author SHA1 Message Date
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
Mario Zechner d6af72e185 docs(durable): clarify scratch examples 2026-09-25 18:05:22 +02:00
Mario Zechner 04b5bad666 feat(durable): add typed IDs and explicit ownership 2026-09-25 17:58:29 +02:00
David Brailovsky a6ca861024 fix(ai): price OpenAI Fast mode service tier like priority
GPT-6 models return service_tier "fast" for Fast mode requests (the new
name for priority processing), which fell through to the 1x default.

closes #10034
2026-09-25 17:39:09 +02:00
David Brailovsky ab30693d64 fix(ai): upgrade openai SDK to 7.19.0 (#10044)
* fix(ai): upgrade openai SDK to 7.19.0

Adds the "fast" service tier to the SDK types, needed to price
GPT-6 Fast mode requests correctly. Drops the local
prompt_cache_options type, which the SDK now defines.

* fix(coding-agent): check Cloudflare compat request via fetch instead of SDK mock

pi-ai now resolves its own nested openai 7.x while evals keeps 6.x at the
root, so vi.mock("openai") in coding-agent no longer reached pi-ai's client.
Capture the outgoing request with a fake fetch and assert the URL and headers.

* fix(ai): drop any casts for stream_options and max_tokens in openai-completions

stream_options is typed by the SDK, so assign it directly. max_tokens is
deprecated by OpenAI but still needed for OpenAI-compatible providers
that reject max_completion_tokens; use a narrow cast instead of any to
avoid the deprecation warning.
2026-09-25 17:27:12 +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
Mario Zechner 507d7649e9 feat(durable): add conversation document forks 2026-09-25 16:17:53 +02:00
David Brailovsky 8930b9ec0b fix(ai): ignore empty Mistral content deltas
GLM models on Mistral send empty content deltas at the start of a
response, alongside tool call fragments, and sometimes mid-thinking.
Each one opened an empty text block, and a mid-thinking one split
thinking into two blocks, which Mistral rejects on replay with
"Expected at most one leading ThinkChunk".

closes #9674
2026-09-25 16:01:28 +02:00
David Brailovsky c01f687e5b fix(ai): apply model samplingParams in direct stream()/complete() calls
Model-level samplingParams were only merged by streamSimple(). Direct
stream()/complete() calls, such as extensions using
modelRegistry.complete(), dropped them. The OpenAI-compatible adapters
now merge model defaults with request keys, and request keys take
precedence.

closes #9506
2026-09-25 15:53:08 +02:00
Christian Klotz ddba596187 fix(coding-agent): honor truecolor in custom themes (fixes #9973) (#10039) 2026-09-25 14:44:41 +01: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
David Brailovsky b3487650f6 fix(tui): keep cursor visible when overlays close after stop
Closing the last overlay hid the terminal cursor. If an extension closed
an overlay during session shutdown, this ran after stop() had restored
the cursor, leaving the shell with an invisible cursor.

closes #10026
2026-09-25 13:30:50 +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
Mario Zechner 5fd446ca18 feat(durable): optimize document replay 2026-09-25 00:09:50 +02:00
Mario Zechner 9e70c3d505 feat(chord): optimize immutable batch application 2026-09-25 00:09:50 +02:00
Ramiz Wachtler b2bd111f2d feat(coding-agent): add hidden-message toggle to HTML exports (#10020) 2026-09-24 23:18:25 +02:00
Mario Zechner 5d4de953ce feat(durable): add checkpoints and document migrations 2026-09-24 23:09:15 +02:00
Mario Zechner 19a0361be8 feat(durable): add transactional sessions and documents
Add typed document definitions, atomic Session transactions, complete commit publication, task/document lifecycle handling, and paginated Tx scans. Share Chord's strict JSON copier across draft placements and durable ownership boundaries.
2026-09-24 22:24:04 +02:00
Ramiz Wachtler 7cf037c218 fix(tui): choose Kitty image dimensions by aspect distortion (#9957) 2026-09-24 20:51:10 +02:00
Mario Zechner 6966636dbe fix(chord): allow promise probes on settled drafts 2026-09-24 19:33:02 +02:00
Armin Ronacher d5629e2048 fix(tui): autocomplete paths after opening wrappers like ( and backticks 2026-09-24 15:08:54 +02:00
Mario Zechner d5cba1d97c feat(chord): make immutable delta tracker canonical
Replace the alternate tracker implementations with the optimized immutable overlay, validate draft placements as strict JSON, and document the ownership contract. Consolidate tracker tests and benchmarks around the canonical implementation.
2026-09-24 15:07:12 +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
Christian Klotz 3f0573877e feat(durable): export storage benchmark workloads 2026-09-24 14:26:22 +02:00
Mario Zechner cbe7cf00be docs(durable): move Pico5 strict-JSON checks to roots and Chord placements 2026-09-24 14:11:10 +02:00
Mario Zechner 481c7232f1 docs(durable): align Pico5 with canonical immutable tracker
Name the Astra-immutable-optimized Chord Delta tracker as the Packages 6-7
prerequisite, include the minimal generic Tx table surface in that
milestone, and revoke drafts at callback settlement. Drop the Chord
prerequisite from Package 11 because the existing replicated-state source
contract already matches. Specify that tool stream() never spills; tools
spill through their execution environment.
2026-09-24 13:50:10 +02:00
Mario Zechner 601437d5a7 fix(durable): test execution environment and fix output truncation metadata
Port and extend the agent environment tests for NodeExecutionEnv, output
capture, adaptive publishing, and truncation, including exact-byte
truncation, flushing, line-reader cancellation, spill backpressure, and
Buffer-free UTF-8 counting.

Fix truncation reporting when bytes and lines are both exceeded, when only
bytes are exceeded at the line cap, and when small limits trim multi-byte
edge characters. Report the full size of oversized newline-terminated tail
lines. Resolve durable test imports from source so tests run unbuilt.

Set Pico tool output defaults to 50 KiB and 2,000 lines.
2026-09-24 13:34:46 +02:00
Armin Ronacher a7d17e39aa feat(ai): serve Jev classifier through OpenRouter and Cloudflare Workers AI
OpenRouter decision models use its TypeSafe-compatible /api/v1/systemone endpoint. Cloudflare Workers AI gets a cloudflare-workers-ai-system-one classifier API for the /ai/run envelope. Request and answer parsing is shared in system-one-shared.ts.
2026-09-24 12:34:58 +02:00
Mario Zechner 7c696c00f3 docs: revise Pico5 immutable revision design 2026-09-24 11:33:45 +02:00
Armin Ronacher 8676a0dcd8 fix(coding-agent): require advertised X11 clipboard images
closes #9786
2026-09-24 09:15:58 +02:00
Christian Klotz b45597504e feat(durable): export scoped storage conformance suite (#9977)
* feat(durable): export scoped storage conformance suite

* docs(durable): clarify storage conformance example
2026-09-23 23:21:15 +02:00
Armin Ronacher 7fd564cbb7 feat: share model catalog protocol with pi.dev (#9763)
Move catalog layout, index validation, version selection, and request
negotiation into scripts/model-catalog-protocol.ts. pi.dev keeps an
identical copy, so the publisher and a test running the current client
exercise the same selection pi.dev performs. Replaces the cross-repository
compatibility dispatch.

Related to #9099.
2026-09-23 20:08:05 +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 667fc3dd36 fix(ai): price Vercel AI Gateway 1-hour cache writes correctly
Read the 1-hour cache-write count from streaming deltas when present, and add a regression test.

Fixes #9210
2026-09-23 17:16:32 +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 36af9dc48e fix(tui): restore skill prefix autocomplete, closes #9944 2026-09-23 14:32:09 +02:00
Armin Ronacher fde38ed7c2 fix(ai): stabilize Copilot Claude Opus 5.5 effort levels 2026-09-23 11:41:33 +02:00
Armin Ronacher 4c2dfd9362 chore: regenerate image models 2026-09-23 11:32:31 +02:00
Mario Zechner b313731b80 feat: add JSONL sidecar reclamation 2026-09-23 09:54:05 +02:00
Mario Zechner 4bc1a2fe53 feat(chord): add optimized delta engine prototypes 2026-09-23 02:23:16 +02:00
Mario Zechner 9a139c62bf feat(chord): consolidate immutable delta tracking 2026-09-23 02:22:52 +02:00
Mario Zechner 898ab80405 feat: add durable JSONL storage backend 2026-09-23 01:33:31 +02:00
Mario Zechner 9672462143 docs: refine Pico5 JSONL publication design 2026-09-23 00:26:05 +02:00
Mario Zechner a32782520f docs: propose Pico5 live extension registries 2026-09-22 23:46:19 +02:00
Armin Ronacher a8ed497713 Add [Unreleased] section for next cycle 2026-09-22 21:28:09 +02:00