@shop-os/modelkit 0.1.8 → 0.1.9

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.
@@ -171,6 +171,11 @@ interface ModelConstraints {
171
171
  durationPresets?: number[];
172
172
  /** Curated quality choices for rows whose `supports` includes "quality". */
173
173
  qualityOptions?: string[];
174
+ /**
175
+ * Exact pixel size per aspect ratio for rows an app must size verbatim
176
+ * (gpt-image-2 keeps its historic WxH contract); callers pass it as `exactSize`.
177
+ */
178
+ exactSizes?: Record<string, string>;
174
179
  references?: ReferenceLimits;
175
180
  requires?: RequiredInput[];
176
181
  supports?: SupportedOption[];
@@ -212,6 +217,11 @@ interface CatalogDisplay {
212
217
  costTier?: 1 | 2 | 3;
213
218
  /** Chat picker highlight flag. */
214
219
  recommended?: boolean;
220
+ /**
221
+ * Picker position: lower comes first; rows without one keep catalog order
222
+ * after the ordered ones. Set it to surface a new model at the top.
223
+ */
224
+ sortOrder?: number;
215
225
  }
216
226
  /** Capability flags a UI keys off. Absent means false / unknown. */
217
227
  interface CatalogCapabilities {
@@ -223,7 +233,8 @@ interface CatalogCapabilities {
223
233
  acceptsSourceVideo?: boolean;
224
234
  /** Video rows: first/last frames and reference images are mutually exclusive inputs. */
225
235
  framesExcludeReferences?: boolean;
226
- /** Text rows. */
236
+ /** Text rows. `reasoning`: the model streams reasoning the UI should surface. */
237
+ reasoning?: boolean;
227
238
  vision?: boolean;
228
239
  tools?: boolean;
229
240
  structuredOutput?: boolean;
@@ -246,11 +257,21 @@ interface CatalogModel {
246
257
  */
247
258
  exposure: "catalog" | "internal";
248
259
  constraints: ModelConstraints;
249
- defaults: Partial<Omit<ImageRequest, "model" | "prompt"> & Omit<VideoRequest, "model" | "prompt"> & Omit<AudioRequest, "model" | "prompt">>;
260
+ defaults: Partial<Omit<ImageRequest, "model" | "prompt"> & Omit<VideoRequest, "model" | "prompt"> & Omit<AudioRequest, "model" | "prompt"> & {
261
+ temperature?: number;
262
+ }>;
263
+ /** Provider options merged under the caller's; text rows carry their reasoning / thinking tuning here. */
250
264
  providerOptions?: ProviderOptions;
265
+ /**
266
+ * `slug` and `providerLabel` keep an app's historic usage-event names for a
267
+ * row (e.g. cowork emits `image_gen_<slug>` from provider `<providerLabel>`);
268
+ * absent means the app derives them from the id and display.provider.
269
+ */
251
270
  usage: {
252
271
  unit: UsageUnit;
253
272
  modality: UsageModality;
273
+ slug?: string;
274
+ providerLabel?: string;
254
275
  };
255
276
  pricingKind: PricingKind;
256
277
  /** Required on every `active` row so a picker can render it without a hand-written catalog. */
package/dist/catalog.d.ts CHANGED
@@ -171,6 +171,11 @@ interface ModelConstraints {
171
171
  durationPresets?: number[];
172
172
  /** Curated quality choices for rows whose `supports` includes "quality". */
173
173
  qualityOptions?: string[];
174
+ /**
175
+ * Exact pixel size per aspect ratio for rows an app must size verbatim
176
+ * (gpt-image-2 keeps its historic WxH contract); callers pass it as `exactSize`.
177
+ */
178
+ exactSizes?: Record<string, string>;
174
179
  references?: ReferenceLimits;
175
180
  requires?: RequiredInput[];
176
181
  supports?: SupportedOption[];
@@ -212,6 +217,11 @@ interface CatalogDisplay {
212
217
  costTier?: 1 | 2 | 3;
213
218
  /** Chat picker highlight flag. */
214
219
  recommended?: boolean;
220
+ /**
221
+ * Picker position: lower comes first; rows without one keep catalog order
222
+ * after the ordered ones. Set it to surface a new model at the top.
223
+ */
224
+ sortOrder?: number;
215
225
  }
216
226
  /** Capability flags a UI keys off. Absent means false / unknown. */
217
227
  interface CatalogCapabilities {
@@ -223,7 +233,8 @@ interface CatalogCapabilities {
223
233
  acceptsSourceVideo?: boolean;
224
234
  /** Video rows: first/last frames and reference images are mutually exclusive inputs. */
225
235
  framesExcludeReferences?: boolean;
226
- /** Text rows. */
236
+ /** Text rows. `reasoning`: the model streams reasoning the UI should surface. */
237
+ reasoning?: boolean;
227
238
  vision?: boolean;
228
239
  tools?: boolean;
229
240
  structuredOutput?: boolean;
@@ -246,11 +257,21 @@ interface CatalogModel {
246
257
  */
247
258
  exposure: "catalog" | "internal";
248
259
  constraints: ModelConstraints;
249
- defaults: Partial<Omit<ImageRequest, "model" | "prompt"> & Omit<VideoRequest, "model" | "prompt"> & Omit<AudioRequest, "model" | "prompt">>;
260
+ defaults: Partial<Omit<ImageRequest, "model" | "prompt"> & Omit<VideoRequest, "model" | "prompt"> & Omit<AudioRequest, "model" | "prompt"> & {
261
+ temperature?: number;
262
+ }>;
263
+ /** Provider options merged under the caller's; text rows carry their reasoning / thinking tuning here. */
250
264
  providerOptions?: ProviderOptions;
265
+ /**
266
+ * `slug` and `providerLabel` keep an app's historic usage-event names for a
267
+ * row (e.g. cowork emits `image_gen_<slug>` from provider `<providerLabel>`);
268
+ * absent means the app derives them from the id and display.provider.
269
+ */
251
270
  usage: {
252
271
  unit: UsageUnit;
253
272
  modality: UsageModality;
273
+ slug?: string;
274
+ providerLabel?: string;
254
275
  };
255
276
  pricingKind: PricingKind;
256
277
  /** Required on every `active` row so a picker can render it without a hand-written catalog. */
package/dist/catalog.js CHANGED
@@ -127,7 +127,7 @@ function geminiImage(id, label, aliases, sizes, display, exposure) {
127
127
  supports: ["safetySettings", "temperature"]
128
128
  },
129
129
  defaults: { size: "1K", aspectRatio: "1:1" },
130
- usage: { ...IMAGE_USAGE },
130
+ usage: { ...IMAGE_USAGE, slug: "gemini" },
131
131
  pricingKind: "image_size",
132
132
  display,
133
133
  capabilities: { ...IMAGE_GENERATE_EDIT }
@@ -195,6 +195,15 @@ var IMAGE_MODELS = [
195
195
  lifecycle: "active",
196
196
  exposure: "catalog",
197
197
  constraints: {
198
+ exactSizes: {
199
+ "1:1": "1024x1024",
200
+ "3:2": "1536x1024",
201
+ "2:3": "1024x1536",
202
+ "16:9": "2048x1152",
203
+ "9:16": "1152x2048",
204
+ "4:5": "1024x1280",
205
+ "5:4": "1280x1024"
206
+ },
198
207
  aspectRatios: ["1:1", "3:2", "2:3", "16:9", "9:16", "4:5", "5:4", "adaptive"],
199
208
  sizes: ["1K", "2K", "4K"],
200
209
  qualityOptions: ["auto", "low", "medium", "high"],
@@ -202,7 +211,7 @@ var IMAGE_MODELS = [
202
211
  supports: ["quality", "count"]
203
212
  },
204
213
  defaults: { size: "1K", aspectRatio: "adaptive", quality: "auto" },
205
- usage: { ...IMAGE_USAGE },
214
+ usage: { ...IMAGE_USAGE, slug: "gpt" },
206
215
  pricingKind: "image_size",
207
216
  display: {
208
217
  provider: "openai",
@@ -222,6 +231,15 @@ var IMAGE_MODELS = [
222
231
  lifecycle: "active",
223
232
  exposure: "internal",
224
233
  constraints: {
234
+ exactSizes: {
235
+ "1:1": "1024x1024",
236
+ "3:2": "1536x1024",
237
+ "2:3": "1024x1536",
238
+ "16:9": "2048x1152",
239
+ "9:16": "1152x2048",
240
+ "4:5": "1024x1280",
241
+ "5:4": "1280x1024"
242
+ },
225
243
  aspectRatios: ["1:1", "3:2", "2:3", "16:9", "9:16", "4:5", "5:4", "adaptive"],
226
244
  sizes: ["1K", "2K", "4K"],
227
245
  qualityOptions: ["auto", "low", "medium", "high"],
@@ -248,6 +266,15 @@ var IMAGE_MODELS = [
248
266
  lifecycle: "active",
249
267
  exposure: "internal",
250
268
  constraints: {
269
+ exactSizes: {
270
+ "1:1": "1024x1024",
271
+ "3:2": "1536x1024",
272
+ "2:3": "1024x1536",
273
+ "16:9": "2048x1152",
274
+ "9:16": "1152x2048",
275
+ "4:5": "1024x1280",
276
+ "5:4": "1280x1024"
277
+ },
251
278
  aspectRatios: ["1:1", "3:2", "2:3", "16:9", "9:16", "4:5", "5:4", "adaptive"],
252
279
  sizes: ["1K", "2K", "4K"],
253
280
  qualityOptions: ["auto", "low", "medium", "high"],
@@ -293,7 +320,7 @@ var IMAGE_MODELS = [
293
320
  supports: ["count", "outputFormat"]
294
321
  },
295
322
  defaults: { size: "1K", aspectRatio: "1:1", outputFormat: "png", count: 1 },
296
- usage: { ...IMAGE_USAGE },
323
+ usage: { ...IMAGE_USAGE, slug: "muse" },
297
324
  pricingKind: "image_size",
298
325
  display: {
299
326
  provider: "meta",
@@ -710,6 +737,14 @@ function text(id, label, providerModelId, extra) {
710
737
  ...extra
711
738
  };
712
739
  }
740
+ var ANTHROPIC_THINKING = {
741
+ anthropic: { thinking: { type: "enabled", budgetTokens: 4e3 }, sendReasoning: true }
742
+ };
743
+ var ANTHROPIC_ADAPTIVE = {
744
+ anthropic: { thinking: { type: "adaptive", display: "summarized" }, sendReasoning: true }
745
+ };
746
+ var OPENAI_REASONING = { openai: { reasoningEffort: "medium", reasoningSummary: "auto" } };
747
+ var DEEPSEEK_THINKING = { deepseek: { thinking: { type: "enabled" } } };
713
748
  var TEXT_MODELS = [
714
749
  text("gpt-4o", "GPT-4o", "gpt-4o", {
715
750
  exposure: "internal",
@@ -788,6 +823,7 @@ var TEXT_MODELS = [
788
823
  }
789
824
  }),
790
825
  text("gpt-5.6-luna", "GPT-5.6 Luna", "gpt-5.6-luna", {
826
+ providerOptions: OPENAI_REASONING,
791
827
  exposure: "catalog",
792
828
  display: {
793
829
  provider: "openai",
@@ -795,6 +831,7 @@ var TEXT_MODELS = [
795
831
  description: "OpenAI GPT-5.6 Luna cost-optimized tier of the GPT-5.6 reasoning family; text and image input, 1.05M-token context."
796
832
  },
797
833
  capabilities: {
834
+ reasoning: true,
798
835
  vision: true,
799
836
  tools: true,
800
837
  structuredOutput: true,
@@ -802,6 +839,7 @@ var TEXT_MODELS = [
802
839
  }
803
840
  }),
804
841
  text("gpt-5.6-terra", "GPT-5.6 Terra", "gpt-5.6-terra", {
842
+ providerOptions: OPENAI_REASONING,
805
843
  exposure: "catalog",
806
844
  display: {
807
845
  provider: "openai",
@@ -809,6 +847,7 @@ var TEXT_MODELS = [
809
847
  description: "OpenAI GPT-5.6 Terra balanced tier of the GPT-5.6 reasoning family; text and image input, 1.05M-token context."
810
848
  },
811
849
  capabilities: {
850
+ reasoning: true,
812
851
  vision: true,
813
852
  tools: true,
814
853
  structuredOutput: true,
@@ -816,6 +855,7 @@ var TEXT_MODELS = [
816
855
  }
817
856
  }),
818
857
  text("gpt-5.6-sol", "GPT-5.6 Sol", "gpt-5.6-sol", {
858
+ providerOptions: OPENAI_REASONING,
819
859
  exposure: "catalog",
820
860
  display: {
821
861
  provider: "openai",
@@ -823,6 +863,7 @@ var TEXT_MODELS = [
823
863
  description: "OpenAI GPT-5.6 Sol flagship tier of the GPT-5.6 reasoning family; text and image input, 1.05M-token context."
824
864
  },
825
865
  capabilities: {
866
+ reasoning: true,
826
867
  vision: true,
827
868
  tools: true,
828
869
  structuredOutput: true,
@@ -842,6 +883,7 @@ var TEXT_MODELS = [
842
883
  }),
843
884
  // Anthropic retired the dated 4.0 ids; callers that still send them get 4.6.
844
885
  text("claude-sonnet-4-6", "Claude Sonnet 4.6", "claude-sonnet-4-6", {
886
+ providerOptions: ANTHROPIC_THINKING,
845
887
  exposure: "catalog",
846
888
  aliases: [
847
889
  "claude-sonnet-4.6",
@@ -855,6 +897,7 @@ var TEXT_MODELS = [
855
897
  description: "Anthropic Claude Sonnet 4.6 (legacy) balanced model; text and image input, 1M-token context."
856
898
  },
857
899
  capabilities: {
900
+ reasoning: true,
858
901
  vision: true,
859
902
  tools: true,
860
903
  structuredOutput: true,
@@ -862,6 +905,7 @@ var TEXT_MODELS = [
862
905
  }
863
906
  }),
864
907
  text("claude-sonnet-5", "Claude Sonnet 5", "claude-sonnet-5", {
908
+ providerOptions: ANTHROPIC_ADAPTIVE,
865
909
  exposure: "catalog",
866
910
  display: {
867
911
  provider: "anthropic",
@@ -869,6 +913,7 @@ var TEXT_MODELS = [
869
913
  description: "Anthropic Claude Sonnet 5 current balanced model; text and image input, 1M-token context."
870
914
  },
871
915
  capabilities: {
916
+ reasoning: true,
872
917
  vision: true,
873
918
  tools: true,
874
919
  structuredOutput: true,
@@ -876,6 +921,7 @@ var TEXT_MODELS = [
876
921
  }
877
922
  }),
878
923
  text("claude-opus-4-8", "Claude Opus 4.8", "claude-opus-4-8", {
924
+ providerOptions: ANTHROPIC_ADAPTIVE,
879
925
  exposure: "catalog",
880
926
  aliases: ["claude-opus-4.8", "claude-opus-4", "claude-opus-4.0", "claude-opus-4-20250514"],
881
927
  display: {
@@ -884,6 +930,7 @@ var TEXT_MODELS = [
884
930
  description: "Anthropic Claude Opus 4.8 (legacy) frontier model; text and image input, 1M-token context."
885
931
  },
886
932
  capabilities: {
933
+ reasoning: true,
887
934
  vision: true,
888
935
  tools: true,
889
936
  structuredOutput: true,
@@ -891,6 +938,7 @@ var TEXT_MODELS = [
891
938
  }
892
939
  }),
893
940
  text("claude-haiku-4-5", "Claude Haiku 4.5", "claude-haiku-4-5", {
941
+ providerOptions: ANTHROPIC_THINKING,
894
942
  exposure: "catalog",
895
943
  aliases: ["claude-haiku-4.5", "claude-haiku-4-5-20251001", "claude-haiku-4"],
896
944
  display: {
@@ -898,7 +946,13 @@ var TEXT_MODELS = [
898
946
  costTier: 1,
899
947
  description: "Anthropic Claude Haiku 4.5 fast model with near-frontier intelligence; text and image input, 200K-token context."
900
948
  },
901
- capabilities: { vision: true, tools: true, structuredOutput: true, contextWindow: 2e5 }
949
+ capabilities: {
950
+ reasoning: true,
951
+ vision: true,
952
+ tools: true,
953
+ structuredOutput: true,
954
+ contextWindow: 2e5
955
+ }
902
956
  }),
903
957
  text("claude-opus-5", "Claude Opus 5", "claude-opus-5", {
904
958
  exposure: "internal",
@@ -1090,15 +1144,21 @@ var TEXT_MODELS = [
1090
1144
  contextWindow: 128e3
1091
1145
  }
1092
1146
  }),
1093
- text("deepseek-v4-flash", "DeepSeek V4 Flash", "deepseek-v4-flash", {
1147
+ // DeepSeek retired V4 Flash upstream and routes the old id to V4.1 Flash at
1148
+ // Flash rates (https://api-docs.deepseek.com/news/news260910/); the old id
1149
+ // stays an alias so stored selections keep resolving.
1150
+ text("deepseek-flash", "DeepSeek V4.1 Flash", "deepseek-flash", {
1151
+ providerOptions: DEEPSEEK_THINKING,
1152
+ aliases: ["deepseek-v4-flash"],
1094
1153
  exposure: "catalog",
1095
1154
  display: {
1096
1155
  provider: "deepseek",
1097
1156
  costTier: 1,
1098
1157
  recommended: true,
1099
- description: "DeepSeek V4 Flash thinking/non-thinking model with vision, tool calls, and JSON output; 1M-token context and up to 384K output tokens."
1158
+ description: "DeepSeek V4.1 Flash thinking/non-thinking model with vision, tool calls, and JSON output; 1M-token context and up to 384K output tokens."
1100
1159
  },
1101
1160
  capabilities: {
1161
+ reasoning: true,
1102
1162
  vision: true,
1103
1163
  tools: true,
1104
1164
  structuredOutput: true,
@@ -1106,6 +1166,7 @@ var TEXT_MODELS = [
1106
1166
  }
1107
1167
  }),
1108
1168
  text("deepseek-v4-pro", "DeepSeek V4 Pro", "deepseek-v4-pro", {
1169
+ providerOptions: DEEPSEEK_THINKING,
1109
1170
  exposure: "catalog",
1110
1171
  display: {
1111
1172
  provider: "deepseek",
@@ -1113,6 +1174,7 @@ var TEXT_MODELS = [
1113
1174
  description: "DeepSeek V4 Pro thinking/non-thinking text model with tool calls and JSON output (no vision); 1M-token context and up to 384K output tokens."
1114
1175
  },
1115
1176
  capabilities: {
1177
+ reasoning: true,
1116
1178
  vision: false,
1117
1179
  tools: true,
1118
1180
  structuredOutput: true,
@@ -1136,6 +1198,7 @@ var TEXT_MODELS = [
1136
1198
  }),
1137
1199
  // Moonshot retired kimi-k2.5 on 2026-08-31 and no longer publishes its specs.
1138
1200
  text("kimi-k2.5", "Kimi K2.5", "kimi-k2.5", {
1201
+ defaults: { temperature: 1 },
1139
1202
  exposure: "catalog",
1140
1203
  display: {
1141
1204
  provider: "moonshot",
@@ -1145,6 +1208,7 @@ var TEXT_MODELS = [
1145
1208
  capabilities: {}
1146
1209
  }),
1147
1210
  text("kimi-k3", "Kimi K3", "kimi-k3", {
1211
+ defaults: { temperature: 1 },
1148
1212
  exposure: "catalog",
1149
1213
  display: {
1150
1214
  provider: "moonshot",
@@ -1152,6 +1216,7 @@ var TEXT_MODELS = [
1152
1216
  description: "Moonshot Kimi K3 flagship model with native visual understanding and always-on thinking; text, image, and video input, 1M-token context."
1153
1217
  },
1154
1218
  capabilities: {
1219
+ reasoning: true,
1155
1220
  vision: true,
1156
1221
  tools: true,
1157
1222
  structuredOutput: true,
@@ -1206,7 +1271,7 @@ var VIDEO_MODELS = [
1206
1271
  supports: ["lastFrame"]
1207
1272
  },
1208
1273
  defaults: { durationSeconds: 8, resolution: "720p", aspectRatio: "16:9" },
1209
- usage: { ...VIDEO_USAGE },
1274
+ usage: { ...VIDEO_USAGE, slug: "veo" },
1210
1275
  pricingKind: "video_per_second",
1211
1276
  display: {
1212
1277
  provider: "google",
@@ -1298,7 +1363,7 @@ var VIDEO_MODELS = [
1298
1363
  supports: []
1299
1364
  },
1300
1365
  defaults: {},
1301
- usage: { ...VIDEO_USAGE },
1366
+ usage: { ...VIDEO_USAGE, slug: "gemini_omni" },
1302
1367
  pricingKind: "video_per_second",
1303
1368
  display: {
1304
1369
  provider: "google",
@@ -1357,7 +1422,7 @@ var VIDEO_MODELS = [
1357
1422
  aspectRatio: "16:9",
1358
1423
  generateAudio: true
1359
1424
  },
1360
- usage: { ...VIDEO_USAGE },
1425
+ usage: { ...VIDEO_USAGE, slug: "seedance2", providerLabel: "byteplus" },
1361
1426
  pricingKind: "video_per_second",
1362
1427
  display: {
1363
1428
  provider: "bytedance",
@@ -1479,7 +1544,7 @@ var VIDEO_MODELS = [
1479
1544
  cfgScale: 0.5,
1480
1545
  negativePrompt: NEGATIVE_PROMPT
1481
1546
  },
1482
- usage: { ...VIDEO_USAGE },
1547
+ usage: { ...VIDEO_USAGE, slug: "grok" },
1483
1548
  pricingKind: "video_per_second",
1484
1549
  display: {
1485
1550
  provider: "kuaishou",
@@ -1930,6 +1995,40 @@ function resolveVideoOptions(model, request, onUnsupported = "error") {
1930
1995
  model: model.id
1931
1996
  });
1932
1997
  }
1998
+ if (merged.sourceVideo !== void 0 && !model.capabilities?.acceptsSourceVideo) {
1999
+ if (onUnsupported === "error") {
2000
+ throw new ModelKitError({
2001
+ code: "unsupported_option",
2002
+ message: `${model.id} does not take a source video`,
2003
+ model: model.id
2004
+ });
2005
+ }
2006
+ warnings.push({
2007
+ code: "option_ignored",
2008
+ field: "sourceVideo",
2009
+ message: `${model.id} does not take a source video; dropped`
2010
+ });
2011
+ delete merged.sourceVideo;
2012
+ }
2013
+ const hasFrames = merged.firstFrame !== void 0 || merged.lastFrame !== void 0;
2014
+ const hasRefs = compact(merged.referenceImages).length + compact(merged.referenceVideos).length + compact(merged.referenceAudios).length > 0;
2015
+ if (hasFrames && hasRefs && model.capabilities?.framesExcludeReferences) {
2016
+ if (onUnsupported === "error") {
2017
+ throw new ModelKitError({
2018
+ code: "unsupported_option",
2019
+ message: `${model.id} takes frames or references, not both`,
2020
+ model: model.id
2021
+ });
2022
+ }
2023
+ warnings.push({
2024
+ code: "option_ignored",
2025
+ field: "referenceImages",
2026
+ message: `${model.id} takes frames or references, not both; references dropped`
2027
+ });
2028
+ delete merged.referenceImages;
2029
+ delete merged.referenceVideos;
2030
+ delete merged.referenceAudios;
2031
+ }
1933
2032
  for (const input of c.ratioIgnoredWith ?? []) {
1934
2033
  if (merged[input] !== void 0 && merged.aspectRatio !== void 0) {
1935
2034
  if (request.aspectRatio !== void 0) {