@benvargas/pi-openai-fast 1.0.1 → 1.0.4

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
@@ -4,7 +4,7 @@
4
4
 
5
5
  This extension does not change the model, thinking level, tools, or prompts. It only adds `service_tier=priority` to provider requests when fast mode is active and the current model matches the configured supported-model list.
6
6
 
7
- Requires pi `0.57.0` or newer.
7
+ Requires pi `0.74.0` or newer.
8
8
 
9
9
  ## Install
10
10
 
@@ -26,6 +26,7 @@ pi -e npm:@benvargas/pi-openai-fast
26
26
  - `/fast status` reports the current fast-mode state.
27
27
  - `--fast` starts the session with fast mode enabled.
28
28
  - By default, fast mode persists across new pi sessions via a JSON config file.
29
+ - Startup state comes from the selected config file, not from resumed session/thread history.
29
30
 
30
31
  Example:
31
32
 
@@ -50,7 +51,9 @@ Default config:
50
51
  "active": false,
51
52
  "supportedModels": [
52
53
  "openai/gpt-5.4",
53
- "openai-codex/gpt-5.4"
54
+ "openai/gpt-5.5",
55
+ "openai-codex/gpt-5.4",
56
+ "openai-codex/gpt-5.5"
54
57
  ]
55
58
  }
56
59
  ```
@@ -58,15 +61,15 @@ Default config:
58
61
  Settings:
59
62
 
60
63
  - `persistState`: when `true`, `/fast` writes the current on/off state to config so it resumes in new pi sessions. Default: `true`.
61
- - `active`: persisted fast-mode state used when `persistState` is enabled.
64
+ - `active`: persisted fast-mode state used on startup when `persistState` is enabled.
62
65
  - `supportedModels`: list of `provider/model-id` strings that should receive `service_tier=priority`.
63
66
 
64
- Project config overrides global config. If fast mode is enabled on a model that is not in `supportedModels`, the setting stays on but requests are left unchanged until you switch back to a configured model.
67
+ Project config overrides global config. `/fast on` and `/fast off` write to the selected config file, so if a project config exists the remembered state is project-specific. If fast mode is enabled on a model that is not in `supportedModels`, the setting stays on but requests are left unchanged until you switch back to a configured model.
65
68
 
66
69
  ## Notes
67
70
 
68
- - Fast mode still stores session state in the current session branch.
69
71
  - When `persistState` is enabled, the last `/fast` setting also carries across brand-new pi sessions.
72
+ - Resumed sessions do not override the config-backed startup state.
70
73
  - On configured models, fast mode maps to OpenAI `service_tier=priority`.
71
74
 
72
75
  ## Uninstall
@@ -1,15 +1,32 @@
1
+ /**
2
+ * OpenAI fast mode for pi.
3
+ *
4
+ * `/fast` and `--fast` toggle `service_tier=priority` for configured models.
5
+ * This extension does not change the selected model, thinking level, tools, or prompts.
6
+ *
7
+ * Startup state comes from `pi-openai-fast.json`, not resumed session history.
8
+ * Config precedence is project `.pi/extensions/pi-openai-fast.json` over
9
+ * global `~/.pi/agent/extensions/pi-openai-fast.json`.
10
+ *
11
+ * `supportedModels` controls which `provider/model-id` pairs receive the flag.
12
+ */
1
13
  import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
2
14
  import { homedir } from "node:os";
3
15
  import { dirname, join } from "node:path";
4
- import type { ExtensionAPI, ExtensionContext } from "@mariozechner/pi-coding-agent";
16
+ import type { ExtensionAPI, ExtensionContext } from "@earendil-works/pi-coding-agent";
5
17
 
6
18
  const FAST_COMMAND = "fast";
7
19
  const FAST_FLAG = "fast";
8
- const FAST_STATE_ENTRY = "pi-openai-fast.state";
9
20
  const FAST_CONFIG_BASENAME = "pi-openai-fast.json";
10
21
  const FAST_COMMAND_ARGS = ["on", "off", "status"] as const;
11
22
  const FAST_SERVICE_TIER = "priority";
12
- const DEFAULT_SUPPORTED_MODEL_KEYS = ["openai/gpt-5.4", "openai-codex/gpt-5.4"] as const;
23
+ const DEFAULT_SUPPORTED_MODEL_KEYS = [
24
+ "openai/gpt-5.4",
25
+ "openai/gpt-5.5",
26
+ "openai-codex/gpt-5.4",
27
+ "openai-codex/gpt-5.5",
28
+ ] as const;
29
+ const LEGACY_DEFAULT_SUPPORTED_MODEL_KEYS = ["openai/gpt-5.4", "openai-codex/gpt-5.4"] as const;
13
30
 
14
31
  interface FastModeState {
15
32
  active: boolean;
@@ -121,22 +138,18 @@ function parseSupportedModels(value: unknown): FastSupportedModel[] | undefined
121
138
  return models;
122
139
  }
123
140
 
124
- function parseFastModeState(value: unknown): FastModeState | undefined {
125
- if (!isRecord(value) || typeof value.active !== "boolean") {
126
- return undefined;
141
+ function sameModelKeys(left: readonly string[] | undefined, right: readonly string[]): boolean {
142
+ if (!left || left.length !== right.length) {
143
+ return false;
127
144
  }
128
- return { active: value.active };
145
+ return left.every((value, index) => value === right[index]);
129
146
  }
130
147
 
131
- function getSavedFastModeState(ctx: ExtensionContext): FastModeState | undefined {
132
- const entries = ctx.sessionManager.getBranch();
133
- for (let i = entries.length - 1; i >= 0; i--) {
134
- const entry = entries[i];
135
- if (entry.type === "custom" && entry.customType === FAST_STATE_ENTRY) {
136
- return parseFastModeState(entry.data);
137
- }
148
+ function migrateSupportedModelKeys(value: string[] | undefined): string[] | undefined {
149
+ if (sameModelKeys(value, LEGACY_DEFAULT_SUPPORTED_MODEL_KEYS)) {
150
+ return [...DEFAULT_SUPPORTED_MODEL_KEYS];
138
151
  }
139
- return undefined;
152
+ return value;
140
153
  }
141
154
 
142
155
  function readConfigFile(filePath: string): FastConfigFile | null {
@@ -194,7 +207,8 @@ function resolveFastConfig(cwd: string, homeDir: string = homedir()): ResolvedFa
194
207
  const selectedConfigPath = existsSync(projectConfigPath) ? projectConfigPath : globalConfigPath;
195
208
  const merged = { ...globalConfig, ...projectConfig };
196
209
  const supportedModels =
197
- parseSupportedModels(merged.supportedModels) ?? parseSupportedModels(DEFAULT_SUPPORTED_MODEL_KEYS);
210
+ parseSupportedModels(migrateSupportedModelKeys(merged.supportedModels)) ??
211
+ parseSupportedModels(DEFAULT_SUPPORTED_MODEL_KEYS);
198
212
 
199
213
  return {
200
214
  configPath: selectedConfigPath,
@@ -251,9 +265,19 @@ function applyFastServiceTier(payload: unknown): unknown {
251
265
 
252
266
  export default function piOpenAIFast(pi: ExtensionAPI): void {
253
267
  let state: FastModeState = { active: false };
268
+ let cachedConfig: ResolvedFastConfig | undefined;
269
+
270
+ function refreshConfig(ctx: ExtensionContext): ResolvedFastConfig {
271
+ cachedConfig = resolveFastConfig(getConfigCwd(ctx));
272
+ return cachedConfig;
273
+ }
274
+
275
+ function getConfig(ctx: ExtensionContext): ResolvedFastConfig {
276
+ return cachedConfig ?? refreshConfig(ctx);
277
+ }
254
278
 
255
279
  function persistState(config: ResolvedFastConfig): void {
256
- pi.appendEntry(FAST_STATE_ENTRY, state);
280
+ cachedConfig = { ...config, active: state.active };
257
281
  if (!config.persistState) {
258
282
  return;
259
283
  }
@@ -262,7 +286,7 @@ export default function piOpenAIFast(pi: ExtensionAPI): void {
262
286
  }
263
287
 
264
288
  async function enableFastMode(ctx: ExtensionContext, options?: { notify?: boolean }): Promise<void> {
265
- const config = resolveFastConfig(getConfigCwd(ctx));
289
+ const config = refreshConfig(ctx);
266
290
  if (state.active) {
267
291
  if (options?.notify !== false) {
268
292
  ctx.ui.notify("Fast mode is already on.", "info");
@@ -279,7 +303,7 @@ export default function piOpenAIFast(pi: ExtensionAPI): void {
279
303
  }
280
304
 
281
305
  async function disableFastMode(ctx: ExtensionContext, options?: { notify?: boolean }): Promise<void> {
282
- const config = resolveFastConfig(getConfigCwd(ctx));
306
+ const config = refreshConfig(ctx);
283
307
  if (!state.active) {
284
308
  if (options?.notify !== false) {
285
309
  ctx.ui.notify("Fast mode is already off.", "info");
@@ -334,10 +358,7 @@ export default function piOpenAIFast(pi: ExtensionAPI): void {
334
358
  await disableFastMode(ctx);
335
359
  return;
336
360
  case "status":
337
- ctx.ui.notify(
338
- describeCurrentState(ctx, state.active, resolveFastConfig(getConfigCwd(ctx)).supportedModels),
339
- "info",
340
- );
361
+ ctx.ui.notify(describeCurrentState(ctx, state.active, refreshConfig(ctx).supportedModels), "info");
341
362
  return;
342
363
  default:
343
364
  ctx.ui.notify("Usage: /fast [on|off|status]", "error");
@@ -346,7 +367,7 @@ export default function piOpenAIFast(pi: ExtensionAPI): void {
346
367
  });
347
368
 
348
369
  pi.on("before_provider_request", (event, ctx) => {
349
- const config = resolveFastConfig(getConfigCwd(ctx));
370
+ const config = getConfig(ctx);
350
371
  if (!state.active || !isFastSupportedModel(ctx.model, config.supportedModels)) {
351
372
  return;
352
373
  }
@@ -354,11 +375,8 @@ export default function piOpenAIFast(pi: ExtensionAPI): void {
354
375
  });
355
376
 
356
377
  pi.on("session_start", async (_event, ctx) => {
357
- const config = resolveFastConfig(getConfigCwd(ctx));
358
- const savedState = getSavedFastModeState(ctx);
359
- const persistedState =
360
- config.persistState && typeof config.active === "boolean" ? { active: config.active } : undefined;
361
- state = savedState ?? persistedState ?? { active: false };
378
+ const config = refreshConfig(ctx);
379
+ state = config.persistState && typeof config.active === "boolean" ? { active: config.active } : { active: false };
362
380
 
363
381
  if (pi.getFlag(FAST_FLAG) === true) {
364
382
  if (!state.active) {
@@ -369,7 +387,7 @@ export default function piOpenAIFast(pi: ExtensionAPI): void {
369
387
  return;
370
388
  }
371
389
 
372
- if (!savedState && state.active) {
390
+ if (state.active) {
373
391
  ctx.ui.notify(describeCurrentState(ctx, state.active, config.supportedModels), "info");
374
392
  }
375
393
  });
@@ -378,16 +396,16 @@ export default function piOpenAIFast(pi: ExtensionAPI): void {
378
396
  export const _test = {
379
397
  FAST_COMMAND,
380
398
  FAST_FLAG,
381
- FAST_STATE_ENTRY,
382
399
  FAST_CONFIG_BASENAME,
383
400
  FAST_COMMAND_ARGS,
384
401
  FAST_SERVICE_TIER,
385
402
  DEFAULT_SUPPORTED_MODEL_KEYS,
403
+ LEGACY_DEFAULT_SUPPORTED_MODEL_KEYS,
386
404
  DEFAULT_CONFIG_FILE,
387
405
  getConfigPaths,
388
- parseFastModeState,
389
406
  parseSupportedModelKey,
390
407
  parseSupportedModels,
408
+ migrateSupportedModelKeys,
391
409
  readConfigFile,
392
410
  resolveFastConfig,
393
411
  isFastSupportedModel,
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@benvargas/pi-openai-fast",
3
- "version": "1.0.1",
4
- "description": "OpenAI fast mode toggle for pi - Enables priority service tier on supported GPT-5.4 models",
3
+ "version": "1.0.4",
4
+ "description": "OpenAI fast mode toggle for pi - Enables priority service tier on supported GPT-5 models",
5
5
  "keywords": [
6
6
  "pi",
7
7
  "pi-package",
@@ -10,6 +10,7 @@
10
10
  "openai",
11
11
  "codex",
12
12
  "gpt-5.4",
13
+ "gpt-5.5",
13
14
  "fast",
14
15
  "priority",
15
16
  "service-tier"
@@ -26,7 +27,7 @@
26
27
  ]
27
28
  },
28
29
  "peerDependencies": {
29
- "@mariozechner/pi-coding-agent": ">=0.57.0"
30
+ "@earendil-works/pi-coding-agent": ">=0.74.0"
30
31
  },
31
32
  "repository": {
32
33
  "type": "git",