mirror of
https://github.com/badlogic/pi-mono.git
synced 2026-11-05 23:37:25 +00:00
feat(ai,coding-agent): image input for System One classifiers
Jev (TypeSafe, Workers AI), Clef (Workers AI), and OpenRouter decision models now accept ClassifierContext.images. Each service takes its own wire form: TypeSafe assets with the opt-in header, Clef images data URLs, or OpenRouter image_url parts in the state. A new SystemOneCompat (imageInput, sendImageOptInHeader) selects the form; catalog entries set it explicitly and models.json provider compat now applies to classifiers. Adds Clef Omni and Jev 1.14 on Workers AI and fixes Clef Flash and Workers AI Jev catalog pricing.
This commit is contained in:
parent
02726086d1
commit
7f225f25d8
19 changed files with 687 additions and 36 deletions
|
|
@ -2631,11 +2631,15 @@ async function loadModelsDevClassifierModels(): Promise<ClassifierModel<"typesaf
|
|||
api: "typesafe-system-one",
|
||||
provider: "typesafe",
|
||||
baseUrl: "https://api.typesafe.ai/v1/",
|
||||
input: metadata.modalities?.input?.includes("image") ? ["text", "image"] : ["text"],
|
||||
// models.dev lists text input only, but the API accepts image assets as an experimental
|
||||
// feature behind an opt-in header, which the typesafe-system-one API sends.
|
||||
// https://github.com/typesafe-ai/typesafe-sdk-js (v0.7.0 changelog)
|
||||
input: ["text", "image"],
|
||||
// The canonical models.dev entry has no direct-provider pricing. System One reports token usage,
|
||||
// so classify() results carry token counts but price them at zero.
|
||||
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
|
||||
contextWindow: metadata.limit?.context || 64000,
|
||||
compat: { imageInput: "assets", sendImageOptInHeader: true },
|
||||
},
|
||||
];
|
||||
} catch (error) {
|
||||
|
|
@ -2645,9 +2649,6 @@ async function loadModelsDevClassifierModels(): Promise<ClassifierModel<"typesaf
|
|||
}
|
||||
}
|
||||
|
||||
// Workers AI has no unauthenticated catalog and models.dev does not list its
|
||||
// System One models yet. Cloudflare publishes pricing only in the dashboard.
|
||||
// https://developers.cloudflare.com/ai/models/typesafe/jev/
|
||||
// OpenCode Zen serves Jev through its TypeSafe-compatible System One endpoint.
|
||||
// Neither its /inference/v1/models listing nor models.dev carries metadata for it.
|
||||
// https://opencode.ai/docs/zen
|
||||
|
|
@ -2676,11 +2677,14 @@ const OPENCODE_CLASSIFIER_MODELS: ClassifierModel<"typesafe-system-one">[] = [
|
|||
},
|
||||
];
|
||||
|
||||
// Workers AI has no unauthenticated catalog, so its System One models are listed here from
|
||||
// Cloudflare's model pages.
|
||||
const CLOUDFLARE_WORKERS_AI_CLASSIFIER_MODELS: ClassifierModel<"cloudflare-workers-ai-system-one">[] = [
|
||||
// Cloudflare-hosted Clef decision models. They accept images, but classifier
|
||||
// contexts carry text or JSON state only, so the catalog advertises text.
|
||||
// Pricing: https://developers.cloudflare.com/workers-ai/models/clef/
|
||||
// and https://developers.cloudflare.com/workers-ai/models/clef-flash/
|
||||
// Cloudflare-hosted Clef decision models. They take up to four PNG, JPEG, or WebP images as data URLs.
|
||||
// Clef Omni also takes audio and video, which classifier contexts do not carry.
|
||||
// Pricing and context: https://developers.cloudflare.com/workers-ai/models/clef/,
|
||||
// https://developers.cloudflare.com/workers-ai/models/clef-flash/,
|
||||
// and https://developers.cloudflare.com/workers-ai/models/clef-omni/
|
||||
{
|
||||
type: "classifier",
|
||||
id: "@cf/cloudflare/clef",
|
||||
|
|
@ -2688,9 +2692,10 @@ const CLOUDFLARE_WORKERS_AI_CLASSIFIER_MODELS: ClassifierModel<"cloudflare-worke
|
|||
api: "cloudflare-workers-ai-system-one",
|
||||
provider: "cloudflare-workers-ai",
|
||||
baseUrl: CLOUDFLARE_WORKERS_AI_REST_BASE_URL,
|
||||
input: ["text"],
|
||||
input: ["text", "image"],
|
||||
cost: { input: 0.24, output: 0, cacheRead: 0, cacheWrite: 0 },
|
||||
contextWindow: 65536,
|
||||
compat: { imageInput: "images" },
|
||||
},
|
||||
{
|
||||
type: "classifier",
|
||||
|
|
@ -2699,10 +2704,26 @@ const CLOUDFLARE_WORKERS_AI_CLASSIFIER_MODELS: ClassifierModel<"cloudflare-worke
|
|||
api: "cloudflare-workers-ai-system-one",
|
||||
provider: "cloudflare-workers-ai",
|
||||
baseUrl: CLOUDFLARE_WORKERS_AI_REST_BASE_URL,
|
||||
input: ["text"],
|
||||
cost: { input: 0.09, output: 0, cacheRead: 0, cacheWrite: 0 },
|
||||
contextWindow: 65536,
|
||||
input: ["text", "image"],
|
||||
cost: { input: 0.038, output: 0, cacheRead: 0, cacheWrite: 0 },
|
||||
contextWindow: 24576,
|
||||
compat: { imageInput: "images" },
|
||||
},
|
||||
{
|
||||
type: "classifier",
|
||||
id: "@cf/cloudflare/clef-omni",
|
||||
name: "Clef Omni",
|
||||
api: "cloudflare-workers-ai-system-one",
|
||||
provider: "cloudflare-workers-ai",
|
||||
baseUrl: CLOUDFLARE_WORKERS_AI_REST_BASE_URL,
|
||||
input: ["text", "image"],
|
||||
cost: { input: 0.15, output: 0, cacheRead: 0, cacheWrite: 0 },
|
||||
contextWindow: 64000,
|
||||
compat: { imageInput: "images" },
|
||||
},
|
||||
// TypeSafe's Jev models take PNG and JPEG images as System One assets.
|
||||
// https://developers.cloudflare.com/ai/models/typesafe/jev/ (jev-latest)
|
||||
// and https://developers.cloudflare.com/ai/models/typesafe/jev-1.14.0/
|
||||
{
|
||||
type: "classifier",
|
||||
id: "typesafe/jev",
|
||||
|
|
@ -2710,9 +2731,22 @@ const CLOUDFLARE_WORKERS_AI_CLASSIFIER_MODELS: ClassifierModel<"cloudflare-worke
|
|||
api: "cloudflare-workers-ai-system-one",
|
||||
provider: "cloudflare-workers-ai",
|
||||
baseUrl: CLOUDFLARE_WORKERS_AI_REST_BASE_URL,
|
||||
input: ["text"],
|
||||
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
|
||||
input: ["text", "image"],
|
||||
cost: { input: 0.042, output: 0, cacheRead: 0, cacheWrite: 0 },
|
||||
contextWindow: 32000,
|
||||
compat: { imageInput: "assets" },
|
||||
},
|
||||
{
|
||||
type: "classifier",
|
||||
id: "typesafe/jev-1.14.0",
|
||||
name: "Jev 1.14",
|
||||
api: "cloudflare-workers-ai-system-one",
|
||||
provider: "cloudflare-workers-ai",
|
||||
baseUrl: CLOUDFLARE_WORKERS_AI_REST_BASE_URL,
|
||||
input: ["text", "image"],
|
||||
cost: { input: 0.042, output: 0, cacheRead: 0, cacheWrite: 0 },
|
||||
contextWindow: 32000,
|
||||
compat: { imageInput: "assets" },
|
||||
},
|
||||
];
|
||||
|
||||
|
|
|
|||
|
|
@ -98,6 +98,8 @@ export function buildOpenRouterCatalog(
|
|||
input: input.length > 0 ? input : ["text"],
|
||||
cost: openRouterCost(model.pricing),
|
||||
contextWindow: model.top_provider?.context_length || model.context_length || 4096,
|
||||
// OpenRouter answers TypeSafe `assets` with 200 but drops the images.
|
||||
compat: { imageInput: "state-image-urls", sendImageOptInHeader: false },
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue