pi-better-openai 0.1.6 → 0.1.7

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.
@@ -5,8 +5,8 @@
5
5
  * enabled and the selected model is in the configured allow-list.
6
6
  */
7
7
  import type { ExtensionAPI, ExtensionContext } from "@mariozechner/pi-coding-agent";
8
- import { CONFIG_BASENAME, STATUS_KEY } from "./identity.ts";
9
- import { formatTokens, sanitizeStatusText, truncateToWidth, visibleWidth } from "./format.ts";
8
+ import { CONFIG_BASENAME, STATUS_KEY } from "./src/identity.ts";
9
+ import { formatTokens, sanitizeStatusText, truncateToWidth, visibleWidth } from "./src/format.ts";
10
10
  import {
11
11
  DEFAULT_CONFIG,
12
12
  DEFAULT_IMAGE_CONFIG,
@@ -25,7 +25,7 @@ import {
25
25
  readRawConfig,
26
26
  resolveConfig,
27
27
  writeConfig
28
- } from "./config.ts";
28
+ } from "./src/config.ts";
29
29
  import {
30
30
  AUTH_FILE,
31
31
  type UsageSnapshot,
@@ -35,8 +35,8 @@ import {
35
35
  parseUsageSnapshot,
36
36
  readCodexAuth,
37
37
  requestCodexUsage
38
- } from "./usage.ts";
39
- import { registerOpenAIImage, _imageTest } from "./image.ts";
38
+ } from "./src/usage.ts";
39
+ import { registerOpenAIImage, _imageTest } from "./src/image.ts";
40
40
 
41
41
  const COMMAND = "fast";
42
42
  const OPENAI_STATUS_COMMAND = "openai-usage";
@@ -57,8 +57,9 @@ function currentModelKey(ctx: ExtensionContext): string {
57
57
  }
58
58
 
59
59
  function supportsFast(ctx: ExtensionContext, supportedModels: SupportedModel[]): boolean {
60
- if (!ctx.model) return false;
61
- return supportedModels.some((model) => model.provider === ctx.model.provider && model.id === ctx.model.id);
60
+ const current = ctx.model;
61
+ if (!current) return false;
62
+ return supportedModels.some((model) => model.provider === current.provider && model.id === current.id);
62
63
  }
63
64
 
64
65
  function modelList(supportedModels: SupportedModel[]): string {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pi-better-openai",
3
- "version": "0.1.6",
3
+ "version": "0.1.7",
4
4
  "description": "Personal pi extension that improves OpenAI with fast mode, usage stats, and footer polish.",
5
5
  "keywords": [
6
6
  "fast",
@@ -19,7 +19,8 @@
19
19
  "url": "git+https://github.com/mattleong/pi-better-openai.git"
20
20
  },
21
21
  "files": [
22
- "extensions/",
22
+ "index.ts",
23
+ "src/",
23
24
  "README.md",
24
25
  "LICENSE"
25
26
  ],
@@ -28,7 +29,8 @@
28
29
  "access": "public"
29
30
  },
30
31
  "scripts": {
31
- "test": "node tests/basic.mjs"
32
+ "test": "node tests/basic.mjs",
33
+ "typecheck": "tsc --noEmit"
32
34
  },
33
35
  "peerDependencies": {
34
36
  "@mariozechner/pi-coding-agent": ">=0.57.0",
@@ -36,7 +38,11 @@
36
38
  },
37
39
  "pi": {
38
40
  "extensions": [
39
- "./extensions/pi-better-openai.ts"
41
+ "./index.ts"
40
42
  ]
43
+ },
44
+ "devDependencies": {
45
+ "@types/node": "^25.6.0",
46
+ "typescript": "^6.0.3"
41
47
  }
42
48
  }
@@ -74,6 +74,8 @@ export type CodexImageResult = {
74
74
  outputFormat: ImageOutputFormat;
75
75
  };
76
76
 
77
+ type ExtractedImageResult = Omit<CodexImageResult, "prompt" | "savedPath" | "model" | "action" | "outputFormat">;
78
+
77
79
  export type ImageGenerationDebug = {
78
80
  authFound: boolean;
79
81
  authSource?: string;
@@ -224,7 +226,11 @@ function asImageResultItem(value: unknown): { id?: string; status?: string; revi
224
226
  return value as { id?: string; status?: string; revised_prompt?: string; result?: string; b64_json?: string };
225
227
  }
226
228
 
227
- function extractImageFromEvent(event: unknown, fallbackMimeType: string): Omit<CodexImageResult, "savedPath" | "model" | "action" | "outputFormat"> | undefined {
229
+ function isImageContent(value: unknown): value is { type: "image"; data: string; mimeType: string } {
230
+ return isRecord(value) && value.type === "image" && typeof value.data === "string" && typeof value.mimeType === "string";
231
+ }
232
+
233
+ function extractImageFromEvent(event: unknown, fallbackMimeType: string): ExtractedImageResult | undefined {
228
234
  if (!isRecord(event)) return undefined;
229
235
  const item = asImageResultItem(event.item) ?? asImageResultItem(event);
230
236
  if (item) {
@@ -247,12 +253,12 @@ function extractImageFromEvent(event: unknown, fallbackMimeType: string): Omit<C
247
253
  return undefined;
248
254
  }
249
255
 
250
- async function parseSseForImage(response: Response, fallbackMimeType: string, signal?: AbortSignal): Promise<Omit<CodexImageResult, "savedPath" | "model" | "action" | "outputFormat">> {
256
+ async function parseSseForImage(response: Response, fallbackMimeType: string, signal?: AbortSignal): Promise<ExtractedImageResult> {
251
257
  if (!response.body) throw new Error("No response body from Codex image request.");
252
258
  const reader = response.body.getReader();
253
259
  const decoder = new TextDecoder();
254
260
  let buffer = "";
255
- let lastImage: Omit<CodexImageResult, "savedPath" | "model" | "action" | "outputFormat"> | undefined;
261
+ let lastImage: ExtractedImageResult | undefined;
256
262
  try {
257
263
  while (true) {
258
264
  if (signal?.aborted) throw new Error("Image request was aborted.");
@@ -429,11 +435,13 @@ export function registerOpenAIImage(pi: ExtensionAPI, getConfig: (ctx: Extension
429
435
  : typeof message.content === "string"
430
436
  ? message.content
431
437
  : message.content.filter((part) => part.type === "text").map((part) => part.text).join("\n");
432
- const image = result && isRecord(result) && typeof result.data === "string" && typeof result.mimeType === "string"
433
- ? { data: result.data, mimeType: result.mimeType, savedPath: typeof result.savedPath === "string" ? result.savedPath : undefined }
434
- : Array.isArray(message.content)
435
- ? message.content.find((part) => part.type === "image" && typeof part.data === "string" && typeof part.mimeType === "string")
436
- : undefined;
438
+ let image: { data: string; mimeType: string; savedPath?: string } | undefined;
439
+ if (result && isRecord(result) && typeof result.data === "string" && typeof result.mimeType === "string") {
440
+ image = { data: result.data, mimeType: result.mimeType, savedPath: typeof result.savedPath === "string" ? result.savedPath : undefined };
441
+ } else if (Array.isArray(message.content)) {
442
+ const imagePart = message.content.find(isImageContent);
443
+ if (imagePart) image = { data: imagePart.data, mimeType: imagePart.mimeType };
444
+ }
437
445
 
438
446
  const container = new Container();
439
447
  const box = new Box(1, 1, (line) => theme.bg("customMessageBg", line));
@@ -487,7 +495,7 @@ export function registerOpenAIImage(pi: ExtensionAPI, getConfig: (ctx: Extension
487
495
  const cfg = getConfig(ctx);
488
496
  const model = resolveModel(params, ctx, cfg);
489
497
  const requestParams = { ...params, prompt: resolveToolPrompt(params, ctx) };
490
- onUpdate?.({ content: [{ type: "text", text: `Requesting OpenAI image via openai-codex/${model}...` }] });
498
+ onUpdate?.({ content: [{ type: "text", text: `Requesting OpenAI image via openai-codex/${model}...` }], details: undefined });
491
499
  const result = await generate(requestParams, ctx, signal);
492
500
  return {
493
501
  content: [
File without changes
File without changes
File without changes
File without changes