@shop-os/modelkit 0.2.23 → 0.2.25

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/dist/index.cjs CHANGED
@@ -81,6 +81,7 @@ __export(index_exports, {
81
81
  liveCatalog: () => liveCatalog,
82
82
  liveState: () => liveState,
83
83
  mergeTextProviderOptions: () => mergeTextProviderOptions,
84
+ missingTierKeys: () => missingTierKeys,
84
85
  nearestAspectRatio: () => nearestAspectRatio,
85
86
  normalizeExposure: () => normalizeExposure,
86
87
  openaiImageAdapter: () => openaiImageAdapter,
@@ -506,6 +507,32 @@ var IMAGE_MODELS = [
506
507
  logo: "https://d31vvfpk2ppdyq.cloudfront.net/assets/characters/1787909065794-k9a7zz.png"
507
508
  }
508
509
  },
510
+ {
511
+ // References switch to the edit endpoint: the first is the image to edit,
512
+ // the rest (up to 4) guide it.
513
+ id: "ideogram-4.5",
514
+ aliases: [],
515
+ label: "Ideogram 4.5",
516
+ type: "image",
517
+ adapter: "fal",
518
+ providerModelId: "ideogram/v4.5",
519
+ lifecycle: "active",
520
+ exposure: ["cowork", "space_builder"],
521
+ constraints: {
522
+ aspectRatios: ["1:1", "16:9", "9:16", "4:3", "3:4", "3:2", "2:3", "5:4", "4:5"],
523
+ sizes: ["1K", "2K"],
524
+ qualityOptions: ["auto", "low", "medium", "high"],
525
+ references: { images: 5 },
526
+ supports: ["quality", "count", "seed"]
527
+ },
528
+ defaults: { size: "2K", aspectRatio: "1:1", quality: "medium", count: 1 },
529
+ usage: { ...IMAGE_USAGE, slug: "ideogram" },
530
+ pricingKind: "image_size",
531
+ display: {
532
+ provider: "ideogram",
533
+ description: "Ideogram's precise edit model: repeated edits keep the untouched pixels and colours intact, at the source's native resolution. Also generates from text."
534
+ }
535
+ },
509
536
  {
510
537
  id: "seedream-5-0-pro",
511
538
  aliases: ["seedream-4-5"],
@@ -3695,6 +3722,7 @@ function createFalAdapter(deps = defaultDeps) {
3695
3722
  id: "fal",
3696
3723
  generateImage: (req, ctx) => {
3697
3724
  throwIfAborted(ctx.signal);
3725
+ if (isIdeogram(ctx.model.providerModelId)) return generateIdeogramImage(req, ctx, deps);
3698
3726
  return generateMuseImage(req, ctx, deps);
3699
3727
  },
3700
3728
  generateVideo: (req, ctx) => {
@@ -3951,6 +3979,72 @@ async function generateMuseImage(req, ctx, deps) {
3951
3979
  raw: payload
3952
3980
  };
3953
3981
  }
3982
+ var IDEOGRAM_MODEL_IDS = /* @__PURE__ */ new Set(["ideogram/v4.5"]);
3983
+ function isIdeogram(providerModelId) {
3984
+ return IDEOGRAM_MODEL_IDS.has(providerModelId.toLowerCase());
3985
+ }
3986
+ var IDEOGRAM_SIZES = {
3987
+ "1:1": { "1K": "1024x1024", "2K": "2048x2048" },
3988
+ "16:9": { "1K": "1280x720", "2K": "2560x1440" },
3989
+ "9:16": { "1K": "720x1280", "2K": "1440x2560" },
3990
+ "4:3": { "1K": "1152x864", "2K": "2304x1728" },
3991
+ "3:4": { "1K": "864x1152", "2K": "1728x2304" },
3992
+ "3:2": { "1K": "1248x832", "2K": "2496x1664" },
3993
+ "2:3": { "1K": "832x1248", "2K": "1664x2496" },
3994
+ "5:4": { "1K": "1120x896", "2K": "2240x1792" },
3995
+ "4:5": { "1K": "896x1120", "2K": "1792x2240" }
3996
+ };
3997
+ function parseExactSize(value) {
3998
+ const match = /^(\d+)x(\d+)$/.exec(value ?? "");
3999
+ return match ? { width: Number(match[1]), height: Number(match[2]) } : void 0;
4000
+ }
4001
+ function ideogramImageSize(req) {
4002
+ const exact = parseExactSize(req.exactSize);
4003
+ if (exact) return exact;
4004
+ if (req.aspectRatio === void 0 || req.aspectRatio === "adaptive") return void 0;
4005
+ return parseExactSize(IDEOGRAM_SIZES[req.aspectRatio]?.[req.size === "1K" ? "1K" : "2K"]);
4006
+ }
4007
+ async function generateIdeogramImage(req, ctx, deps) {
4008
+ const [source, ...references] = (req.references ?? []).map(refToUrl);
4009
+ const input = { prompt: req.prompt, num_images: req.count ?? 1 };
4010
+ if (req.quality !== void 0 && req.quality !== "auto") input.quality = req.quality;
4011
+ if (req.seed !== void 0) input.seed = req.seed;
4012
+ const id = ctx.model.providerModelId;
4013
+ let endpoint = id;
4014
+ if (source === void 0) {
4015
+ input.enable_prompt_expansion = false;
4016
+ const size = ideogramImageSize(req);
4017
+ if (size) input.image_size = size;
4018
+ } else {
4019
+ endpoint = `${id}/edit`;
4020
+ input.image_url = source;
4021
+ input.edit_precision = "high";
4022
+ if (references.length > 0) input.reference_image_urls = references;
4023
+ }
4024
+ const payload = await runJob(ctx, deps, endpoint, input);
4025
+ const parsed = museImageResultSchema.safeParse(payload);
4026
+ const images = parsed.success ? parsed.data.images ?? [] : [];
4027
+ const files = await Promise.all(
4028
+ images.flatMap((img) => {
4029
+ if (img.url === void 0) return [];
4030
+ return [decodeImage(ctx, img.url, img.content_type ?? void 0)];
4031
+ })
4032
+ );
4033
+ if (files.length === 0) {
4034
+ throw new ModelKitError({
4035
+ code: "provider_rejected",
4036
+ message: "fal Ideogram returned no image",
4037
+ provider: "fal",
4038
+ model: ctx.model.id,
4039
+ retryable: false
4040
+ });
4041
+ }
4042
+ return {
4043
+ images: files.map((f) => ({ bytes: f.bytes, mime: f.mime })),
4044
+ usage: imageUsage(ctx, req, files.length),
4045
+ raw: payload
4046
+ };
4047
+ }
3954
4048
  var H3_MAX_MODEL_IDS = /* @__PURE__ */ new Set([
3955
4049
  "minimax/h3-max",
3956
4050
  "minimax/h3-max/reference-to-video"
@@ -8002,10 +8096,22 @@ function hasAll(keys, names) {
8002
8096
  function hasKey(keys, name) {
8003
8097
  return hasAll(keys, [name]);
8004
8098
  }
8099
+ function missingTierKeys(config, tier, names) {
8100
+ return names.filter((name) => !hasAll(config.keys[tier], [name]));
8101
+ }
8005
8102
  function missingEnterpriseKeys(config, names) {
8006
- return names.filter((name) => !hasAll(config.keys.enterprise, [name]));
8103
+ return missingTierKeys(config, "enterprise", names);
8007
8104
  }
8008
8105
  function resolveKeys(config, names, tier = "pro") {
8106
+ if (tier === "sloosh") {
8107
+ if (names.length === 0) return config.keys.sloosh ?? {};
8108
+ if (hasAll(config.keys.sloosh, names)) return config.keys.sloosh;
8109
+ throw new ModelKitError({
8110
+ code: "auth",
8111
+ message: `Missing Sloosh API key for ${names.join(", ")}`,
8112
+ retryable: false
8113
+ });
8114
+ }
8009
8115
  if (tier === "enterprise" && hasAll(config.keys.enterprise, names))
8010
8116
  return config.keys.enterprise;
8011
8117
  if (names.length > 0 && !hasAll(config.keys.pro, names)) {
@@ -8194,6 +8300,7 @@ function resolveAnthropicTransport(model, config, tier, warn) {
8194
8300
  const preferred = preferredAnthropicTransport(model, config.routing ?? {});
8195
8301
  const usable = (transport) => {
8196
8302
  const name = transport === "bedrock" ? "aws" : "anthropic";
8303
+ if (tier === "sloosh") return hasKey(config.keys.sloosh, name);
8197
8304
  return hasKey(config.keys.pro, name) || tier === "enterprise" && hasKey(config.keys.enterprise, name);
8198
8305
  };
8199
8306
  if (usable(preferred)) return preferred;
@@ -8775,11 +8882,19 @@ function createModelKit(config, adapters) {
8775
8882
  }
8776
8883
 
8777
8884
  // src/default.ts
8885
+ function withSharedAws(keys) {
8886
+ const { pro, sloosh } = keys;
8887
+ if (!sloosh || sloosh.aws || !pro.aws) return keys;
8888
+ return { ...keys, sloosh: { ...sloosh, aws: pro.aws } };
8889
+ }
8778
8890
  function createDefaultModelKit(config = {}) {
8779
- const keys = config.keys ?? {
8780
- pro: keysFromEnv(process.env),
8781
- enterprise: keysFromEnv(process.env, "ENTERPRISE_")
8782
- };
8891
+ const keys = withSharedAws(
8892
+ config.keys ?? {
8893
+ pro: keysFromEnv(process.env),
8894
+ enterprise: keysFromEnv(process.env, "ENTERPRISE_"),
8895
+ sloosh: keysFromEnv(process.env, "SLOOSH_")
8896
+ }
8897
+ );
8783
8898
  return createModelKit({ ...config, keys }, DEFAULT_ADAPTERS);
8784
8899
  }
8785
8900
  var generateText2 = (options, call) => createDefaultModelKit().generateText(options, call);
@@ -8844,6 +8959,7 @@ var describe = (modelId) => createDefaultModelKit().describe(modelId);
8844
8959
  liveCatalog,
8845
8960
  liveState,
8846
8961
  mergeTextProviderOptions,
8962
+ missingTierKeys,
8847
8963
  nearestAspectRatio,
8848
8964
  normalizeExposure,
8849
8965
  openaiImageAdapter,