Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ jobs:
- uses: actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1 # v7.1.0
with:
node-version: ${{ matrix.node }}
- uses: pnpm/action-setup@ea17c68df8912ef543352723c149a84f56e3d413 # v6.1.0
- uses: pnpm/action-setup@73e46992e05b19abd31f2f3c20e0e7370d762115 # v6.1.1
with:
version: 12.16.1
- run: pnpm install --frozen-lockfile --ignore-scripts
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ jobs:
- uses: actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1 # v7.1.0
with:
node-version: 24
- uses: pnpm/action-setup@ea17c68df8912ef543352723c149a84f56e3d413 # v6.1.0
- uses: pnpm/action-setup@73e46992e05b19abd31f2f3c20e0e7370d762115 # v6.1.1
with:
version: 12.16.1
- run: test "v$(jq -r .version package.json)" = "$GITHUB_REF_NAME"
Expand Down
2 changes: 1 addition & 1 deletion biome.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"$schema": "https://biomejs.dev/schemas/2.6.4/schema.json",
"$schema": "https://biomejs.dev/schemas/2.6.5/schema.json",
"vcs": { "enabled": true, "clientKind": "git", "useIgnoreFile": true },
"formatter": { "indentStyle": "space", "indentWidth": 2, "lineWidth": 110 },
"linter": { "enabled": true }
Expand Down
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "pi-cliproxyapi-native",
"version": "0.3.4",
"version": "0.3.5",
"description": "CLIProxyAPI chat discovery, image generation and editing, and video generation with Pi's native adapters",
"publishConfig": {
"access": "public"
Expand Down Expand Up @@ -38,7 +38,7 @@
"check": "pnpm typecheck && pnpm lint && pnpm test"
},
"devDependencies": {
"@biomejs/biome": "^2.6.4",
"@biomejs/biome": "^2.6.5",
"@earendil-works/pi-ai": "^1.5.0",
"@earendil-works/pi-coding-agent": "^1.5.0",
"@earendil-works/pi-tui": "^1.5.0",
Expand Down
92 changes: 46 additions & 46 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

44 changes: 29 additions & 15 deletions src/catalog.ts
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,15 @@ const mediaModels = new Map<
price?: readonly [number, number, number];
}
>([
[
"gpt-image-2.6-flare",
{ name: "GPT Image 2.6 Flare", purpose: "image", route: "openai", price: gptImage2Price },
],
[
"gpt-image-2.6-sunburst",
{ name: "GPT Image 2.6 Sunburst", purpose: "image", route: "openai", price: gptImage2Price },
],
["gpt-image-2.6", { name: "GPT Image 2.6", purpose: "image", route: "openai" }],
[
"gpt-image-2.5-flare",
{ name: "GPT Image 2.5 Flare", purpose: "image", route: "openai", price: gptImage2Price },
Expand Down Expand Up @@ -165,13 +174,12 @@ export function mediaCapability(id: string) {
if (backend && (capability?.route === "xai" || capability?.route === "openai")) {
return { ...capability, route: undefined, disabledReason: `Unsupported media execution on ${backend}.` };
}
// CLIProxyAPI 8.0.48 advertises it for API keys, but OpenAI's Images API rejects the bare 2.5 name.
if (capability && authType === "api-key" && metadataId === "gpt-image-2.5") {
// CLIProxyAPI advertises the plain names for API keys, but OpenAI's Images API has only Sunburst and Flare.
if (capability && authType === "api-key" && /^gpt-image-2\.[56]$/.test(metadataId)) {
return {
...capability,
route: undefined,
disabledReason:
"OpenAI's API has no gpt-image-2.5 model. Use api/gpt-image-2.5-sunburst or api/gpt-image-2.5-flare.",
disabledReason: `OpenAI's API has no ${metadataId} model. Use api/${metadataId}-sunburst or api/${metadataId}-flare.`,
};
}
return capability;
Expand All @@ -185,6 +193,9 @@ export function mediaControls(id: string) {
const capability = mediaCapability(id);
const { metadataId, authType } = modelRoute(id);
const openai = capability?.route === "openai";
// Sunburst and Flare add quality tiers and markup edits; 2.6 adds complexity plus GIF and SVG output.
const tiered = openai && /^gpt-image-2\.[56]-(sunburst|flare)$/.test(metadataId);
const image26 = tiered && metadataId.startsWith("gpt-image-2.6-");
const commonRatios = ["1:1", "16:9", "9:16", "4:3", "3:4", "3:2", "2:3"];
let resolution: string[] = [];
let aspect_ratio: string[] = [];
Expand Down Expand Up @@ -214,24 +225,27 @@ export function mediaControls(id: string) {
: undefined,
resolution,
aspect_ratio,
quality: openai
? [
"auto",
"low",
"medium",
"high",
...(/^gpt-image-2\.5-(sunburst|flare)$/.test(metadataId) ? ["xhigh", "max"] : []),
]
: [],
quality: openai ? ["auto", "low", "medium", "high", ...(tiered ? ["xhigh", "max"] : [])] : [],
complexity: image26 ? ["low", "medium", "high"] : [],
background: openai ? ["auto", "opaque", "transparent"] : [],
output_format: openai ? ["png", "jpeg", "webp"] : [],
output_format: openai ? ["png", "jpeg", "webp", ...(image26 ? ["gif", "svg"] : [])] : [],
// GIF sizes are per frame and skip min_pixels; OpenAI checks the animation against its pixel budget.
gif: image26
? { frame_count: { min: 2, max: 16 }, frame_duration_ms: { min: 20, max: 2000 } }
: undefined,
output_compression: openai ? { min: 0, max: 100, formats: ["jpeg", "webp"] } : undefined,
moderation: openai ? ["auto", "low"] : [],
// Subscription image-tool translation does not forward n.
n: openai ? { min: 1, max: authType === "api-key" ? 10 : 1 } : undefined,
partial_images: openai ? { min: 0, max: 3 } : undefined,
editing: openai
? { max_images: 16, max_file_bytes: 14 * 1024 * 1024, max_total_bytes: 20 * 1024 * 1024, mask: "png" }
? {
max_images: 16,
max_file_bytes: 14 * 1024 * 1024,
max_total_bytes: 20 * 1024 * 1024,
mask: "png",
...(tiered ? { markup: "png" } : {}),
}
: undefined,
input_fidelity: openai && metadataId === "gpt-image-1.5" ? ["low", "high"] : [],
};
Expand Down
2 changes: 1 addition & 1 deletion src/media-defaults.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { type MediaPurpose, mediaCapability, mediaPurpose, modelRoute } from "./
import { type Config, isModelId, isRecord, PROVIDER_ID } from "./config.ts";

export const MEDIA_DEFAULTS_ENTRY = "cliproxyapi-media-defaults";
export const OPENAI_IMAGE_DEFAULT = "gpt-image-2.5-sunburst";
export const OPENAI_IMAGE_DEFAULT = "gpt-image-2.6-sunburst";
Comment thread
coderabbitai[bot] marked this conversation as resolved.
Resolved
// null blocks fallback for invalid selections, including after unrelated picker saves.
export type MediaDefaults = Partial<Record<MediaPurpose, string | null>>;
export type DefaultsContext = {
Expand Down
Loading
Loading