@kingingwang/pi-darwin-arm64 1.0.4 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/bin/CHANGELOG.md CHANGED
@@ -1,5 +1,57 @@
1
1
  # Changelog
2
2
 
3
+ ## [1.1.0] - 2026-10-07
4
+
5
+ ### New Features
6
+
7
+ - **Program status reporting**: terminals and agent dashboards that support OSC 7501 see whether Pi is working, blocked on a dialog or login, done, or failed. See [Program status](docs/terminal-setup.md#program-status).
8
+ - **Claude Haiku 5.5**: `anthropic/claude-haiku-5-5`, with adaptive thinking up to `xhigh`/`max` effort.
9
+ - **Adjust default tools with `+name`/`-name`**: `--tools` entries like `pi -t +codemode,-write` change the default selection instead of replacing it. See [Tools](docs/cli.md#tools).
10
+ - **GPT-6 Luna and image classification**: OpenAI's GPT-6 Luna is available as a classifier model through the Decisions API, and codemode's `models.classify()` accepts images for classifiers that support them. See [Use classifier models](docs/models.md#use-classifier-models).
11
+ - **Native llama.cpp decision models**: Julia-1, Laya, Kev, lev, and OpenJev served by llama.cpp 0.6.0 or later run natively as classifiers through `/v1/systemone`. See [Classification](docs/llama-cpp.md#classification).
12
+
13
+ ### Added
14
+
15
+ - Added `+name` and `-name` entries to `--tools`, which change the default tool selection instead of replacing it, for example `pi -t +codemode`
16
+ - Added `durationMs` to the tool render context and to `tool_execution_end` extension events: the recorded execution time of a final tool result ([#10549](https://github.com/earendil-works/pi/issues/10549))
17
+ - Added `outputPad` to the tool render context ([#10557](https://github.com/earendil-works/pi/pull/10557) by [@rwachtler](https://github.com/rwachtler))
18
+ - Added OpenAI's GPT-6 Luna as a classifier model through the Decisions API, available with `OPENAI_API_KEY` (see [Use classifier models](docs/models.md#use-classifier-models))
19
+ - Added `images` to codemode's `models.classify()` context, so classifiers that accept images, such as GPT-6 Luna, can judge them
20
+ - Added program status reporting with OSC 7501: terminals and agent dashboards that support it see whether Pi is working, blocked on a dialog or login, done, or failed. `PI_PROGRAM_STATUS=1|0` overrides detection (see [Terminal setup](docs/terminal-setup.md#program-status)) ([#10607](https://github.com/earendil-works/pi/issues/10607))
21
+ - Added `aborted` to `agent_settled` session, extension, and JSON events, so integrations can tell a cancelled run from a finished one ([#10607](https://github.com/earendil-works/pi/issues/10607))
22
+ - Added Claude Haiku 5.5 (`anthropic/claude-haiku-5-5`), with adaptive thinking up to `xhigh`/`max` effort and prompt caching on Bedrock
23
+ - Added native llama.cpp decision models: Julia-1, Laya, Kev, lev, and OpenJev served by llama.cpp 0.6.0 or later are listed only as classifiers through `/v1/systemone` instead of as chat models (see [Classification](docs/llama-cpp.md#classification)) ([#10382](https://github.com/earendil-works/pi/pull/10382))
24
+
25
+ ### Changed
26
+
27
+ - Changed `outputPad` to also apply to `!` command output, tool output, and summary blocks ([#9946](https://github.com/earendil-works/pi/issues/9946), [#10557](https://github.com/earendil-works/pi/pull/10557) by [@rwachtler](https://github.com/rwachtler))
28
+ - Changed `pi mcp login --timeout` to limit the whole sign-in, including requests to the authorization server, instead of only the wait for the browser ([#10565](https://github.com/earendil-works/pi/issues/10565))
29
+
30
+ ### Fixed
31
+
32
+ - Fixed bash and PowerShell results losing `Took` after reloading a session, and the live `Took` including wall-clock steps; both now show the recorded execution time ([#10549](https://github.com/earendil-works/pi/issues/10549))
33
+ - Fixed managed installs keeping every old release; `pi update` now keeps only the new release and the one it updated from ([#10392](https://github.com/earendil-works/pi/issues/10392), [#10511](https://github.com/earendil-works/pi/pull/10511) by [@davidbrai](https://github.com/davidbrai))
34
+ - Fixed standalone binaries loading `.env`, `.env.local`, and `.env.development` from the launch directory into Pi's environment ([#10473](https://github.com/earendil-works/pi/issues/10473))
35
+ - Fixed `!!` command headers losing their dim color once output arrives ([#10557](https://github.com/earendil-works/pi/pull/10557) by [@rwachtler](https://github.com/rwachtler))
36
+ - Fixed the codemode description not marking `searchTools()`, `describeTool()`, and `describeNamespace()` as async, which led models to serialize the unawaited promise as `{}` ([#10555](https://github.com/earendil-works/pi/issues/10555))
37
+ - Fixed codemode output items running together, so models could not tell where one `text()` or `console.log()` output ended and the next began. With several text items, each now starts with a `==> text N/M <==` line, and `console` calls follow the other output in one `<console_output>` block with one line per call
38
+ - Fixed `/mcp` waiting for all servers to connect before opening; the manager now updates live and remains usable while enabling, reconnecting, or disabling servers ([#10562](https://github.com/earendil-works/pi/issues/10562))
39
+ - Fixed images being dropped as "could not be resized" when running under `node --watch` on Node 24.19+ and 26.x, where Node posts its own messages on the image resize worker channel ([#10527](https://github.com/earendil-works/pi/issues/10527))
40
+ - Fixed clipboard paste doing nothing in Termux, and failed copies there omitting the Termux:API install hint ([#10391](https://github.com/earendil-works/pi/issues/10391))
41
+ - Fixed `!` and RPC `bash` output keeping fragments of color codes, such as a stray `m`, when a code was split across output chunks ([#10504](https://github.com/earendil-works/pi/issues/10504))
42
+ - Fixed MCP OAuth sign-ins that could not be cancelled while waiting on the authorization server and kept running after the session ended. The sign-in screen now cancels with Esc at every step, session shutdown aborts a running sign-in, and each request to the authorization server times out after 15 seconds ([#10565](https://github.com/earendil-works/pi/issues/10565))
43
+ - Fixed shutdown waiting up to 15 seconds to refresh an MCP OAuth token that was about to expire, only to close the server's session ([#10565](https://github.com/earendil-works/pi/issues/10565))
44
+ - Fixed the fullscreen text selection surviving session switches and other transcript rebuilds, which highlighted unrelated text in the new transcript ([#9311](https://github.com/earendil-works/pi/issues/9311), [#10567](https://github.com/earendil-works/pi/pull/10567) by [@christianklotz](https://github.com/christianklotz))
45
+ - Fixed OpenAI models on Bedrock ignoring the thinking level and always running at Bedrock's default reasoning effort ([#9331](https://github.com/earendil-works/pi/issues/9331), [#10142](https://github.com/earendil-works/pi/pull/10142) by [@jsanter27](https://github.com/jsanter27))
46
+ - Fixed model `headers` in `models.json` not overriding the `originator` and `User-Agent` headers of Codex requests ([#10429](https://github.com/earendil-works/pi/pull/10429) by [@lucasmeijer](https://github.com/lucasmeijer))
47
+ - Fixed `server_busy` and `servers are currently busy` provider errors ending the turn instead of being retried ([#10543](https://github.com/earendil-works/pi/issues/10543))
48
+ - Fixed Mistral responses that end with `finish_reason: "error"` not being retried ([#10487](https://github.com/earendil-works/pi/issues/10487))
49
+ - Reduced context-limit request failures by estimating input at 3.5 characters per token instead of 4 when calculating output limits ([#10497](https://github.com/earendil-works/pi/issues/10497))
50
+ - Fixed Radius models disabled by an organization owner still being listed
51
+ - Fixed Anthropic browser login failing with "localhost refused to connect" when port 53692 is reserved or in use, for example by Hyper-V/WSL port exclusions on Windows: login now falls back to a free loopback port ([#10571](https://github.com/earendil-works/pi/issues/10571))
52
+ - Fixed session costs undercounting long prompts on models with prompt-length pricing tiers, such as Claude Haiku 5.5, Gemini 3.1 Pro, and GPT-5.4, through OpenCode, OpenCode Go, OpenRouter, Vercel AI Gateway, Google, MiniMax, and other providers
53
+ - Fixed Markdown links not being clickable in Herdr ([#10573](https://github.com/earendil-works/pi/issues/10573))
54
+
3
55
  ## [1.0.4] - 2026-10-05
4
56
 
5
57
  ### New Features
package/bin/docs/cli.md CHANGED
@@ -117,7 +117,7 @@ pi --tools read,grep,find,ls --print "Review this project"
117
117
  See [Settings](settings.md#tools) for configuring the default tool selection.
118
118
 
119
119
  - `-t`, `--tools <list>`<br>
120
- Replaces the default selection with a comma-separated allowlist of built-in, extension, or custom tools. Entries are tool names or patterns where `*` matches any characters. MCP tools are kept unless an entry starts with `mcp__` (see [MCP tools](#mcp-tools)).
120
+ Replaces the default selection with a comma-separated allowlist of built-in, extension, or custom tools. Entries are tool names or patterns where `*` matches any characters. MCP tools are kept unless an entry starts with `mcp__` (see [MCP tools](#mcp-tools)). A list of only `+name` and `-name` entries is not an allowlist; it changes the default selection instead.
121
121
  - `-xt`, `--exclude-tools <list>`<br>
122
122
  Disables comma-separated tool names or patterns after all other selection options, MCP tools included.
123
123
  - `-nbt`, `--no-builtin-tools`<br>
@@ -125,7 +125,7 @@ See [Settings](settings.md#tools) for configuring the default tool selection.
125
125
  - `-nt`, `--no-tools`<br>
126
126
  Starts with all built-in, extension, custom, and MCP tools disabled.
127
127
 
128
- Default enabled tools are `read`, `bash`, `edit`, and `write`, unless `defaultTools` changes them. `--tools` replaces the whole selection, so name every tool you want; `defaultTools` also accepts `+name` and `-name` to change the defaults instead.
128
+ Default enabled tools are `read`, `bash`, `edit`, and `write`, unless `defaultTools` changes them. `--tools` with plain names replaces the whole selection, so name every tool you want. Like `defaultTools`, it also accepts a list of only `+name` and `-name` entries, which adds tools to or removes them from the default selection: `pi --tools +codemode,-write` keeps the other default tools, enables `codemode`, and disables `write`. These entries take exact tool names, not `*` patterns; use `--exclude-tools` to disable tools by pattern. Plain names and `+name`/`-name` entries cannot be mixed. `/reload` enables tools newly added to `defaultTools`, but a tool removed with `-name` stays removed.
129
129
 
130
130
  <a id="mcp-tools"></a>
131
131
 
@@ -165,10 +165,10 @@ To turn on `codemode` for every session, add it to the default tools in `~/.pi/a
165
165
  }
166
166
  ```
167
167
 
168
- This keeps `read`, `bash`, `edit`, and `write` and adds `codemode`. For one invocation, list every tool, since `--tools` replaces the selection:
168
+ This keeps `read`, `bash`, `edit`, and `write` and adds `codemode`. For one invocation, add it with `--tools`:
169
169
 
170
170
  ```sh
171
- pi --tools read,bash,edit,write,codemode
171
+ pi --tools +codemode
172
172
  ```
173
173
 
174
174
  Codemode is useful without MCP: scripts can run several tool calls in parallel, filter large output before it reaches the model, call classifier models such as TypeSafe's Jev through `models.classify()` (see [Classifier models](models.md#use-classifier-models)), and generate images through `models.generateImages()` (see [Image models](models.md#use-image-models)).
@@ -15,7 +15,7 @@ A script may start with an options line:
15
15
  - `max_output_tokens` (default 10000) limits the output. Longer output keeps its start and end, and the full text is written to a temp file whose path is included in the result. A script fails when its output passes 16777216 characters of text and base64 image data or 100000 `text()`, `image()`, and `console` calls; write large data to a file with a tool instead.
16
16
  - `timeout_ms` is a hard deadline for the whole script. It is unset by default. Image generation can take minutes, so do not set a short deadline for scripts that generate images.
17
17
 
18
- The result starts with `Script completed` or `Script failed`, the wall time, and the output. A failed script keeps its partial output, followed by `Script error:` and the error. Tool calls are real: calls made before a failure are not undone. Calls still running when the script ends are cancelled, and unawaited promises are discarded.
18
+ The result starts with `Script completed` or `Script failed`, the wall time, and the output. Text and image items appear in order, each on its own line. When the output has more than one text item (from `text()` or `return`), each starts with a `==> text N/M <==` line. `console` calls follow in one `<console_output>` block with one line per call. A failed script keeps its partial output, followed by `Script error:` and the error. Tool calls are real: calls made before a failure are not undone. Calls still running when the script ends are cancelled, and unawaited promises are discarded.
19
19
 
20
20
  ## Globals
21
21
 
@@ -24,7 +24,7 @@ The result starts with `Script completed` or `Script failed`, the wall time, and
24
24
  | `tools.<name>(args)` | Call a tool. See [Call tools](#call-tools). |
25
25
  | `text(value)` | Add a text item to the output. Strings are added as is, other values as JSON. |
26
26
  | `image(value)` | Add an image to the output: a base64 `data:` URL, an `{ image_url }` object, or an image block `{ type: "image", data, mimeType }` such as those returned by MCP tools and `models.generateImages()`. Remote URLs are not supported. PNG, JPEG, GIF, and WebP are accepted. Each image is also saved to a temp file, and the result names the path before the image. |
27
- | `console.log(...)` | Like `text()`; `info`, `warn`, `error`, and `debug` do the same. |
27
+ | `console.log(...)` | Add a line to the `<console_output>` block after the other output. Arguments are joined with spaces; `info`, `warn`, `error`, and `debug` do the same. |
28
28
  | `return value` | A top-level `return` adds the value like `text()`. |
29
29
  | `exit()` | End the script successfully. |
30
30
  | `store(key, value)` / `load(key)` | Keep small JSON values across `codemode` calls. See [Store values](#store-values). |
@@ -59,7 +59,7 @@ The store is for small state such as IDs, cursors, or summaries. One value may h
59
59
 
60
60
  ## Models
61
61
 
62
- `models` reaches the model catalog and runs non-LLM models with the session's credentials: classifiers, which answer typed questions about JSON state, and image models, which generate images. Chat models are listed but cannot be run from scripts. Which classifier and image models exist is described in [Use classifier models](models.md#use-classifier-models) and [Use image models](models.md#use-image-models).
62
+ `models` reaches the model catalog and runs non-LLM models with the session's credentials: classifiers, which answer typed questions about JSON state and, for some models, images, and image models, which generate images. Chat models are listed but cannot be run from scripts. Which classifier and image models exist is described in [Use classifier models](models.md#use-classifier-models) and [Use image models](models.md#use-image-models).
63
63
 
64
64
  ```ts
65
65
  type ModelType = "chat" | "image" | "classifier";
@@ -100,6 +100,8 @@ Model IDs differ between providers, for example `typesafe/jev-latest` and `openr
100
100
  interface ClassifierContext {
101
101
  /** The data to classify. */
102
102
  state: Record<string, unknown>;
103
+ /** Images judged together with `state`. Only models whose `input` includes "image" accept them. */
104
+ images?: { type: "image"; data: string; mimeType: string }[];
103
105
  /** Questions by ID. One call answers all of them. */
104
106
  questions: Record<string, ClassifierQuestion>;
105
107
  }
@@ -163,6 +165,24 @@ return results.map((result, i) =>
163
165
  );
164
166
  ```
165
167
 
168
+ Classifiers whose `input` includes `"image"` also judge images. `tools.read()` returns an image file as an image block that `images` accepts. Other classifiers return an error result when `images` is not empty.
169
+
170
+ ```js
171
+ const luna = await models.getModelOfType("classifier", "openai", "gpt-6-luna");
172
+ const photo = await tools.read({ path: "screenshot.png" });
173
+ const result = await models.classify(luna, {
174
+ state: { task: "Settings page redesign" },
175
+ images: [photo],
176
+ questions: {
177
+ broken: {
178
+ type: "bool",
179
+ instructions: "Does the screenshot show a broken layout?",
180
+ criteria: { true: "Overlapping, cut-off, or misaligned elements", false: "Clean layout" },
181
+ },
182
+ },
183
+ });
184
+ ```
185
+
166
186
  ### Generate images
167
187
 
168
188
  ```ts
@@ -89,6 +89,7 @@ These variables are read by Pi itself:
89
89
  | `PI_RADIUS_GATEWAY` | Override the Radius gateway origin used by `/bug` uploads and Radius relay connections |
90
90
  | `PI_HARDWARE_CURSOR` | Set to `1` to show the hardware cursor; see [Terminal setup](terminal-setup.md) |
91
91
  | `PI_HYPERLINKS` | Override OSC 8 hyperlink detection with `1`, `0`, or `auto` |
92
+ | `PI_PROGRAM_STATUS` | Override OSC 7501 program status detection: `1` always reports, `0` never reports; otherwise Pi reports only after the terminal confirms support. See [Terminal setup](terminal-setup.md#program-status) |
92
93
  | `PI_IMAGE_PROTOCOL` | Override inline image detection with `kitty`, `iterm2`, `none`, or `auto` |
93
94
  | `PI_TRUE_COLOR` | Override truecolor detection with `1`, `0`, or `auto` |
94
95
  | `PI_TUI_ESC_TIMEOUT` | How long to wait after a lone ESC before treating it as Escape, in milliseconds; defaults to `100` over SSH and `10` otherwise. Increase if Alt-key input is misread as Escape |
package/bin/docs/json.md CHANGED
@@ -42,7 +42,7 @@ A basic run produces records like these:
42
42
  {"type":"message_end","message":{"role":"assistant","...":"..."}}
43
43
  {"type":"turn_end","message":{"role":"assistant","...":"..."},"toolResults":[]}
44
44
  {"type":"agent_end","messages":[{"...":"..."}],"willRetry":false}
45
- {"type":"agent_settled"}
45
+ {"type":"agent_settled","aborted":false}
46
46
  ```
47
47
 
48
48
  `agent_end` closes one low-level agent run. Automatic retry, overflow recovery, compaction retry, steering, or follow-up work can still continue. `agent_settled` means Pi has no remaining automatic work for that session-level run.
@@ -53,7 +53,7 @@ A basic run produces records like these:
53
53
  |---|---|---|
54
54
  | `agent_start` | None | A low-level agent run started. |
55
55
  | `agent_end` | `messages`, `willRetry` | That low-level run ended. `messages` contains messages generated by the run. |
56
- | `agent_settled` | None | Pi will not continue automatically through retries, compaction recovery, or queued messages. |
56
+ | `agent_settled` | `aborted` | Pi will not continue automatically through retries, compaction recovery, or queued messages. `aborted` is `true` when the run ended because it was aborted. |
57
57
  | `turn_start` | None | One assistant turn started. |
58
58
  | `turn_end` | `message`, `toolResults` | One assistant response and its resulting tool calls finished. |
59
59
 
@@ -104,7 +104,7 @@ The top-level `usage` is the latest cumulative provider-reported usage for the a
104
104
  |---|---|---|
105
105
  | `tool_execution_start` | `toolCallId`, `toolName`, `args` | Tool execution started. |
106
106
  | `tool_execution_update` | `toolCallId`, `toolName`, `args`, `partialResult` | The tool reported a partial result. |
107
- | `tool_execution_end` | `toolCallId`, `toolName`, `result`, `isError` | Tool execution finished. |
107
+ | `tool_execution_end` | `toolCallId`, `toolName`, `result`, `isError`, `durationMs` | Tool execution finished. `durationMs` is how long the tool's `execute()` took, measured with a monotonic clock; absent when the tool did not run. |
108
108
 
109
109
  Use `toolCallId` to correlate the lifecycle. `partialResult` is the latest partial result supplied by the tool. Whether it replaces or extends an earlier update depends on that tool's result contract.
110
110
 
@@ -88,7 +88,14 @@ If the router disconnects, `/llama` shows **Retry** and **Close**. Retry reconne
88
88
 
89
89
  ## Classification
90
90
 
91
- Every model listed for chat is also listed as a classifier model with the same ID and the `llama-cpp-classify` API. Classifier models answer typed `choice`, `bool`, and `score` questions about JSON state, like TypeSafe's Jev models. The model reaches them from [`codemode`](cli.md#enable-codemode) scripts, and extensions through `ctx.modelRegistry.classify()`; see [Classifier models](models.md#use-classifier-models).
91
+ Classifier models answer typed `choice`, `bool`, and `score` questions about JSON state, like TypeSafe's Jev models. The model reaches them from [`codemode`](cli.md#enable-codemode) scripts, and extensions through `ctx.modelRegistry.classify()`; see [Classifier models](models.md#use-classifier-models). Pi lists llama.cpp models as classifiers in two ways:
92
+
93
+ - **Decision models** such as [Julia-1, Laya, Kev, lev, and OpenJev](https://huggingface.co/collections/ggml-org/decision-models-6abf80cca3c83f127060a769) answer natively through llama.cpp's `/v1/systemone` endpoint. They appear only as classifiers, with the `typesafe-system-one` API, and not in `/model`.
94
+ - **Chat models** are also listed as classifiers with the same ID and the `llama-cpp-classify` API, which reads answers from next-token probabilities as described below.
95
+
96
+ llama.cpp 0.6.0 and later report decision models in the router's model list: their `architecture.output_modalities` contains `decisions`. The router reads this from the GGUF metadata without loading the model, so Pi recognizes unloaded and sleeping decision models too. Older llama.cpp builds do not report it, and Pi lists their decision models as chat models.
97
+
98
+ ### Chat models as classifiers
92
99
 
93
100
  The model does not generate an answer. Each question becomes one chat prompt: the state, every question of the request, the state again, and then the question with its answers under single-token labels. Labels are letters for a choice (up to 62 options), `Yes`/`No` for a bool, and digits for a score (up to 10 levels). The second copy of the state is read with the questions in view, which improved accuracy on JevBench with small models. Pi reads the probabilities of the labels as the next token and normalizes them. A choice returns every option's probability and a confidence of `(n * peak - 1) / (n - 1)`; a score returns the expected level.
94
101
 
@@ -100,12 +100,11 @@ interface SystemMessage {
100
100
  sections?: Record<string, string | null>;
101
101
  toolsAdded?: Tool[];
102
102
  toolsRemoved?: ToolReference[];
103
- replace?: boolean;
104
103
  timestamp: number;
105
104
  }
106
105
  ```
107
106
 
108
- The leading system message declares the initial prompt and tools. Later system messages can append instructions, replace or remove named prompt sections, and add or remove tools. Replaying them in order yields the current state. A message with `replace: true` discards the earlier state and establishes a complete new baseline.
107
+ The leading system message declares the initial prompt and tools. Later system messages can append instructions, replace or remove named prompt sections, and add or remove tools. Replaying them in order yields the current state.
109
108
 
110
109
  ### UserMessage
111
110
 
@@ -129,6 +128,7 @@ interface AssistantMessage {
129
128
  responseModel?: string;
130
129
  responseId?: string;
131
130
  providerThinkingLevel?: string;
131
+ thinkingLevel?: ModelThinkingLevel;
132
132
  diagnostics?: AssistantMessageDiagnostic[];
133
133
  usage: Usage;
134
134
  stopReason: "pending" | "stop" | "length" | "toolUse" | "error" | "aborted" | "deferred";
@@ -140,7 +140,7 @@ interface AssistantMessage {
140
140
  }
141
141
  ```
142
142
 
143
- `responseModel` records a concrete provider response model when it differs from the requested model. `responseId`, `providerThinkingLevel`, `diagnostics`, and `rawStopReason` preserve provider or runtime details.
143
+ `responseModel` records a concrete provider response model when it differs from the requested model. `responseId`, `providerThinkingLevel`, `thinkingLevel`, `diagnostics`, and `rawStopReason` preserve provider or runtime details.
144
144
 
145
145
  `"pending"` is used for a partial assistant message while it streams. The completed message in `message_end` has a terminal stop reason, and Pi does not persist `"pending"` assistant messages in session JSONL.
146
146
 
@@ -168,12 +168,30 @@ interface ToolResultMessage<TDetails = any> {
168
168
  content: (TextContent | ImageContent)[];
169
169
  details?: TDetails;
170
170
  usage?: Usage;
171
+ nestedCalls?: NestedToolCalls;
171
172
  isError: boolean;
172
173
  timestamp: number;
173
174
  }
174
175
  ```
175
176
 
176
- `details` is tool-specific. Optional `usage` reports nested model work performed by the tool and contributes to full-session statistics, but it is not part of the main model-call usage.
177
+ `details` is tool-specific. Optional `usage` reports nested model work performed by the tool and contributes to full-session statistics, but it is not part of the main model-call usage. `nestedCalls` records bounded metadata about calls this tool made to other tools:
178
+
179
+ ```typescript
180
+ interface NestedToolCalls {
181
+ calls: NestedToolCallRecord[];
182
+ complete: boolean;
183
+ }
184
+
185
+ interface NestedToolCallRecord {
186
+ id: string;
187
+ name: string;
188
+ arguments?: JsonObject;
189
+ argumentsBytes?: number;
190
+ status: "ok" | "error" | "unfinished";
191
+ durationMs?: number;
192
+ error?: string;
193
+ }
194
+ ```
177
195
 
178
196
  ## Coding-agent messages
179
197
 
@@ -128,7 +128,7 @@ Compatibility settings should describe verified differences in the endpoint's re
128
128
 
129
129
  ## Use classifier models
130
130
 
131
- Classifier models do not chat. They answer typed questions about JSON state: pick one of several choices, answer yes or no, or give a score, each with probabilities. Pi includes TypeSafe's Jev model from these providers, and Cloudflare's Clef and Clef Flash models from Workers AI:
131
+ Classifier models do not chat. They answer typed questions about JSON state: pick one of several choices, answer yes or no, or give a score, each with probabilities. Pi includes TypeSafe's Jev model from these providers, Cloudflare's Clef and Clef Flash models from Workers AI, and OpenAI's GPT-6 Luna through the [Decisions API](https://developers.openai.com/api/docs/guides/decisions):
132
132
 
133
133
  | Provider | Model IDs | Authentication |
134
134
  |---|---|---|
@@ -137,9 +137,12 @@ Classifier models do not chat. They answer typed questions about JSON state: pic
137
137
  | `cloudflare-workers-ai` | `typesafe/jev`, `@cf/cloudflare/clef`, `@cf/cloudflare/clef-flash` | `CLOUDFLARE_API_KEY` and `CLOUDFLARE_ACCOUNT_ID` |
138
138
  | `vercel-ai-gateway` | `typesafe-ai/jev` | `AI_GATEWAY_API_KEY` |
139
139
  | `opencode` | `jev-1.13`, `jev-1.13-free` | `OPENCODE_API_KEY` |
140
+ | `openai` | `gpt-6-luna` | `OPENAI_API_KEY` |
140
141
 
141
142
  Chat models on a [llama.cpp router](llama-cpp.md#classification) are also listed as classifier models.
142
143
 
144
+ OpenAI's Decisions API needs an API key. Sign in with ChatGPT credentials do not work with it, so `gpt-6-luna` is not listed as available while `openai` is logged in through `/login`, even when `OPENAI_API_KEY` is set; log out of `openai` to use the key. GPT-6 Luna also judges images passed in `images` (see [Codemode](codemode.md#classify)); other classifier models return an error for them. The API rejects inputs above 922K tokens, but requests that run longer than about five seconds, currently above roughly 600K input tokens, fail with a gateway timeout.
145
+
143
146
  Classifier models do not appear in `/model`. The model reaches them through the [`codemode`](cli.md#enable-codemode) tool, which is off unless an MCP server turned it on. Enable it with `"defaultTools": ["+codemode"]` in [settings](settings.md#tools). Scripts then list classifier models with `models.getAvailableOfType("classifier")` and call `models.classify(model, { state, questions })`:
144
147
 
145
148
  ```js
@@ -115,6 +115,10 @@ Radius authentication uses its gateway catalog and caches refreshed model metada
115
115
 
116
116
  ### Azure OpenAI
117
117
 
118
+ The provider ID is `azure` (formerly `azure-openai-responses`). Use it as the key in `auth.json`, `models.json`, and `settings.json`, and in model references such as `--model azure/gpt-5.4`.
119
+
120
+ The `azure` provider serves OpenAI models through the Responses API and Microsoft Foundry models through Chat Completions, such as `azure/deepseek-v4-pro`.
121
+
118
122
  Set an API key plus either a base URL or resource name:
119
123
 
120
124
  ```bash
@@ -126,6 +130,29 @@ export AZURE_OPENAI_RESOURCE_NAME=your-resource
126
130
 
127
131
  Resource root URLs under `ai.azure.com`, `cognitiveservices.azure.com`, and `openai.azure.com` are normalized to the OpenAI API path.
128
132
 
133
+ Pi sends the model ID as the deployment name. If a deployment has a different name, map it with `AZURE_OPENAI_DEPLOYMENT_NAME_MAP`:
134
+
135
+ ```bash
136
+ export AZURE_OPENAI_DEPLOYMENT_NAME_MAP=gpt-5.4=my-gpt-deployment,deepseek-v4-pro=my-deepseek
137
+ ```
138
+
139
+ `AZURE_OPENAI_API_VERSION` overrides the API version for OpenAI models (default `v1`).
140
+
141
+ To use a Foundry model that Pi does not include, add it under `azure` in [`models.json`](models.md#configure-a-compatible-endpoint) with `api: "openai-completions"`. Custom models require a `baseUrl`; `AZURE_OPENAI_BASE_URL` and `AZURE_OPENAI_RESOURCE_NAME` take priority over it when set:
142
+
143
+ ```json
144
+ {
145
+ "providers": {
146
+ "azure": {
147
+ "baseUrl": "https://your-resource.services.ai.azure.com",
148
+ "models": [
149
+ { "id": "your-deployment", "api": "openai-completions" }
150
+ ]
151
+ }
152
+ }
153
+ }
154
+ ```
155
+
129
156
  ### Amazon Bedrock
130
157
 
131
158
  Bedrock can use a bearer token or an ambient AWS credential source:
@@ -53,9 +53,9 @@ A list of only `+name` and `-name` entries changes the inherited selection inste
53
53
 
54
54
  This replaces `bash` with `powershell` and enables `grep`: `["-bash", "+powershell", "+grep"]`. Project settings apply on top of user settings: a project list with only `+name` and `-name` entries changes the user's selection, and a project list with a plain name replaces it. In one list, plain names form the selection, and `+name` and `-name` then apply in order.
55
55
 
56
- `/reload` enables tools newly added to `defaultTools`. It does not disable tools removed from it or re-enable unchanged tools you turned off. `--tools`, `--no-tools`, and `--no-builtin-tools` override `defaultTools`, also on reload.
56
+ `/reload` enables tools newly added to `defaultTools`. It does not disable tools removed from it or re-enable unchanged tools you turned off. `--tools` with plain names, `--no-tools`, and `--no-builtin-tools` override `defaultTools`, also on reload.
57
57
 
58
- CLI tool options override this setting for one invocation; `--tools` does not accept `+name` or `-name`. See [Command Line](cli.md#tools).
58
+ CLI tool options override this setting for one invocation. `--tools` with only `+name` and `-name` entries changes the resolved `defaultTools` selection instead, for example `pi --tools +codemode`. On `/reload`, these entries apply to the reloaded setting too, so a tool removed with `-name` stays removed. See [Command Line](cli.md#tools).
59
59
 
60
60
  ## Sessions and context
61
61
 
@@ -97,7 +97,7 @@ See [Compaction Reference](compaction.md) for trigger, summarization, and valida
97
97
  | `fullscreenCopyOnSelect` | boolean | `true` | Copy selected text automatically in fullscreen mode. |
98
98
  | `fullscreenWheelScrollLines` | `"auto"` \| number | `"auto"` | Lines per mouse-wheel event in fullscreen mode, from 1 to 100. `"auto"` moves one line per event in local macOS terminals, which already accelerate wheel and trackpad input; elsewhere, and over SSH, it speeds up fast wheel spins to at most 6 lines per event. Alt+wheel moves five times as far. |
99
99
  | `editorPaddingX` | number | `0` | Horizontal editor padding from 0 to 3 cells. |
100
- | `outputPad` | `0 \| 1` | `1` | Horizontal transcript padding. |
100
+ | `outputPad` | `0 \| 1` | `1` | Horizontal transcript padding for messages, tool output, `!` command output, and summary blocks. |
101
101
  | `autocompleteMaxVisible` | number | `5` | Visible autocomplete entries, from 3 to 20. |
102
102
  | `showHardwareCursor` | boolean | `false` | Show the terminal cursor while Pi positions it for input methods. |
103
103
  | `terminal.showImages` | boolean | `true` | Display inline images when supported. |
@@ -217,3 +217,17 @@ Pi automatically detects OSC 8 hyperlinks, inline image protocols, and truecolor
217
217
  Settings take precedence over environment variables. An unset value or `auto` preserves automatic detection.
218
218
 
219
219
  Only force a capability supported by the complete terminal path. Unsupported escape sequences can corrupt rendering. See [Environment Variables](environment-variables.md#pi-process-configuration) and [Settings](settings.md) for the canonical value definitions.
220
+
221
+ ## Program status
222
+
223
+ Pi reports its state with the [Program Status Protocol (OSC 7501)](https://www.superlogical.com/rex/docs/build/program-status), so terminals and agent dashboards can show whether it is working, waiting for you, done, or failed:
224
+
225
+ | State | When |
226
+ |---|---|
227
+ | `working` | An agent run or compaction is in progress. The message is the session name. |
228
+ | `blocked` | An extension dialog or login waits for you. The message is the dialog title. |
229
+ | `done` | A run finished. The message is the session name. |
230
+ | `error` | A run ended with an error that is not retried. The message is the first line of the error. |
231
+ | `idle` | Pi started, or you cancelled the run. |
232
+
233
+ Reports never contain prompts or model output. Pi sends them only after the terminal answers the protocol's support query; tmux and screen do not forward them. Set `PI_PROGRAM_STATUS=1` to send reports without asking, or `PI_PROGRAM_STATUS=0` to turn them off.
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "pi-extension-custom-provider",
3
- "version": "1.0.4",
3
+ "version": "1.1.0",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "pi-extension-custom-provider",
9
- "version": "1.0.4",
9
+ "version": "1.1.0",
10
10
  "dependencies": {
11
11
  "@anthropic-ai/sdk": "^0.52.0"
12
12
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "pi-extension-custom-provider-anthropic",
3
3
  "private": true,
4
- "version": "1.0.4",
4
+ "version": "1.1.0",
5
5
  "type": "module",
6
6
  "scripts": {
7
7
  "clean": "echo 'nothing to clean'",
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "pi-extension-custom-provider-gitlab-duo",
3
3
  "private": true,
4
- "version": "1.0.4",
4
+ "version": "1.1.0",
5
5
  "type": "module",
6
6
  "scripts": {
7
7
  "clean": "echo 'nothing to clean'",
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "pi-extension-gondolin",
3
- "version": "1.0.4",
3
+ "version": "1.1.0",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "pi-extension-gondolin",
9
- "version": "1.0.4",
9
+ "version": "1.1.0",
10
10
  "dependencies": {
11
11
  "@earendil-works/gondolin": "0.12.0"
12
12
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "pi-extension-gondolin",
3
3
  "private": true,
4
- "version": "1.0.4",
4
+ "version": "1.1.0",
5
5
  "type": "module",
6
6
  "scripts": {
7
7
  "clean": "echo 'nothing to clean'",
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "pi-extension-sandbox",
3
- "version": "1.0.4",
3
+ "version": "1.1.0",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "pi-extension-sandbox",
9
- "version": "1.0.4",
9
+ "version": "1.1.0",
10
10
  "dependencies": {
11
11
  "@anthropic-ai/sandbox-runtime": "^0.0.26"
12
12
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "pi-extension-sandbox",
3
3
  "private": true,
4
- "version": "1.0.4",
4
+ "version": "1.1.0",
5
5
  "type": "module",
6
6
  "scripts": {
7
7
  "clean": "echo 'nothing to clean'",
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "pi-extension-with-deps",
3
- "version": "1.0.4",
3
+ "version": "1.1.0",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "pi-extension-with-deps",
9
- "version": "1.0.4",
9
+ "version": "1.1.0",
10
10
  "dependencies": {
11
11
  "ms": "^2.1.3"
12
12
  },
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "pi-extension-with-deps",
3
3
  "private": true,
4
- "version": "1.0.4",
4
+ "version": "1.1.0",
5
5
  "type": "module",
6
6
  "scripts": {
7
7
  "clean": "echo 'nothing to clean'",
@@ -1 +1 @@
1
- {"version":3,"file":"tool-renderer.d.ts","sourceRoot":"","sources":["../../../src/core/export-html/tool-renderer.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,wCAAwC,CAAC;AACpE,OAAO,KAAK,EAAqB,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAG/E,MAAM,WAAW,oBAAoB;IACpC,sFAAsF;IACtF,gBAAgB,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,aAAa,GAAG,SAAS,CAAC;IAC9D,wBAAwB;IACxB,KAAK,EAAE,KAAK,CAAC;IACb,2CAA2C;IAC3C,GAAG,EAAE,MAAM,CAAC;IACZ,kDAAkD;IAClD,KAAK,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,gBAAgB;IAChC,oFAAoF;IACpF,UAAU,CAAC,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,CAAC;IACpF,yGAAyG;IACzG,YAAY,CACX,UAAU,EAAE,MAAM,EAClB,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,EAChF,OAAO,EAAE,OAAO,EAChB,OAAO,EAAE,OAAO,GACd;QAAE,SAAS,CAAC,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,SAAS,CAAC;CACzD;AAsBD,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,oBAAoB,GAAG,gBAAgB,CAkHnF"}
1
+ {"version":3,"file":"tool-renderer.d.ts","sourceRoot":"","sources":["../../../src/core/export-html/tool-renderer.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,wCAAwC,CAAC;AACpE,OAAO,KAAK,EAAqB,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAG/E,MAAM,WAAW,oBAAoB;IACpC,sFAAsF;IACtF,gBAAgB,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,aAAa,GAAG,SAAS,CAAC;IAC9D,wBAAwB;IACxB,KAAK,EAAE,KAAK,CAAC;IACb,2CAA2C;IAC3C,GAAG,EAAE,MAAM,CAAC;IACZ,kDAAkD;IAClD,KAAK,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,gBAAgB;IAChC,oFAAoF;IACpF,UAAU,CAAC,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,CAAC;IACpF,yGAAyG;IACzG,YAAY,CACX,UAAU,EAAE,MAAM,EAClB,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,EAChF,OAAO,EAAE,OAAO,EAChB,OAAO,EAAE,OAAO,GACd;QAAE,SAAS,CAAC,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,SAAS,CAAC;CACzD;AAsBD,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,oBAAoB,GAAG,gBAAgB,CAoHnF"}
@@ -52,6 +52,8 @@ export function createToolHtmlRenderer(deps) {
52
52
  expanded,
53
53
  showImages: false,
54
54
  isError,
55
+ durationMs: undefined,
56
+ outputPad: 1,
55
57
  };
56
58
  };
57
59
  return {
@@ -1 +1 @@
1
- {"version":3,"file":"tool-renderer.js","sourceRoot":"","sources":["../../../src/core/export-html/tool-renderer.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Tool HTML renderer for custom tools in HTML export.\n *\n * Renders custom tool calls and results to HTML by invoking their TUI renderers\n * and converting the ANSI output to HTML.\n */\n\nimport type { ImageContent, TextContent } from \"@earendil-works/pi-ai\";\nimport type { Component } from \"@earendil-works/pi-tui\";\nimport type { Theme } from \"../../modes/interactive/theme/theme.ts\";\nimport type { ToolRenderContext, ToolRenderers } from \"../extensions/types.ts\";\nimport { ansiLinesToHtml } from \"./ansi-to-html.ts\";\n\nexport interface ToolHtmlRendererDeps {\n\t/** Renderers of calls to a tool, as resolved by extensions and the registered tool */\n\tgetToolRenderers: (name: string) => ToolRenderers | undefined;\n\t/** Theme for styling */\n\ttheme: Theme;\n\t/** Working directory for render context */\n\tcwd: string;\n\t/** Terminal width for rendering (default: 100) */\n\twidth?: number;\n}\n\nexport interface ToolHtmlRenderer {\n\t/** Render a tool call to HTML. Returns undefined if tool has no custom renderer. */\n\trenderCall(toolCallId: string, toolName: string, args: unknown): string | undefined;\n\t/** Render a tool result to collapsed/expanded HTML. Returns undefined if tool has no custom renderer. */\n\trenderResult(\n\t\ttoolCallId: string,\n\t\ttoolName: string,\n\t\tresult: Array<{ type: string; text?: string; data?: string; mimeType?: string }>,\n\t\tdetails: unknown,\n\t\tisError: boolean,\n\t): { collapsed?: string; expanded?: string } | undefined;\n}\n\n/**\n * Create a tool HTML renderer.\n *\n * The renderer looks up tool definitions and invokes their renderCall/renderResult\n * methods, converting the resulting TUI Component output (ANSI) to HTML.\n */\nconst ANSI_ESCAPE_REGEX = /\\x1b\\[[\\d;]*m/g;\n\nfunction isBlankRenderedLine(line: string): boolean {\n\treturn line.replace(ANSI_ESCAPE_REGEX, \"\").trim().length === 0;\n}\n\nfunction trimRenderedResultLines(lines: string[]): string[] {\n\tlet start = 0;\n\tlet end = lines.length;\n\twhile (start < end && isBlankRenderedLine(lines[start])) start++;\n\twhile (end > start && isBlankRenderedLine(lines[end - 1])) end--;\n\treturn lines.slice(start, end);\n}\n\nexport function createToolHtmlRenderer(deps: ToolHtmlRendererDeps): ToolHtmlRenderer {\n\tconst { getToolRenderers, theme, cwd, width = 100 } = deps;\n\n\tconst renderedCallComponents = new Map<string, Component>();\n\tconst renderedResultComponents = new Map<string, Component>();\n\tconst renderedStates = new Map<string, any>();\n\tconst renderedArgs = new Map<string, unknown>();\n\n\tconst getState = (toolCallId: string): any => {\n\t\tlet state = renderedStates.get(toolCallId);\n\t\tif (!state) {\n\t\t\tstate = {};\n\t\t\trenderedStates.set(toolCallId, state);\n\t\t}\n\t\treturn state;\n\t};\n\n\tconst createRenderContext = (\n\t\ttoolCallId: string,\n\t\tlastComponent: Component | undefined,\n\t\texpanded: boolean,\n\t\tisPartial: boolean,\n\t\tisError: boolean,\n\t): ToolRenderContext => {\n\t\treturn {\n\t\t\targs: renderedArgs.get(toolCallId),\n\t\t\ttoolCallId,\n\t\t\tinvalidate: () => {},\n\t\t\tlastComponent,\n\t\t\tstate: getState(toolCallId),\n\t\t\tcwd,\n\t\t\texecutionStarted: true,\n\t\t\targsComplete: true,\n\t\t\tisPartial,\n\t\t\texpanded,\n\t\t\tshowImages: false,\n\t\t\tisError,\n\t\t};\n\t};\n\n\treturn {\n\t\trenderCall(toolCallId: string, toolName: string, args: unknown): string | undefined {\n\t\t\ttry {\n\t\t\t\trenderedArgs.set(toolCallId, args);\n\t\t\t\tconst toolDef = getToolRenderers(toolName);\n\t\t\t\tif (!toolDef?.renderCall) {\n\t\t\t\t\treturn undefined;\n\t\t\t\t}\n\n\t\t\t\tconst component = toolDef.renderCall(\n\t\t\t\t\targs,\n\t\t\t\t\ttheme,\n\t\t\t\t\tcreateRenderContext(toolCallId, renderedCallComponents.get(toolCallId), false, true, false),\n\t\t\t\t);\n\t\t\t\trenderedCallComponents.set(toolCallId, component);\n\t\t\t\tconst lines = component.render(width);\n\t\t\t\treturn ansiLinesToHtml(lines);\n\t\t\t} catch {\n\t\t\t\t// On error, return undefined so HTML export can fall back to structured result rendering\n\t\t\t\treturn undefined;\n\t\t\t}\n\t\t},\n\n\t\trenderResult(\n\t\t\ttoolCallId: string,\n\t\t\ttoolName: string,\n\t\t\tresult: Array<{ type: string; text?: string; data?: string; mimeType?: string }>,\n\t\t\tdetails: unknown,\n\t\t\tisError: boolean,\n\t\t): { collapsed?: string; expanded?: string } | undefined {\n\t\t\ttry {\n\t\t\t\tconst toolDef = getToolRenderers(toolName);\n\t\t\t\tif (!toolDef?.renderResult) {\n\t\t\t\t\treturn undefined;\n\t\t\t\t}\n\n\t\t\t\t// Build AgentToolResult from content array\n\t\t\t\t// Cast content since session storage uses generic object types\n\t\t\t\tconst agentToolResult = {\n\t\t\t\t\tcontent: result as (TextContent | ImageContent)[],\n\t\t\t\t\tdetails,\n\t\t\t\t\tisError,\n\t\t\t\t};\n\n\t\t\t\t// Render collapsed\n\t\t\t\tconst collapsedComponent = toolDef.renderResult(\n\t\t\t\t\tagentToolResult,\n\t\t\t\t\t{ expanded: false, isPartial: false },\n\t\t\t\t\ttheme,\n\t\t\t\t\tcreateRenderContext(toolCallId, renderedResultComponents.get(toolCallId), false, false, isError),\n\t\t\t\t);\n\t\t\t\trenderedResultComponents.set(toolCallId, collapsedComponent);\n\t\t\t\tconst collapsed = ansiLinesToHtml(trimRenderedResultLines(collapsedComponent.render(width)));\n\n\t\t\t\t// Render expanded\n\t\t\t\tconst expandedComponent = toolDef.renderResult(\n\t\t\t\t\tagentToolResult,\n\t\t\t\t\t{ expanded: true, isPartial: false },\n\t\t\t\t\ttheme,\n\t\t\t\t\tcreateRenderContext(toolCallId, renderedResultComponents.get(toolCallId), true, false, isError),\n\t\t\t\t);\n\t\t\t\trenderedResultComponents.set(toolCallId, expandedComponent);\n\t\t\t\tconst expanded = ansiLinesToHtml(trimRenderedResultLines(expandedComponent.render(width)));\n\n\t\t\t\treturn {\n\t\t\t\t\t...(collapsed && collapsed !== expanded ? { collapsed } : {}),\n\t\t\t\t\texpanded,\n\t\t\t\t};\n\t\t\t} catch {\n\t\t\t\t// On error, return undefined so HTML export can fall back to structured result rendering\n\t\t\t\treturn undefined;\n\t\t\t}\n\t\t},\n\t};\n}\n"]}
1
+ {"version":3,"file":"tool-renderer.js","sourceRoot":"","sources":["../../../src/core/export-html/tool-renderer.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Tool HTML renderer for custom tools in HTML export.\n *\n * Renders custom tool calls and results to HTML by invoking their TUI renderers\n * and converting the ANSI output to HTML.\n */\n\nimport type { ImageContent, TextContent } from \"@earendil-works/pi-ai\";\nimport type { Component } from \"@earendil-works/pi-tui\";\nimport type { Theme } from \"../../modes/interactive/theme/theme.ts\";\nimport type { ToolRenderContext, ToolRenderers } from \"../extensions/types.ts\";\nimport { ansiLinesToHtml } from \"./ansi-to-html.ts\";\n\nexport interface ToolHtmlRendererDeps {\n\t/** Renderers of calls to a tool, as resolved by extensions and the registered tool */\n\tgetToolRenderers: (name: string) => ToolRenderers | undefined;\n\t/** Theme for styling */\n\ttheme: Theme;\n\t/** Working directory for render context */\n\tcwd: string;\n\t/** Terminal width for rendering (default: 100) */\n\twidth?: number;\n}\n\nexport interface ToolHtmlRenderer {\n\t/** Render a tool call to HTML. Returns undefined if tool has no custom renderer. */\n\trenderCall(toolCallId: string, toolName: string, args: unknown): string | undefined;\n\t/** Render a tool result to collapsed/expanded HTML. Returns undefined if tool has no custom renderer. */\n\trenderResult(\n\t\ttoolCallId: string,\n\t\ttoolName: string,\n\t\tresult: Array<{ type: string; text?: string; data?: string; mimeType?: string }>,\n\t\tdetails: unknown,\n\t\tisError: boolean,\n\t): { collapsed?: string; expanded?: string } | undefined;\n}\n\n/**\n * Create a tool HTML renderer.\n *\n * The renderer looks up tool definitions and invokes their renderCall/renderResult\n * methods, converting the resulting TUI Component output (ANSI) to HTML.\n */\nconst ANSI_ESCAPE_REGEX = /\\x1b\\[[\\d;]*m/g;\n\nfunction isBlankRenderedLine(line: string): boolean {\n\treturn line.replace(ANSI_ESCAPE_REGEX, \"\").trim().length === 0;\n}\n\nfunction trimRenderedResultLines(lines: string[]): string[] {\n\tlet start = 0;\n\tlet end = lines.length;\n\twhile (start < end && isBlankRenderedLine(lines[start])) start++;\n\twhile (end > start && isBlankRenderedLine(lines[end - 1])) end--;\n\treturn lines.slice(start, end);\n}\n\nexport function createToolHtmlRenderer(deps: ToolHtmlRendererDeps): ToolHtmlRenderer {\n\tconst { getToolRenderers, theme, cwd, width = 100 } = deps;\n\n\tconst renderedCallComponents = new Map<string, Component>();\n\tconst renderedResultComponents = new Map<string, Component>();\n\tconst renderedStates = new Map<string, any>();\n\tconst renderedArgs = new Map<string, unknown>();\n\n\tconst getState = (toolCallId: string): any => {\n\t\tlet state = renderedStates.get(toolCallId);\n\t\tif (!state) {\n\t\t\tstate = {};\n\t\t\trenderedStates.set(toolCallId, state);\n\t\t}\n\t\treturn state;\n\t};\n\n\tconst createRenderContext = (\n\t\ttoolCallId: string,\n\t\tlastComponent: Component | undefined,\n\t\texpanded: boolean,\n\t\tisPartial: boolean,\n\t\tisError: boolean,\n\t): ToolRenderContext => {\n\t\treturn {\n\t\t\targs: renderedArgs.get(toolCallId),\n\t\t\ttoolCallId,\n\t\t\tinvalidate: () => {},\n\t\t\tlastComponent,\n\t\t\tstate: getState(toolCallId),\n\t\t\tcwd,\n\t\t\texecutionStarted: true,\n\t\t\targsComplete: true,\n\t\t\tisPartial,\n\t\t\texpanded,\n\t\t\tshowImages: false,\n\t\t\tisError,\n\t\t\tdurationMs: undefined,\n\t\t\toutputPad: 1,\n\t\t};\n\t};\n\n\treturn {\n\t\trenderCall(toolCallId: string, toolName: string, args: unknown): string | undefined {\n\t\t\ttry {\n\t\t\t\trenderedArgs.set(toolCallId, args);\n\t\t\t\tconst toolDef = getToolRenderers(toolName);\n\t\t\t\tif (!toolDef?.renderCall) {\n\t\t\t\t\treturn undefined;\n\t\t\t\t}\n\n\t\t\t\tconst component = toolDef.renderCall(\n\t\t\t\t\targs,\n\t\t\t\t\ttheme,\n\t\t\t\t\tcreateRenderContext(toolCallId, renderedCallComponents.get(toolCallId), false, true, false),\n\t\t\t\t);\n\t\t\t\trenderedCallComponents.set(toolCallId, component);\n\t\t\t\tconst lines = component.render(width);\n\t\t\t\treturn ansiLinesToHtml(lines);\n\t\t\t} catch {\n\t\t\t\t// On error, return undefined so HTML export can fall back to structured result rendering\n\t\t\t\treturn undefined;\n\t\t\t}\n\t\t},\n\n\t\trenderResult(\n\t\t\ttoolCallId: string,\n\t\t\ttoolName: string,\n\t\t\tresult: Array<{ type: string; text?: string; data?: string; mimeType?: string }>,\n\t\t\tdetails: unknown,\n\t\t\tisError: boolean,\n\t\t): { collapsed?: string; expanded?: string } | undefined {\n\t\t\ttry {\n\t\t\t\tconst toolDef = getToolRenderers(toolName);\n\t\t\t\tif (!toolDef?.renderResult) {\n\t\t\t\t\treturn undefined;\n\t\t\t\t}\n\n\t\t\t\t// Build AgentToolResult from content array\n\t\t\t\t// Cast content since session storage uses generic object types\n\t\t\t\tconst agentToolResult = {\n\t\t\t\t\tcontent: result as (TextContent | ImageContent)[],\n\t\t\t\t\tdetails,\n\t\t\t\t\tisError,\n\t\t\t\t};\n\n\t\t\t\t// Render collapsed\n\t\t\t\tconst collapsedComponent = toolDef.renderResult(\n\t\t\t\t\tagentToolResult,\n\t\t\t\t\t{ expanded: false, isPartial: false },\n\t\t\t\t\ttheme,\n\t\t\t\t\tcreateRenderContext(toolCallId, renderedResultComponents.get(toolCallId), false, false, isError),\n\t\t\t\t);\n\t\t\t\trenderedResultComponents.set(toolCallId, collapsedComponent);\n\t\t\t\tconst collapsed = ansiLinesToHtml(trimRenderedResultLines(collapsedComponent.render(width)));\n\n\t\t\t\t// Render expanded\n\t\t\t\tconst expandedComponent = toolDef.renderResult(\n\t\t\t\t\tagentToolResult,\n\t\t\t\t\t{ expanded: true, isPartial: false },\n\t\t\t\t\ttheme,\n\t\t\t\t\tcreateRenderContext(toolCallId, renderedResultComponents.get(toolCallId), true, false, isError),\n\t\t\t\t);\n\t\t\t\trenderedResultComponents.set(toolCallId, expandedComponent);\n\t\t\t\tconst expanded = ansiLinesToHtml(trimRenderedResultLines(expandedComponent.render(width)));\n\n\t\t\t\treturn {\n\t\t\t\t\t...(collapsed && collapsed !== expanded ? { collapsed } : {}),\n\t\t\t\t\texpanded,\n\t\t\t\t};\n\t\t\t} catch {\n\t\t\t\t// On error, return undefined so HTML export can fall back to structured result rendering\n\t\t\t\treturn undefined;\n\t\t\t}\n\t\t},\n\t};\n}\n"]}
package/bin/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@earendil-works/pi-coding-agent",
3
- "version": "1.0.4",
3
+ "version": "1.1.0",
4
4
  "description": "Coding agent CLI with read, bash, edit, write tools and session management",
5
5
  "type": "module",
6
6
  "piConfig": {
@@ -40,19 +40,19 @@
40
40
  "clean": "shx rm -rf dist",
41
41
  "build": "npm run build:unbundled && node ../../scripts/build-coding-agent-bundle.mjs",
42
42
  "build:unbundled": "tsc -p tsconfig.build.json && shx chmod +x dist/cli.js dist/rpc-entry.js && npm run copy-assets",
43
- "build:binary": "npm --prefix ../tui run build && npm --prefix ../telemetry run build && npm --prefix ../ai run build && npm --prefix ../agent run build && npm --prefix ../protocol run build && npm --prefix ../client run build && npm run build && bun build --compile --no-compile-autoload-bunfig ./dist/bun/cli.js ./src/utils/image-resize-worker.ts ./src/extensions/codemode/worker.ts --outfile dist/pi && npm run copy-binary-assets",
43
+ "build:binary": "npm --prefix ../tui run build && npm --prefix ../telemetry run build && npm --prefix ../ai run build && npm --prefix ../agent run build && npm --prefix ../protocol run build && npm --prefix ../client run build && npm run build && bun build --compile --no-compile-autoload-bunfig --no-compile-autoload-dotenv ./dist/bun/cli.js ./src/utils/image-resize-worker.ts ./src/extensions/codemode/worker.ts --outfile dist/pi && npm run copy-binary-assets",
44
44
  "copy-assets": "shx mkdir -p dist/modes/interactive/theme && shx cp src/modes/interactive/theme/*.json dist/modes/interactive/theme/ && shx mkdir -p dist/modes/interactive/assets && shx cp src/modes/interactive/assets/*.png dist/modes/interactive/assets/ && shx mkdir -p dist/core/export-html/vendor && shx cp src/core/export-html/template.html src/core/export-html/template.css src/core/export-html/template.js dist/core/export-html/ && shx cp src/core/export-html/vendor/*.js dist/core/export-html/vendor/",
45
45
  "copy-binary-assets": "shx cp package.json dist/ && shx cp README.md dist/ && shx cp CHANGELOG.md dist/ && shx mkdir -p dist/theme && shx cp src/modes/interactive/theme/*.json dist/theme/ && shx mkdir -p dist/assets && shx cp src/modes/interactive/assets/*.png dist/assets/ && shx mkdir -p dist/export-html/vendor && shx cp src/core/export-html/template.html dist/export-html/ && shx cp src/core/export-html/vendor/*.js dist/export-html/vendor/ && shx cp -r docs dist/ && shx cp -r examples dist/ && shx cp ../../node_modules/@silvia-odwyer/photon-node/photon_rs_bg.wasm dist/",
46
46
  "test": "vitest --run",
47
47
  "prepublishOnly": "npm run clean && npm run build"
48
48
  },
49
49
  "dependencies": {
50
- "@earendil-works/chord": "^1.0.4",
51
- "@earendil-works/pi-agent-core": "^1.0.4",
52
- "@earendil-works/pi-ai": "^1.0.4",
53
- "@earendil-works/pi-codemode": "^1.0.4",
54
- "@earendil-works/pi-mcp": "^1.0.4",
55
- "@earendil-works/pi-tui": "^1.0.4",
50
+ "@earendil-works/chord": "^1.1.0",
51
+ "@earendil-works/pi-agent-core": "^1.1.0",
52
+ "@earendil-works/pi-ai": "^1.1.0",
53
+ "@earendil-works/pi-codemode": "^1.1.0",
54
+ "@earendil-works/pi-mcp": "^1.1.0",
55
+ "@earendil-works/pi-tui": "^1.1.0",
56
56
  "@silvia-odwyer/photon-node": "0.3.4",
57
57
  "brace-expansion": "5.0.12",
58
58
  "chalk": "6.0.0",
@@ -75,16 +75,16 @@
75
75
  "protobufjs": "7.6.6"
76
76
  },
77
77
  "devDependencies": {
78
- "@earendil-works/pi-client": "^1.0.4",
79
- "@earendil-works/pi-protocol": "^1.0.4",
80
- "@earendil-works/pi-server": "^1.0.4",
78
+ "@earendil-works/pi-client": "^1.1.0",
79
+ "@earendil-works/pi-protocol": "^1.1.0",
80
+ "@earendil-works/pi-server": "^1.1.0",
81
81
  "@types/cross-spawn": "6.0.6",
82
82
  "@types/hosted-git-info": "3.0.5",
83
83
  "@types/node": "22.19.19",
84
84
  "@types/proper-lockfile": "4.1.4",
85
85
  "@types/semver": "7.7.1",
86
86
  "marked": "18.0.11",
87
- "shx": "0.4.0",
87
+ "shx": "0.3.4",
88
88
  "vitest": "4.1.11"
89
89
  },
90
90
  "keywords": [
package/bin/pi CHANGED
@@ -1,4 +1,4 @@
1
1
  [diffend] Oversized file quarantined before diffing.
2
2
  name: package/bin/pi
3
- size: 76870370 bytes
4
- sha256: bceb3f3b317940c58de01bddd9decdcb0755ffb544ae793fac1745502da6ddc2
3
+ size: 76936418 bytes
4
+ sha256: 6d79ba093af5fd12f13795537282c5c69ff3a628f3c57bced3eca544ee188a64
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kingingwang/pi-darwin-arm64",
3
- "version": "1.0.4",
3
+ "version": "1.1.0",
4
4
  "description": "Pi standalone binary for darwin-arm64 (fork distribution)",
5
5
  "license": "MIT",
6
6
  "os": [