pi-formatter 1.0.0 → 1.0.1

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/README.md CHANGED
@@ -3,11 +3,11 @@
3
3
  A [pi](https://pi.dev) extension that auto-formats files after `write` and
4
4
  `edit` tool calls.
5
5
 
6
- By default, formatting runs once per turn. You can also format after each tool
7
- call or defer formatting until the current session shuts down.
6
+ By default, formatting runs once per prompt after the agent finishes all its
7
+ work and yields control back to you. You can also format after each individual
8
+ tool call or defer formatting until the session shuts down.
8
9
 
9
- This default changed from the previous immediate-per-tool behavior. If you want
10
- the old default, set `"formatMode": "tool"`.
10
+ To format after every individual edit instead, set `"formatMode": "tool"`.
11
11
 
12
12
  ## 📦 Install
13
13
 
@@ -22,19 +22,17 @@ best-effort post-processing. Formatter failures never block tool results.
22
22
 
23
23
  Formatting modes:
24
24
 
25
- - `tool`: format immediately after each successful `write` or `edit` tool
26
- result.
27
- Use this mode when you want the file on disk to stay formatted after every
28
- edit, even while the agent is still working.
29
- - `turn`: collect files touched during the current turn and format them once at
30
- `turn_end`. This is the default.
31
- Use this mode when you want to avoid mid-turn formatter drift while still
32
- keeping files formatted throughout the run.
25
+ - `tool`: format immediately after each successful `write` or `edit` tool call.
26
+ Use this mode when you want files on disk to stay formatted after every edit,
27
+ even while the agent is still working.
28
+ - `prompt`: collect all files touched during the agent run and format them once
29
+ when the agent finishes and yields control back to you. This is the default.
30
+ Use this mode to avoid mid-run formatter interruptions while still getting
31
+ clean files after each response.
33
32
  - `session`: collect files touched during the current session and format them
34
- once at `session_shutdown`.
35
- Use this mode when you want the fewest formatter interruptions and are okay
36
- with formatting only when the session exits, reloads, or switches. Interrupted
37
- runs stay pending until the session ends or changes.
33
+ once at session shutdown, reload, or switch.
34
+ Use this mode when you want the fewest interruptions and are okay with
35
+ formatting only when the session ends.
38
36
 
39
37
  Supported file types:
40
38
 
@@ -61,14 +59,14 @@ folder (default: `~/.pi/agent`, overridable via `PI_CODING_AGENT_DIR`):
61
59
 
62
60
  ```json
63
61
  {
64
- "formatMode": "turn",
62
+ "formatMode": "prompt",
65
63
  "commandTimeoutMs": 10000,
66
64
  "hideCallSummariesInTui": false
67
65
  }
68
66
  ```
69
67
 
70
- - `formatMode`: formatting strategy (`"tool"` | `"turn"` | `"session"`,
71
- default: `"turn"`). Use `"tool"` to restore the old immediate default.
68
+ - `formatMode`: formatting strategy (`"tool"` | `"prompt"` | `"session"`,
69
+ default: `"prompt"`). Use `"tool"` to format after every individual edit.
72
70
  - `commandTimeoutMs`: timeout (ms) per formatter command (default: `10000`)
73
71
  - `hideCallSummariesInTui`: hide formatter pass/fail summaries in the TUI
74
72
  (default: `false`)
@@ -2,11 +2,11 @@ import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
2
2
  import { join } from "node:path";
3
3
  import { getAgentDir } from "@mariozechner/pi-coding-agent";
4
4
 
5
- export type FormatMode = "tool" | "turn" | "session";
5
+ export type FormatMode = "tool" | "prompt" | "session";
6
6
 
7
7
  const DEFAULT_COMMAND_TIMEOUT_MS = 10_000;
8
8
  const DEFAULT_HIDE_CALL_SUMMARIES_IN_TUI = false;
9
- const DEFAULT_FORMAT_MODE: FormatMode = "turn";
9
+ export const DEFAULT_FORMAT_MODE: FormatMode = "prompt";
10
10
  const FORMATTER_CONFIG_FILE = "formatter.json";
11
11
 
12
12
  export type FormatterConfigSnapshot = {
@@ -65,7 +65,7 @@ function parseBooleanValue(value: unknown, defaultValue: boolean): boolean {
65
65
  }
66
66
 
67
67
  function parseFormatMode(value: unknown, defaultValue: FormatMode): FormatMode {
68
- if (value === "tool" || value === "turn" || value === "session") {
68
+ if (value === "tool" || value === "prompt" || value === "session") {
69
69
  return value;
70
70
  }
71
71
 
@@ -79,9 +79,9 @@ function getFormatterSettingItems(
79
79
  id: "formatMode",
80
80
  label: "Format mode",
81
81
  description:
82
- "Choose whether formatting runs after each successful write/edit tool call, once after each turn, or once when the session shuts down.",
82
+ "Choose whether formatting runs after each successful write/edit tool call, once after each prompt completes, or once when the session shuts down.",
83
83
  currentValue: config.formatMode,
84
- values: ["tool", "turn", "session"],
84
+ values: ["tool", "prompt", "session"],
85
85
  },
86
86
  {
87
87
  id: "commandTimeoutMs",
@@ -112,7 +112,7 @@ type FormatterContext = {
112
112
  export default function (pi: ExtensionAPI) {
113
113
  let formatterConfig = loadFormatterConfig();
114
114
  const formatQueueByPath = new Map<string, Promise<void>>();
115
- const pendingTurnPaths = new Set<string>();
115
+ const pendingPromptPaths = new Set<string>();
116
116
  const pendingSessionPaths = new Set<string>();
117
117
 
118
118
  const enqueueFormat = async (
@@ -208,7 +208,7 @@ export default function (pi: ExtensionAPI) {
208
208
  };
209
209
 
210
210
  const flushPendingPaths = async (ctx: FormatterContext): Promise<void> => {
211
- await flushPaths(pendingTurnPaths, ctx);
211
+ await flushPaths(pendingPromptPaths, ctx);
212
212
  await flushPaths(pendingSessionPaths, ctx);
213
213
  };
214
214
 
@@ -235,32 +235,24 @@ export default function (pi: ExtensionAPI) {
235
235
  return;
236
236
  }
237
237
 
238
- if (formatterConfig.formatMode === "turn") {
239
- pendingTurnPaths.add(filePath);
238
+ if (formatterConfig.formatMode === "prompt") {
239
+ pendingPromptPaths.add(filePath);
240
240
  return;
241
241
  }
242
242
 
243
243
  pendingSessionPaths.add(filePath);
244
244
  });
245
245
 
246
- pi.on("turn_end", async (_event, ctx) => {
247
- if (pendingTurnPaths.size === 0) {
248
- return;
249
- }
250
-
251
- await flushPaths(pendingTurnPaths, ctx);
252
- });
253
-
254
246
  pi.on("agent_end", async (_event, ctx) => {
255
- if (pendingTurnPaths.size === 0) {
247
+ if (pendingPromptPaths.size === 0) {
256
248
  return;
257
249
  }
258
250
 
259
- await flushPaths(pendingTurnPaths, ctx);
251
+ await flushPaths(pendingPromptPaths, ctx);
260
252
  });
261
253
 
262
254
  pi.on("session_switch", async (_event, ctx) => {
263
- if (pendingTurnPaths.size === 0 && pendingSessionPaths.size === 0) {
255
+ if (pendingPromptPaths.size === 0 && pendingSessionPaths.size === 0) {
264
256
  return;
265
257
  }
266
258
 
@@ -268,7 +260,7 @@ export default function (pi: ExtensionAPI) {
268
260
  });
269
261
 
270
262
  pi.on("session_shutdown", async (_event, ctx) => {
271
- if (pendingTurnPaths.size === 0 && pendingSessionPaths.size === 0) {
263
+ if (pendingPromptPaths.size === 0 && pendingSessionPaths.size === 0) {
272
264
  return;
273
265
  }
274
266
 
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "pi-formatter",
3
- "version": "1.0.0",
4
- "description": "Pi extension that auto-formats files after write/edit tool calls.",
3
+ "version": "1.0.1",
4
+ "description": "Pi extension that auto-formats files.",
5
5
  "type": "module",
6
6
  "files": [
7
7
  "extensions",