@herbertgao/pi-extensions 2026.9.4 → 2026.9.5

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.
Files changed (109) hide show
  1. package/node_modules/@dietrichgebert/ponytail/.qoder-plugin/plugin.json +1 -1
  2. package/node_modules/@dietrichgebert/ponytail/README.es.md +33 -2
  3. package/node_modules/@dietrichgebert/ponytail/README.ko.md +33 -2
  4. package/node_modules/@dietrichgebert/ponytail/README.md +49 -5
  5. package/node_modules/@dietrichgebert/ponytail/assets/retriever-icon.png +0 -0
  6. package/node_modules/@dietrichgebert/ponytail/assets/retriever-logo-dark.svg +4 -0
  7. package/node_modules/@dietrichgebert/ponytail/assets/retriever-logo-light.svg +4 -0
  8. package/node_modules/@dietrichgebert/ponytail/hooks/claude-codex-hooks.json +0 -3
  9. package/node_modules/@dietrichgebert/ponytail/hooks/cursor-hooks.json +17 -0
  10. package/node_modules/@dietrichgebert/ponytail/hooks/ponytail-activate.js +22 -3
  11. package/node_modules/@dietrichgebert/ponytail/hooks/ponytail-mode-tracker.js +27 -2
  12. package/node_modules/@dietrichgebert/ponytail/hooks/ponytail-runtime.js +61 -2
  13. package/node_modules/@dietrichgebert/ponytail/package.json +2 -1
  14. package/node_modules/@dietrichgebert/ponytail/scripts/cursor-hooks.js +135 -0
  15. package/node_modules/@dietrichgebert/ponytail/scripts/uninstall.js +21 -4
  16. package/node_modules/@herbertgao/pi-cc-extensions/extensions/feature/reference/index.ts +33 -15
  17. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/mouse/interaction.ts +6 -2
  18. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/mouse/scroll.ts +23 -1
  19. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/diff/diff-renderer.ts +69 -14
  20. package/node_modules/@herbertgao/pi-cc-extensions/package.json +3 -3
  21. package/node_modules/@herbertgao/sol-pi/src/sol-pi/extensions/online-context-compact/economics.ts +4 -4
  22. package/node_modules/@herbertgao/sol-pi/src/sol-pi/extensions/online-context-compact/extension.ts +41 -1
  23. package/node_modules/@juicesharp/rpiv-ask-user-question/ask-user-question.ts +5 -1
  24. package/node_modules/@juicesharp/rpiv-ask-user-question/events.ts +5 -1
  25. package/node_modules/@juicesharp/rpiv-ask-user-question/package.json +3 -2
  26. package/node_modules/@juicesharp/rpiv-ask-user-question/tool/normalize-params.ts +56 -0
  27. package/node_modules/@juicesharp/rpiv-ask-user-question/view/components/option-list-view.ts +1 -1
  28. package/node_modules/@juicesharp/rpiv-ask-user-question/view/components/tab-bar.ts +1 -2
  29. package/node_modules/@pi-plugins/fast-mode/README.md +31 -44
  30. package/node_modules/@pi-plugins/fast-mode/dist/index.mjs +20914 -30
  31. package/node_modules/@pi-plugins/fast-mode/dist/index.mjs.map +1 -1
  32. package/node_modules/@pi-plugins/fast-mode/package.json +5 -7
  33. package/node_modules/@tifan/pi-copy-response/README.md +2 -2
  34. package/node_modules/@tifan/pi-copy-response/package.json +3 -2
  35. package/node_modules/@tifan/pi-inline-skills/README.md +2 -2
  36. package/node_modules/@tifan/pi-inline-skills/package.json +3 -2
  37. package/node_modules/@tifan/pi-mermaid-open/README.md +1 -1
  38. package/node_modules/@tifan/pi-mermaid-open/package.json +3 -2
  39. package/node_modules/@tifan/pi-preferred-thinking/package.json +3 -2
  40. package/node_modules/@tifan/pi-recap/package.json +3 -2
  41. package/node_modules/pi-mcp-adapter/CHANGELOG.md +78 -0
  42. package/node_modules/pi-mcp-adapter/README.md +125 -19
  43. package/node_modules/pi-mcp-adapter/agent-plugin-loader.ts +69 -30
  44. package/node_modules/pi-mcp-adapter/agent-plugin-provenance.ts +36 -0
  45. package/node_modules/pi-mcp-adapter/claude-plugin-loader.ts +365 -0
  46. package/node_modules/pi-mcp-adapter/commands.ts +13 -15
  47. package/node_modules/pi-mcp-adapter/config.ts +198 -30
  48. package/node_modules/pi-mcp-adapter/consent-manager.ts +40 -9
  49. package/node_modules/pi-mcp-adapter/direct-tool-surface.ts +250 -0
  50. package/node_modules/pi-mcp-adapter/direct-tools.ts +9 -228
  51. package/node_modules/pi-mcp-adapter/dist/agent-plugin-loader.js +74 -32
  52. package/node_modules/pi-mcp-adapter/dist/agent-plugin-loader.js.map +1 -1
  53. package/node_modules/pi-mcp-adapter/dist/agent-plugin-provenance.d.ts +1 -0
  54. package/node_modules/pi-mcp-adapter/dist/agent-plugin-provenance.js +31 -0
  55. package/node_modules/pi-mcp-adapter/dist/agent-plugin-provenance.js.map +1 -0
  56. package/node_modules/pi-mcp-adapter/dist/claude-plugin-loader.d.ts +9 -0
  57. package/node_modules/pi-mcp-adapter/dist/claude-plugin-loader.js +362 -0
  58. package/node_modules/pi-mcp-adapter/dist/claude-plugin-loader.js.map +1 -0
  59. package/node_modules/pi-mcp-adapter/dist/config.d.ts +3 -1
  60. package/node_modules/pi-mcp-adapter/dist/config.js +189 -27
  61. package/node_modules/pi-mcp-adapter/dist/config.js.map +1 -1
  62. package/node_modules/pi-mcp-adapter/dist/metadata-cache.js +7 -16
  63. package/node_modules/pi-mcp-adapter/dist/metadata-cache.js.map +1 -1
  64. package/node_modules/pi-mcp-adapter/dist/package-mcp-loader.js +5 -17
  65. package/node_modules/pi-mcp-adapter/dist/package-mcp-loader.js.map +1 -1
  66. package/node_modules/pi-mcp-adapter/dist/types.d.ts +30 -4
  67. package/node_modules/pi-mcp-adapter/dist/types.js +26 -0
  68. package/node_modules/pi-mcp-adapter/dist/types.js.map +1 -1
  69. package/node_modules/pi-mcp-adapter/dist/utils.d.ts +6 -0
  70. package/node_modules/pi-mcp-adapter/dist/utils.js +65 -6
  71. package/node_modules/pi-mcp-adapter/dist/utils.js.map +1 -1
  72. package/node_modules/pi-mcp-adapter/host-html-template.ts +20 -19
  73. package/node_modules/pi-mcp-adapter/http-ca.ts +84 -0
  74. package/node_modules/pi-mcp-adapter/index.ts +827 -164
  75. package/node_modules/pi-mcp-adapter/init.ts +48 -10
  76. package/node_modules/pi-mcp-adapter/lazy-loader.ts +7 -0
  77. package/node_modules/pi-mcp-adapter/mcp-auth-fetch.ts +113 -0
  78. package/node_modules/pi-mcp-adapter/mcp-auth-flow.ts +256 -77
  79. package/node_modules/pi-mcp-adapter/mcp-auth.ts +316 -54
  80. package/node_modules/pi-mcp-adapter/mcp-code.ts +45 -18
  81. package/node_modules/pi-mcp-adapter/mcp-install.ts +60 -0
  82. package/node_modules/pi-mcp-adapter/mcp-oauth-provider.ts +70 -6
  83. package/node_modules/pi-mcp-adapter/mcp-output-guard.ts +53 -42
  84. package/node_modules/pi-mcp-adapter/mcp-panel-theme.ts +104 -0
  85. package/node_modules/pi-mcp-adapter/mcp-panel.ts +366 -332
  86. package/node_modules/pi-mcp-adapter/mcp-references.ts +9 -14
  87. package/node_modules/pi-mcp-adapter/mcp-script-worker.mjs +3 -1
  88. package/node_modules/pi-mcp-adapter/mcp-setup-panel.ts +383 -341
  89. package/node_modules/pi-mcp-adapter/mcp-status.ts +5 -0
  90. package/node_modules/pi-mcp-adapter/metadata-cache.ts +7 -16
  91. package/node_modules/pi-mcp-adapter/namespace-tools.ts +61 -3
  92. package/node_modules/pi-mcp-adapter/oauth.ts +6 -2
  93. package/node_modules/pi-mcp-adapter/package-mcp-loader.ts +5 -17
  94. package/node_modules/pi-mcp-adapter/package.json +13 -3
  95. package/node_modules/pi-mcp-adapter/prompts.ts +35 -3
  96. package/node_modules/pi-mcp-adapter/proxy-modes.ts +108 -7
  97. package/node_modules/pi-mcp-adapter/runtime-owner.ts +16 -1
  98. package/node_modules/pi-mcp-adapter/sampling-handler.ts +9 -32
  99. package/node_modules/pi-mcp-adapter/sandbox-proxy-template.ts +20 -93
  100. package/node_modules/pi-mcp-adapter/server-manager.ts +227 -40
  101. package/node_modules/pi-mcp-adapter/session-approvals.ts +187 -0
  102. package/node_modules/pi-mcp-adapter/skills/mcp-scripting/SKILL.md +9 -1
  103. package/node_modules/pi-mcp-adapter/state.ts +10 -1
  104. package/node_modules/pi-mcp-adapter/tool-approval.ts +10 -22
  105. package/node_modules/pi-mcp-adapter/tool-metadata.ts +14 -0
  106. package/node_modules/pi-mcp-adapter/types.ts +57 -4
  107. package/node_modules/pi-mcp-adapter/ui-server.ts +36 -28
  108. package/node_modules/pi-mcp-adapter/utils.ts +64 -6
  109. package/package.json +12 -15
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@herbertgao/pi-cc-extensions",
3
- "version": "0.9.1",
3
+ "version": "0.9.2",
4
4
  "license": "MIT",
5
5
  "description": "A Pi productivity suite with Claude Code-style UI, context inspection, and agent/session references",
6
6
  "type": "module",
@@ -69,8 +69,8 @@
69
69
  },
70
70
  "x-upstream": {
71
71
  "package": "pi-cc-extensions",
72
- "version": "0.8.70",
72
+ "version": "0.8.71",
73
73
  "repository": "https://github.com/minuque/pi-cc-extensions",
74
- "commit": "9f200064951ffb148ecec2e1cf0dab7a2940f823"
74
+ "commit": "e43e0041b59f5d7f03be9b9d103a5f9e954e4c11"
75
75
  }
76
76
  }
@@ -218,9 +218,8 @@ export function decideCompaction(input: {
218
218
  carriedDebtTokens: input.carriedDebtTokens,
219
219
  cacheDebtRepaymentTokens: input.cacheDebtRepaymentTokens,
220
220
  compact,
221
- reason: !compressible
222
- ? "non_positive_saving"
223
- : windowProtection
221
+ reason: compressible
222
+ ? windowProtection
224
223
  ? "window_protection"
225
224
  : economic
226
225
  ? "economic"
@@ -232,6 +231,7 @@ export function decideCompaction(input: {
232
231
  ? "deferred_subsequent_margin"
233
232
  : !firstCompaction && baseEconomic && !carriedDebtGateOpen
234
233
  ? "deferred_carried_debt"
235
- : "deferred_economic",
234
+ : "deferred_economic"
235
+ : "non_positive_saving",
236
236
  };
237
237
  }
@@ -2,12 +2,13 @@
2
2
  * SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
3
3
  * SPDX-License-Identifier: MIT
4
4
  */
5
- import type { AgentMessage, AgentToolResult } from "@earendil-works/pi-agent-core";
5
+ import type { AgentMessage, AgentToolResult, ThinkingLevel } from "@earendil-works/pi-agent-core";
6
6
  import {
7
7
  buildSessionContext,
8
8
  estimateTokens,
9
9
  findCutPoint,
10
10
  sessionEntryToContextMessages,
11
+ type ExtensionAPI,
11
12
  type ExtensionContext,
12
13
  type ExtensionFactory,
13
14
  type SessionEntry,
@@ -165,6 +166,37 @@ function validPositiveInteger(value: unknown): value is number {
165
166
  return typeof value === "number" && Number.isSafeInteger(value) && value > 0;
166
167
  }
167
168
 
169
+ type CompactionThinkingOverride = {
170
+ readonly previous: ThinkingLevel;
171
+ readonly applied: ThinkingLevel;
172
+ };
173
+
174
+ // Native summaries share their output cap with reasoning; reserve the cap for summary text.
175
+ function lowerCompactionThinking(
176
+ pi: ExtensionAPI,
177
+ reasoning: boolean,
178
+ ): CompactionThinkingOverride | undefined {
179
+ if (!reasoning) return;
180
+ try {
181
+ const previous = pi.getThinkingLevel();
182
+ if (previous !== "high" && previous !== "xhigh" && previous !== "max") return;
183
+ pi.setThinkingLevel("medium");
184
+ const applied = pi.getThinkingLevel();
185
+ return applied === previous ? undefined : { previous, applied };
186
+ } catch {
187
+ return;
188
+ }
189
+ }
190
+
191
+ function restoreCompactionThinking(pi: ExtensionAPI, override: CompactionThinkingOverride | undefined): void {
192
+ if (!override) return;
193
+ try {
194
+ if (pi.getThinkingLevel() === override.applied) pi.setThinkingLevel(override.previous);
195
+ } catch {
196
+ // A compaction result must not be masked by a best-effort state restore.
197
+ }
198
+ }
199
+
168
200
  function releaseParentContinuation(continuation: PendingContinuation | undefined): void {
169
201
  if (continuation) setTimeout(continuation.resolve, 0);
170
202
  }
@@ -182,6 +214,7 @@ export function createOnlineContextCompactExtension(options: OnlineContextCompac
182
214
  let activeDebt: CacheDebt | undefined;
183
215
  let nextContinuation: PendingContinuation | undefined;
184
216
  let compactionInFlight = false;
217
+ let compactionThinkingOverride: CompactionThinkingOverride | undefined;
185
218
 
186
219
  const releaseContinuation = (): void => {
187
220
  const continuation = nextContinuation;
@@ -349,6 +382,7 @@ export function createOnlineContextCompactExtension(options: OnlineContextCompac
349
382
  let compactionError: Error | undefined;
350
383
  try {
351
384
  compactionInFlight = true;
385
+ compactionThinkingOverride = lowerCompactionThinking(pi, context.model?.reasoning === true);
352
386
  await new Promise<void>((resolve) => {
353
387
  let finished = false;
354
388
  const finish = (): void => {
@@ -382,6 +416,8 @@ export function createOnlineContextCompactExtension(options: OnlineContextCompac
382
416
  },
383
417
  });
384
418
  });
419
+ restoreCompactionThinking(pi, compactionThinkingOverride);
420
+ compactionThinkingOverride = undefined;
385
421
  compactionInFlight = false;
386
422
  if (
387
423
  compactionError &&
@@ -422,6 +458,8 @@ export function createOnlineContextCompactExtension(options: OnlineContextCompac
422
458
  await continuation.promise;
423
459
  }
424
460
  } finally {
461
+ restoreCompactionThinking(pi, compactionThinkingOverride);
462
+ compactionThinkingOverride = undefined;
425
463
  compactionInFlight = false;
426
464
  activeDebt = undefined;
427
465
  releaseParentContinuation(parentContinuation);
@@ -445,6 +483,8 @@ export function createOnlineContextCompactExtension(options: OnlineContextCompac
445
483
  });
446
484
 
447
485
  pi.on("session_shutdown", () => {
486
+ restoreCompactionThinking(pi, compactionThinkingOverride);
487
+ compactionThinkingOverride = undefined;
448
488
  releaseContinuation();
449
489
  pendingBoundary = undefined;
450
490
  selected = undefined;
@@ -18,6 +18,7 @@ import {
18
18
  import { type DialogUI, hasDialogUI, runRpcQuestionnaire } from "./rpc-fallback.js";
19
19
  import { displayLabel, t } from "./state/i18n-bridge.js";
20
20
  import { sentinelsToAppend } from "./state/row-intent.js";
21
+ import { normalizeQuestionParams } from "./tool/normalize-params.js";
21
22
  import { buildQuestionnaireResponse, buildToolResult } from "./tool/response-envelope.js";
22
23
  import {
23
24
  MAX_OPTIONS,
@@ -310,7 +311,10 @@ export function registerAskUserQuestionTool(pi: ExtensionAPI): void {
310
311
  parameters: QuestionParamsSchema,
311
312
 
312
313
  async execute(_toolCallId, params, _signal, _onUpdate, ctx) {
313
- const typed = params as unknown as QuestionParams;
314
+ // Line-terminator normalization runs once here, ahead of validation, so
315
+ // every downstream consumer — validator, TUI, RPC walker, envelope, prompt
316
+ // event — sees the same clean text (#192).
317
+ const typed = normalizeQuestionParams(params as unknown as QuestionParams);
314
318
  if (!ctx.hasUI) return rejectWithoutUi();
315
319
 
316
320
  const validation = validateQuestionnaire(typed);
@@ -38,7 +38,11 @@ export interface AskUserBlockedEventPayload {
38
38
  }
39
39
 
40
40
  export interface AskUserPromptQuestion {
41
- /** The full question text, exactly as the agent authored it. */
41
+ /**
42
+ * The full question text as the agent authored it, with line terminators
43
+ * normalized at tool entry (`\r\n` → `\n`, lone `\r` removed — #192). The
44
+ * same normalization applies to `header` and every option field below.
45
+ */
42
46
  question: string;
43
47
  /** The short chip/tag shown next to the question. */
44
48
  header: string;
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@juicesharp/rpiv-ask-user-question",
3
- "version": "2.9.0",
3
+ "version": "2.10.1",
4
4
  "description": "Pi extension. A structured questionnaire the model can put to you when it would otherwise guess, with typed options instead of free-form replies.",
5
5
  "keywords": [
6
6
  "pi-package",
@@ -56,6 +56,7 @@
56
56
  "state/state-reducer.ts",
57
57
  "state/state.ts",
58
58
  "tool/format-answer.ts",
59
+ "tool/normalize-params.ts",
59
60
  "tool/response-envelope.ts",
60
61
  "tool/types.ts",
61
62
  "tool/validate-questionnaire.ts",
@@ -94,7 +95,7 @@
94
95
  }
95
96
  },
96
97
  "dependencies": {
97
- "@juicesharp/rpiv-config": "^2.9.0",
98
+ "@juicesharp/rpiv-config": "^2.10.1",
98
99
  "typebox": "^1.1.24"
99
100
  }
100
101
  }
@@ -0,0 +1,56 @@
1
+ import type { QuestionParams } from "./types.js";
2
+
3
+ /**
4
+ * Normalize line terminators in one model-supplied text field (#192).
5
+ *
6
+ * Some models serialize a bare carriage return inside tool-call string
7
+ * arguments at token boundaries where the text was meant to be contiguous
8
+ * (`GEMBA\r_LOG\r_FILE` for `GEMBA_LOG_FILE`). A raw CR is a cursor-control
9
+ * byte, not text: pi-tui ≤0.80 writes it straight into the row, so the
10
+ * terminal returns to column 0 and later text overwrites the pointer and
11
+ * number; pi-tui ≥0.84 splits `wrapTextWithAnsi` on `\r`, so one option
12
+ * fragments into stacked rows. Both symptoms have the same fix at our
13
+ * boundary:
14
+ *
15
+ * - `\r\n` → `\n` keeps genuine multi-line content (preview markdown) intact.
16
+ * - a lone `\r` is deleted — never a space (phantom gaps inside words) and
17
+ * never `\n` (reintroduces the vertical fragmentation). This matches
18
+ * pi-coding-agent's own display normalization (`normalizeDisplayText`).
19
+ */
20
+ export function normalizeLineTerminators(text: string): string {
21
+ return text.replace(/\r\n/g, "\n").replace(/\r/g, "");
22
+ }
23
+
24
+ /**
25
+ * Copy `obj`, normalizing the listed keys that hold strings. Keys absent from
26
+ * `obj` (e.g. an omitted `preview`) stay absent so `"preview" in option`
27
+ * checks and `hasPreview` derivations are unchanged.
28
+ */
29
+ function normalizeStringFields<T extends object>(obj: T, keys: readonly (keyof T)[]): T {
30
+ const out = { ...obj };
31
+ for (const key of keys) {
32
+ const value = obj[key];
33
+ if (typeof value === "string") out[key] = normalizeLineTerminators(value) as T[typeof key];
34
+ }
35
+ return out;
36
+ }
37
+
38
+ /**
39
+ * Return a copy of the tool params with every user-facing string field
40
+ * (`question`, `header`, `options[].label`, `options[].description`,
41
+ * `options[].preview`) line-terminator-normalized. Runs once at tool entry,
42
+ * BEFORE `validateQuestionnaire`, so the reserved-label and duplicate-label
43
+ * guards compare the text the user will actually see (`"Other\r"` must not
44
+ * slip past `reserved_label`), and so the TUI, the RPC dialog walker, the
45
+ * envelope echo, and the `rpiv:ask-user:prompt` payload all carry the same
46
+ * clean text. Pure: the input object is never mutated.
47
+ */
48
+ export function normalizeQuestionParams(params: QuestionParams): QuestionParams {
49
+ return {
50
+ ...params,
51
+ questions: params.questions.map((q) => ({
52
+ ...normalizeStringFields(q, ["question", "header"]),
53
+ options: q.options.map((o) => normalizeStringFields(o, ["label", "description", "preview"])),
54
+ })),
55
+ };
56
+ }
@@ -13,7 +13,7 @@ export interface OptionListViewConfig {
13
13
  }
14
14
 
15
15
  /**
16
- * Per-tick projection of OptionListView state. After Phase 11b, `inputBuffer`
16
+ * Per-tick projection of OptionListView state. `inputBuffer`
17
17
  * is part of the props bag — the session-owned `inlineInput` (a headless
18
18
  * `pi-tui` Editor instance) supplies its current `getText()` here per tick.
19
19
  * `OptionListView` is purely props-driven; the imperative buffer surface and
@@ -6,8 +6,7 @@ import type { StatefulView } from "../stateful-view.js";
6
6
  * Per-tick projection of TabBar state. The selector
7
7
  * (`selectTabBarProps`) hoists every render-time derivation
8
8
  * (`allAnswered`, `answered`, `isActive`, `submitActive`) into props so
9
- * `render()` is pure styling. Replaces the prior `setConfig(TabBarConfig)`
10
- * snowflake and the inline `+ 1` magic at `props-adapter.ts:127`.
9
+ * `render()` is pure styling.
11
10
  */
12
11
  export interface TabBarProps {
13
12
  /** One per author-defined question, in order. */
@@ -1,12 +1,7 @@
1
1
  # `@pi-plugins/fast-mode`
2
2
 
3
- A [pi-agent](https://github.com/earendil-works/pi) extension that requests a
4
- provider's fast (priority) service tier for configured models — faster inference at a
5
- higher token cost.
6
-
7
- Fast mode is a per-model opt-in: you decide which `provider/model-id` pairs it
8
- applies to, and a single session toggle turns it on and off. Requests for any other
9
- model are left untouched.
3
+ Request priority inference for selected models in
4
+ [pi](https://github.com/earendil-works/pi) with a session toggle.
10
5
 
11
6
  ## Install
12
7
 
@@ -14,49 +9,45 @@ model are left untouched.
14
9
  pi install npm:@pi-plugins/fast-mode
15
10
  ```
16
11
 
17
- For a one-off run without adding it to settings:
12
+ To try it for one session without changing your settings:
18
13
 
19
14
  ```bash
20
15
  pi -e npm:@pi-plugins/fast-mode
21
16
  ```
22
17
 
23
- For local development, load it straight from this directory:
24
-
25
- ```bash
26
- pi -e ./plugins/fast-mode
27
- ```
28
-
29
- ## Supported providers
30
-
31
- | Provider | Mechanism |
32
- | -------------- | ---------------------------------- |
33
- | `openai` | `service_tier: "priority"` payload |
34
- | `openai-codex` | `service_tier: "priority"` payload |
35
-
36
18
  ## Usage
37
19
 
38
- ```text
39
- /fast # toggle fast mode for this session
40
- /fast on # enable
41
- /fast off # disable
42
- /fast status # show the current state and why it is (in)active
43
- ```
20
+ Use `/fast` to control fast mode for the current session:
44
21
 
45
- Start a session with fast mode already enabled:
22
+ | Command | Action |
23
+ | -------------- | ---------------------------------------------------------------------------- |
24
+ | `/fast` | Toggle fast mode. |
25
+ | `/fast on` | Enable fast mode. |
26
+ | `/fast off` | Disable fast mode. |
27
+ | `/fast status` | Show the current state and explain whether it applies to the selected model. |
28
+
29
+ To start a session with fast mode enabled:
46
30
 
47
31
  ```bash
48
32
  pi --fast
49
33
  ```
50
34
 
51
- While fast mode is on and the current model is configured for it, a dim `[fast mode]`
52
- indicator is shown at the right of a status line right above the editor, shared with
53
- other pi-plugins extensions (e.g. `@pi-plugins/speed` renders its measurements at the
54
- left of the same line).
35
+ Fast mode applies only to models listed in the configuration. Other models are left
36
+ unchanged. A `[fast mode]` indicator appears above the editor while active.
37
+
38
+ ## Supported providers
39
+
40
+ | Provider | Pi provider |
41
+ | ------------ | -------------- |
42
+ | OpenAI | `openai` |
43
+ | OpenAI Codex | `openai-codex` |
44
+
45
+ Priority availability depends on the provider and model.
55
46
 
56
47
  ## Configuration
57
48
 
58
- Optional config file at `<agent-dir>/extensions/fast-mode.json` (typically
59
- `~/.pi/agent/extensions/fast-mode.json`):
49
+ Optionally create `<agent-dir>/extensions/fast-mode.json`, typically
50
+ `~/.pi/agent/extensions/fast-mode.json`. The defaults are:
60
51
 
61
52
  ```json
62
53
  {
@@ -79,16 +70,12 @@ Optional config file at `<agent-dir>/extensions/fast-mode.json` (typically
79
70
  }
80
71
  ```
81
72
 
82
- - `enabled`: fast-mode state at session start (`/fast` overrides it for the session
83
- without writing the toggle back to the file).
84
- - `models`: the `provider/model-id` keys fast mode applies to. The defaults above are
85
- used when the file is absent. Models whose API has no fast-mode support are
86
- ignored.
87
- - `showStatus`: show the `[fast mode]` indicator above the editor while active.
73
+ | Setting | Description |
74
+ | ------------ | ----------------------------------------------------------------------------------------------------------- |
75
+ | `enabled` | Enable fast mode at session start. `/fast` changes only the current session and does not write to the file. |
76
+ | `models` | The exact `provider/model-id` pairs fast mode applies to. |
77
+ | `showStatus` | Show the status indicator while fast mode is active. |
88
78
 
89
79
  ## Notes
90
80
 
91
- - The priority service tier bills at a higher rate than the default tier — check your
92
- provider's pricing before leaving it enabled.
93
- - If another extension already set a `service_tier` on the payload, this extension
94
- leaves it alone.
81
+ Priority inference can cost more. Check your provider's pricing before enabling it.