@oh-my-pi/pi-catalog 16.3.14 → 16.4.0

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.
@@ -29,6 +29,7 @@ import {
29
29
  mistralModelManagerOptions,
30
30
  moonshotModelManagerOptions,
31
31
  nanoGptModelManagerOptions,
32
+ novitaModelManagerOptions,
32
33
  nvidiaModelManagerOptions,
33
34
  ollamaModelManagerOptions,
34
35
  openaiModelManagerOptions,
@@ -271,6 +272,14 @@ export const CATALOG_PROVIDERS = [
271
272
  createModelManagerOptions: (config: ModelManagerConfig) => nvidiaModelManagerOptions(config),
272
273
  catalogDiscovery: { label: "NVIDIA" },
273
274
  },
275
+ {
276
+ id: "novita",
277
+ defaultModel: "moonshotai/kimi-k2.7-code",
278
+ envVars: ["NOVITA_API_KEY"],
279
+ createModelManagerOptions: (config: ModelManagerConfig) => novitaModelManagerOptions(config),
280
+ dynamicModelsAuthoritative: true,
281
+ catalogDiscovery: { label: "Novita", allowUnauthenticated: true },
282
+ },
274
283
  {
275
284
  id: "ollama",
276
285
  defaultModel: "gpt-oss:20b",
@@ -25,8 +25,7 @@ type OllamaShowResponse = {
25
25
  const OLLAMA_RETRY_DELAYS_MS = [2_000, 5_000, 10_000];
26
26
  const OLLAMA_CLOUD_GLM_52_THINKING: ThinkingConfig = {
27
27
  mode: "effort",
28
- efforts: [Effort.High, Effort.XHigh],
29
- effortMap: { [Effort.XHigh]: "max" },
28
+ efforts: [Effort.High, Effort.Max],
30
29
  };
31
30
 
32
31
  function trimTrailingSlash(value: string): string {
@@ -622,9 +622,8 @@ const UMANS_REASONING_EFFORT_BY_LEVEL: Record<string, Effort> = {
622
622
  medium: Effort.Medium,
623
623
  high: Effort.High,
624
624
  xhigh: Effort.XHigh,
625
- max: Effort.XHigh,
625
+ max: Effort.Max,
626
626
  };
627
- const UMANS_MAX_REASONING_EFFORT_MAP = { [Effort.XHigh]: "max" } as const;
628
627
  const UMANS_DEFAULT_REASONING_EFFORTS = [Effort.Minimal, Effort.Low, Effort.Medium, Effort.High, Effort.XHigh] as const;
629
628
  const UMANS_VIA_HANDOFF_MODEL_IDS = ["umans-glm-5.1", "umans-glm-5.2"] as const;
630
629
 
@@ -689,9 +688,6 @@ function mapUmansThinkingConfig(value: unknown): ThinkingConfig | undefined {
689
688
  mode: umansHasMaxReasoningLevel(value) ? "anthropic-budget-effort" : "budget",
690
689
  efforts,
691
690
  };
692
- if (thinking.mode === "anthropic-budget-effort") {
693
- thinking.effortMap = UMANS_MAX_REASONING_EFFORT_MAP;
694
- }
695
691
  if (isRecord(value)) {
696
692
  if (value.can_disable === false) {
697
693
  thinking.requiresEffort = true;
@@ -821,6 +817,62 @@ export function openaiModelManagerOptions(config?: OpenAIModelManagerConfig): Mo
821
817
  };
822
818
  }
823
819
 
820
+ /** First-party gpt-5.6 SKUs that accept `reasoning: { mode: "pro" }` on the Responses APIs. */
821
+ const OPENAI_PRO_REASONING_BASE_IDS: Record<string, true> = {
822
+ "gpt-5.6-luna": true,
823
+ "gpt-5.6-sol": true,
824
+ "gpt-5.6-terra": true,
825
+ };
826
+ const OPENAI_PRO_REASONING_PROVIDERS: Record<string, true> = { openai: true, "openai-codex": true };
827
+
828
+ /**
829
+ * A row this generator pass owns: one of the derived `gpt-5.6-*-pro` alias ids
830
+ * on `openai`/`openai-codex` that carries the generated `reasoningMode` marker.
831
+ * A real upstream model occupying the same id has no `reasoningMode` and is
832
+ * never touched.
833
+ */
834
+ function isGeneratedOpenAIProReasoningAlias(model: ModelSpec<Api>): boolean {
835
+ return (
836
+ OPENAI_PRO_REASONING_PROVIDERS[model.provider] === true &&
837
+ model.reasoningMode !== undefined &&
838
+ model.id.endsWith("-pro") &&
839
+ OPENAI_PRO_REASONING_BASE_IDS[model.id.slice(0, -"-pro".length)] === true
840
+ );
841
+ }
842
+
843
+ /**
844
+ * Re-derive the generated pro-reasoning aliases (`gpt-5.6-*-pro`) for the
845
+ * first-party `openai`/`openai-codex` gpt-5.6 rows. Each alias inherits the
846
+ * base row's metadata, requests the base wire id via `requestModelId`, and
847
+ * sets `reasoningMode: "pro"` so Responses-family request builders emit
848
+ * `reasoning: { mode: "pro" }`. Called by the models.json generator after all
849
+ * sources merge: stale copies of the owned aliases (previous snapshot) are
850
+ * dropped and re-projected from the current base rows so alias metadata always
851
+ * tracks the base, while a real upstream model that occupies an alias id wins
852
+ * and suppresses the projection.
853
+ */
854
+ export function projectOpenAIProReasoningAliases(models: readonly ModelSpec<Api>[]): ModelSpec<Api>[] {
855
+ const kept = models.filter(model => !isGeneratedOpenAIProReasoningAlias(model));
856
+ const ids = new Set(kept.map(model => `${model.provider}/${model.id}`));
857
+ const out = [...kept];
858
+ for (const model of kept) {
859
+ if (!OPENAI_PRO_REASONING_PROVIDERS[model.provider]) continue;
860
+ if (!OPENAI_PRO_REASONING_BASE_IDS[model.id]) continue;
861
+ const aliasId = `${model.id}-pro`;
862
+ const aliasKey = `${model.provider}/${aliasId}`;
863
+ if (ids.has(aliasKey)) continue;
864
+ ids.add(aliasKey);
865
+ out.push({
866
+ ...model,
867
+ id: aliasId,
868
+ name: `${model.name} Pro`,
869
+ requestModelId: model.id,
870
+ reasoningMode: "pro",
871
+ });
872
+ }
873
+ return out;
874
+ }
875
+
824
876
  // ---------------------------------------------------------------------------
825
877
  // 2. Groq
826
878
  // ---------------------------------------------------------------------------
@@ -915,6 +967,102 @@ export function nvidiaModelManagerOptions(
915
967
  return createSimpleOpenAICompletionsOptions("nvidia", "https://integrate.api.nvidia.com/v1", config);
916
968
  }
917
969
 
970
+ // ---------------------------------------------------------------------------
971
+ // 5.5 Novita
972
+ // ---------------------------------------------------------------------------
973
+
974
+ /** Novita OpenAI-compatible discovery configuration. */
975
+ export interface NovitaModelManagerConfig {
976
+ apiKey?: string;
977
+ baseUrl?: string;
978
+ fetch?: FetchImpl;
979
+ }
980
+
981
+ function novitaArrayIncludes(value: unknown, expected: string): boolean {
982
+ return Array.isArray(value) && value.some(item => item === expected);
983
+ }
984
+
985
+ function isPublicNovitaModelId(id: string): boolean {
986
+ return !id.toLowerCase().startsWith("ai_infer_test");
987
+ }
988
+
989
+ // Novita reports token prices in 1/10,000 USD per million tokens.
990
+ function toNovitaCostPerMillion(value: unknown): number {
991
+ return toPositiveNumber(value, 0) / 10_000;
992
+ }
993
+
994
+ function getNovitaCacheReadPricePerMillion(entry: OpenAICompatibleModelRecord): number {
995
+ const pricing = entry.pricing;
996
+ if (!isRecord(pricing)) {
997
+ return 0;
998
+ }
999
+ const cacheRead = pricing.input_cache_read;
1000
+ if (!isRecord(cacheRead)) {
1001
+ return 0;
1002
+ }
1003
+ return toNovitaCostPerMillion(cacheRead.price_per_m);
1004
+ }
1005
+
1006
+ function mapNovitaModel(
1007
+ entry: OpenAICompatibleModelRecord,
1008
+ defaults: ModelSpec<"openai-completions">,
1009
+ reference: ModelSpec<"openai-completions"> | undefined,
1010
+ ): ModelSpec<"openai-completions"> {
1011
+ const model = mapWithBundledReference(
1012
+ {
1013
+ ...entry,
1014
+ name: entry.display_name ?? entry.title ?? entry.name,
1015
+ },
1016
+ defaults,
1017
+ reference,
1018
+ );
1019
+ return {
1020
+ ...model,
1021
+ reasoning: novitaArrayIncludes(entry.features, "reasoning"),
1022
+ supportsTools: novitaArrayIncludes(entry.features, "function-calling"),
1023
+ input: toInputCapabilities(entry.input_modalities),
1024
+ cost: {
1025
+ input: toNovitaCostPerMillion(entry.input_token_price_per_m),
1026
+ output: toNovitaCostPerMillion(entry.output_token_price_per_m),
1027
+ cacheRead: getNovitaCacheReadPricePerMillion(entry),
1028
+ cacheWrite: 0,
1029
+ },
1030
+ contextWindow: toPositiveNumber(entry.context_size, model.contextWindow),
1031
+ maxTokens: toPositiveNumber(entry.max_output_tokens, model.maxTokens),
1032
+ };
1033
+ }
1034
+
1035
+ /** Builds Novita's public model-discovery manager. */
1036
+ export function novitaModelManagerOptions(
1037
+ config?: NovitaModelManagerConfig,
1038
+ ): ModelManagerOptions<"openai-completions"> {
1039
+ const apiKey = config?.apiKey;
1040
+ const baseUrl = config?.baseUrl ?? "https://api.novita.ai/openai/v1";
1041
+ const references = createBundledReferenceMap<"openai-completions">("novita");
1042
+ return {
1043
+ providerId: "novita",
1044
+ dynamicModelsAuthoritative: true,
1045
+ fetchDynamicModels: async () =>
1046
+ fetchOpenAICompatibleModels({
1047
+ api: "openai-completions",
1048
+ provider: "novita",
1049
+ baseUrl,
1050
+ apiKey,
1051
+ mapModel: (entry, defaults) => mapNovitaModel(entry, defaults, references.get(defaults.id)),
1052
+ filterModel: (entry, model) => {
1053
+ const active = typeof entry.status !== "number" || entry.status === 1;
1054
+ return (
1055
+ active &&
1056
+ isPublicNovitaModelId(model.id) &&
1057
+ novitaArrayIncludes(entry.endpoints, "chat/completions") &&
1058
+ toPositiveNumber(entry.max_output_tokens, 0) > 0
1059
+ );
1060
+ },
1061
+ fetch: config?.fetch,
1062
+ }),
1063
+ };
1064
+ }
1065
+
918
1066
  // ---------------------------------------------------------------------------
919
1067
  // 6. xAI
920
1068
  // ---------------------------------------------------------------------------
@@ -983,6 +1131,7 @@ export const XAI_OAUTH_CURATED_MODELS: readonly XAICuratedModel[] = [
983
1131
  input: ["text", "image"],
984
1132
  },
985
1133
  { id: "grok-4.3", contextWindow: 1_000_000, name: "Grok 4.3", input: ["text", "image"] },
1134
+ { id: "grok-4.5", contextWindow: 500_000, name: "Grok 4.5", input: ["text", "image"] },
986
1135
  // grok-4.20-multi-agent-0309 is text-only per the bundled catalog; omit `input` for the default.
987
1136
  { id: "grok-4.20-multi-agent-0309", contextWindow: 2_000_000, name: "Grok 4.20 (Multi-Agent)" },
988
1137
  {
@@ -1050,18 +1199,21 @@ const XAI_REASONING_EFFORT_MAP = { minimal: "low" } as const;
1050
1199
  // The `minimal -> low` effort clamp (XAI_REASONING_EFFORT_MAP) is always
1051
1200
  // merged in so dynamic-fetched models — which arrive without curated
1052
1201
  // compat keys — still get the clamp applyResponsesReasoningParams expects.
1202
+ // The effort-dial pair (`supportsReasoningEffort`/`omitReasoningEffort`) is
1203
+ // authoritative: a stale flag on `base` (previous snapshot or dynamic fetch)
1204
+ // must not outlive an allowlist change in identity/family.ts.
1053
1205
  function mergeCuratedIntoModel(
1054
1206
  base: ModelSpec<"openai-responses">,
1055
1207
  curated: XAICuratedModel,
1056
1208
  ): ModelSpec<"openai-responses"> {
1057
- const effort = curated.supportsReasoningEffort;
1209
+ const effortCapable = curated.supportsReasoningEffort ?? isGrokReasoningEffortCapable(curated.id);
1058
1210
  const compat = {
1059
1211
  ...(base.compat ?? {}),
1060
1212
  reasoningEffortMap: { ...XAI_REASONING_EFFORT_MAP, ...(base.compat?.reasoningEffortMap ?? {}) },
1061
1213
  includeEncryptedReasoning: base.compat?.includeEncryptedReasoning ?? false,
1062
1214
  filterReasoningHistory: base.compat?.filterReasoningHistory ?? true,
1063
- omitReasoningEffort: base.compat?.omitReasoningEffort ?? !isGrokReasoningEffortCapable(base.id),
1064
- ...(effort === undefined ? {} : { supportsReasoningEffort: effort }),
1215
+ omitReasoningEffort: !effortCapable,
1216
+ supportsReasoningEffort: effortCapable,
1065
1217
  };
1066
1218
  return {
1067
1219
  ...base,
@@ -2649,18 +2801,13 @@ export function basetenModelManagerOptions(
2649
2801
 
2650
2802
  const baseModel = mapWithBundledReference(entry, defaults, reference);
2651
2803
 
2804
+ // Baseten's reasoning router accepts only the high/max
2805
+ // effort tiers for its GLM-5.2 and gpt-oss routes.
2652
2806
  const isEffortReasoning = defaults.id === "openai/gpt-oss-120b" || defaults.id === "zai-org/GLM-5.2";
2653
2807
  const thinking = isEffortReasoning
2654
2808
  ? {
2655
2809
  mode: "effort" as const,
2656
- efforts: [Effort.Minimal, Effort.Low, Effort.Medium, Effort.High, Effort.XHigh],
2657
- effortMap: {
2658
- minimal: "high",
2659
- low: "high",
2660
- medium: "high",
2661
- high: "high",
2662
- xhigh: "max",
2663
- },
2810
+ efforts: [Effort.High, Effort.Max],
2664
2811
  }
2665
2812
  : undefined;
2666
2813
 
@@ -2783,8 +2930,7 @@ const SAKANA_FUGU_ULTRA_COST = { input: 5, output: 30, cacheRead: 0.5, cacheWrit
2783
2930
  const SAKANA_FUGU_ULTRA_CONTEXT_WINDOW = 1_000_000;
2784
2931
  const SAKANA_FUGU_THINKING: ThinkingConfig = {
2785
2932
  mode: "effort",
2786
- efforts: [Effort.High, Effort.XHigh],
2787
- effortMap: { [Effort.XHigh]: "max" },
2933
+ efforts: [Effort.High, Effort.Max],
2788
2934
  };
2789
2935
  const SAKANA_RESPONSES_COMPAT: ModelSpec<"openai-responses">["compat"] = {
2790
2936
  includeEncryptedReasoning: false,
package/src/types.ts CHANGED
@@ -691,6 +691,13 @@ export interface Model<TApi extends Api = Api> {
691
691
  * everything local (selection, caching, usage attribution) keys on `id`.
692
692
  */
693
693
  requestModelId?: string;
694
+ /**
695
+ * `reasoning.mode` to send on OpenAI Responses-family requests. Set on
696
+ * generated pro aliases (`gpt-5.6-*-pro` on `openai`/`openai-codex`) that
697
+ * pair a base wire id (`requestModelId`) with OpenAI's pro reasoning
698
+ * serving path. Absent everywhere else; providers omit the wire field.
699
+ */
700
+ reasoningMode?: "pro";
694
701
  name: string;
695
702
  api: TApi;
696
703
  provider: Provider;
@@ -751,6 +758,8 @@ export interface Model<TApi extends Api = Api> {
751
758
  transport?: "pi-native";
752
759
  /** Hint that websocket transport should be preferred when supported by the provider implementation. */
753
760
  preferWebsockets?: boolean;
761
+ /** Codex Responses Lite transport: send the lite marker and carry instructions/tools as input items (mirrors codex-rs `use_responses_lite`). */
762
+ useResponsesLite?: boolean;
754
763
  /** Preferred model to switch to when context promotion is triggered (model id or provider/id). */
755
764
  contextPromotionTarget?: string;
756
765
  /** Preferred model to use only for compaction (model id or provider/id); the active session model is unchanged. */
@@ -111,15 +111,12 @@ function thinkingPair(baseId: string, name: string): EffortVariantFamily {
111
111
  };
112
112
  }
113
113
 
114
- type DevinTierRoutes = Partial<Record<"off" | "minimal" | "low" | "medium" | "high" | "xhigh", string>>;
114
+ type DevinTierRoutes = Partial<Record<"off" | "minimal" | "low" | "medium" | "high" | "xhigh" | "max", string>>;
115
115
 
116
- const DEVIN_FIVE_TIER_EFFORTS: readonly Effort[] = [
117
- Effort.Minimal,
118
- Effort.Low,
119
- Effort.Medium,
120
- Effort.High,
121
- Effort.XHigh,
122
- ];
116
+ /** Devin families with a `-max` sibling: five wire tiers, `low` floor. */
117
+ const DEVIN_FIVE_TIER_EFFORTS: readonly Effort[] = [Effort.Low, Effort.Medium, Effort.High, Effort.XHigh, Effort.Max];
118
+ /** Devin families topping out at `-xhigh` (pre-5.6 GPT, 5.6 fast lanes). */
119
+ const DEVIN_FOUR_TIER_EFFORTS: readonly Effort[] = [Effort.Low, Effort.Medium, Effort.High, Effort.XHigh];
123
120
 
124
121
  function devinTierFamily(
125
122
  id: string,
@@ -132,11 +129,7 @@ function devinTierFamily(
132
129
  for (const effort of efforts) {
133
130
  switch (effort) {
134
131
  case Effort.Minimal:
135
- if (routes.minimal) {
136
- routing[effort] = routes.minimal;
137
- } else if (routes.low) {
138
- routing[effort] = routes.low;
139
- }
132
+ if (routes.minimal) routing[effort] = routes.minimal;
140
133
  break;
141
134
  case Effort.Low:
142
135
  if (routes.low) routing[effort] = routes.low;
@@ -150,11 +143,20 @@ function devinTierFamily(
150
143
  case Effort.XHigh:
151
144
  if (routes.xhigh) routing[effort] = routes.xhigh;
152
145
  break;
146
+ case Effort.Max:
147
+ if (routes.max) routing[effort] = routes.max;
148
+ break;
153
149
  }
154
150
  }
155
- const members = [routes.off, routes.minimal, routes.low, routes.medium, routes.high, routes.xhigh].filter(
156
- (member, index, items): member is string => typeof member === "string" && items.indexOf(member) === index,
157
- );
151
+ const members = [
152
+ routes.off,
153
+ routes.minimal,
154
+ routes.low,
155
+ routes.medium,
156
+ routes.high,
157
+ routes.xhigh,
158
+ routes.max,
159
+ ].filter((member, index, items): member is string => typeof member === "string" && items.indexOf(member) === index);
158
160
  return {
159
161
  id,
160
162
  name,
@@ -169,11 +171,9 @@ function devinTierFamily(
169
171
  }
170
172
 
171
173
  /**
172
- * GPT-5.6 (Luna/Sol/Terra) adds a genuine `max` tier above `xhigh`, so the
173
- * standard family shifts every user effort up one notch (`minimal` `-low`
174
- * … `xhigh` → `-max`), mirroring the Opus 4.7+ five-tier mapping. Devin
175
- * serves no `-max-priority` sibling, so the fast family keeps the direct
176
- * `low..xhigh` `-priority` scale.
174
+ * GPT-5.6 (Luna/Sol/Terra) serves per-tier siblings for the full five-tier
175
+ * `low..max` wire scale; user efforts route 1:1 onto them. Devin serves no
176
+ * `-max-priority` sibling, so the fast family tops out at `xhigh`.
177
177
  */
178
178
  function devinGpt56Families(variant: "luna" | "sol" | "terra", name: string): readonly EffortVariantFamily[] {
179
179
  const base = `gpt-5-6-${variant}`;
@@ -183,11 +183,11 @@ function devinGpt56Families(variant: "luna" | "sol" | "terra", name: string): re
183
183
  name,
184
184
  {
185
185
  off: `${base}-none`,
186
- minimal: `${base}-low`,
187
- low: `${base}-medium`,
188
- medium: `${base}-high`,
189
- high: `${base}-xhigh`,
190
- xhigh: `${base}-max`,
186
+ low: `${base}-low`,
187
+ medium: `${base}-medium`,
188
+ high: `${base}-high`,
189
+ xhigh: `${base}-xhigh`,
190
+ max: `${base}-max`,
191
191
  },
192
192
  DEVIN_FIVE_TIER_EFFORTS,
193
193
  ),
@@ -201,7 +201,7 @@ function devinGpt56Families(variant: "luna" | "sol" | "terra", name: string): re
201
201
  high: `${base}-high-priority`,
202
202
  xhigh: `${base}-xhigh-priority`,
203
203
  },
204
- DEVIN_FIVE_TIER_EFFORTS,
204
+ DEVIN_FOUR_TIER_EFFORTS,
205
205
  ),
206
206
  ];
207
207
  }
@@ -357,98 +357,54 @@ export const GEMINI_CLI_VARIANT_COLLAPSE_TABLE: VariantCollapseTable = {
357
357
  };
358
358
  export const DEVIN_VARIANT_COLLAPSE_TABLE: VariantCollapseTable = {
359
359
  families: [
360
- {
361
- id: "claude-opus-4-7",
362
- name: "Claude Opus 4.7",
363
- members: [
364
- "claude-opus-4-7-low",
365
- "claude-opus-4-7-medium",
366
- "claude-opus-4-7-high",
367
- "claude-opus-4-7-xhigh",
368
- "claude-opus-4-7-max",
369
- ],
370
- routing: {
371
- [Effort.Minimal]: "claude-opus-4-7-low",
372
- [Effort.Low]: "claude-opus-4-7-medium",
373
- [Effort.Medium]: "claude-opus-4-7-high",
374
- [Effort.High]: "claude-opus-4-7-xhigh",
375
- [Effort.XHigh]: "claude-opus-4-7-max",
376
- },
377
- thinking: {
378
- mode: "effort",
379
- efforts: DEVIN_FIVE_TIER_EFFORTS,
380
- requiresEffort: true,
381
- },
382
- },
383
- {
384
- id: "claude-opus-4-7-fast",
385
- name: "Claude Opus 4.7 Fast",
386
- members: [
387
- "claude-opus-4-7-low-fast",
388
- "claude-opus-4-7-medium-fast",
389
- "claude-opus-4-7-high-fast",
390
- "claude-opus-4-7-xhigh-fast",
391
- "claude-opus-4-7-max-fast",
392
- ],
393
- routing: {
394
- [Effort.Minimal]: "claude-opus-4-7-low-fast",
395
- [Effort.Low]: "claude-opus-4-7-medium-fast",
396
- [Effort.Medium]: "claude-opus-4-7-high-fast",
397
- [Effort.High]: "claude-opus-4-7-xhigh-fast",
398
- [Effort.XHigh]: "claude-opus-4-7-max-fast",
399
- },
400
- thinking: {
401
- mode: "effort",
402
- efforts: DEVIN_FIVE_TIER_EFFORTS,
403
- requiresEffort: true,
404
- },
405
- },
406
- {
407
- id: "claude-opus-4-8",
408
- name: "Claude Opus 4.8",
409
- members: [
410
- "claude-opus-4-8-low",
411
- "claude-opus-4-8-medium",
412
- "claude-opus-4-8-high",
413
- "claude-opus-4-8-xhigh",
414
- "claude-opus-4-8-max",
415
- ],
416
- routing: {
417
- [Effort.Minimal]: "claude-opus-4-8-low",
418
- [Effort.Low]: "claude-opus-4-8-medium",
419
- [Effort.Medium]: "claude-opus-4-8-high",
420
- [Effort.High]: "claude-opus-4-8-xhigh",
421
- [Effort.XHigh]: "claude-opus-4-8-max",
360
+ devinTierFamily(
361
+ "claude-opus-4-7",
362
+ "Claude Opus 4.7",
363
+ {
364
+ low: "claude-opus-4-7-low",
365
+ medium: "claude-opus-4-7-medium",
366
+ high: "claude-opus-4-7-high",
367
+ xhigh: "claude-opus-4-7-xhigh",
368
+ max: "claude-opus-4-7-max",
422
369
  },
423
- thinking: {
424
- mode: "effort",
425
- efforts: DEVIN_FIVE_TIER_EFFORTS,
426
- requiresEffort: true,
370
+ DEVIN_FIVE_TIER_EFFORTS,
371
+ ),
372
+ devinTierFamily(
373
+ "claude-opus-4-7-fast",
374
+ "Claude Opus 4.7 Fast",
375
+ {
376
+ low: "claude-opus-4-7-low-fast",
377
+ medium: "claude-opus-4-7-medium-fast",
378
+ high: "claude-opus-4-7-high-fast",
379
+ xhigh: "claude-opus-4-7-xhigh-fast",
380
+ max: "claude-opus-4-7-max-fast",
427
381
  },
428
- },
429
- {
430
- id: "claude-opus-4-8-fast",
431
- name: "Claude Opus 4.8 Fast",
432
- members: [
433
- "claude-opus-4-8-low-fast",
434
- "claude-opus-4-8-medium-fast",
435
- "claude-opus-4-8-high-fast",
436
- "claude-opus-4-8-xhigh-fast",
437
- "claude-opus-4-8-max-fast",
438
- ],
439
- routing: {
440
- [Effort.Minimal]: "claude-opus-4-8-low-fast",
441
- [Effort.Low]: "claude-opus-4-8-medium-fast",
442
- [Effort.Medium]: "claude-opus-4-8-high-fast",
443
- [Effort.High]: "claude-opus-4-8-xhigh-fast",
444
- [Effort.XHigh]: "claude-opus-4-8-max-fast",
382
+ DEVIN_FIVE_TIER_EFFORTS,
383
+ ),
384
+ devinTierFamily(
385
+ "claude-opus-4-8",
386
+ "Claude Opus 4.8",
387
+ {
388
+ low: "claude-opus-4-8-low",
389
+ medium: "claude-opus-4-8-medium",
390
+ high: "claude-opus-4-8-high",
391
+ xhigh: "claude-opus-4-8-xhigh",
392
+ max: "claude-opus-4-8-max",
445
393
  },
446
- thinking: {
447
- mode: "effort",
448
- efforts: DEVIN_FIVE_TIER_EFFORTS,
449
- requiresEffort: true,
394
+ DEVIN_FIVE_TIER_EFFORTS,
395
+ ),
396
+ devinTierFamily(
397
+ "claude-opus-4-8-fast",
398
+ "Claude Opus 4.8 Fast",
399
+ {
400
+ low: "claude-opus-4-8-low-fast",
401
+ medium: "claude-opus-4-8-medium-fast",
402
+ high: "claude-opus-4-8-high-fast",
403
+ xhigh: "claude-opus-4-8-xhigh-fast",
404
+ max: "claude-opus-4-8-max-fast",
450
405
  },
451
- },
406
+ DEVIN_FIVE_TIER_EFFORTS,
407
+ ),
452
408
  devinTierFamily(
453
409
  "gpt-5-2",
454
410
  "GPT-5.2",
@@ -459,7 +415,7 @@ export const DEVIN_VARIANT_COLLAPSE_TABLE: VariantCollapseTable = {
459
415
  high: "MODEL_GPT_5_2_HIGH",
460
416
  xhigh: "MODEL_GPT_5_2_XHIGH",
461
417
  },
462
- DEVIN_FIVE_TIER_EFFORTS,
418
+ DEVIN_FOUR_TIER_EFFORTS,
463
419
  ),
464
420
  devinTierFamily(
465
421
  "gpt-5-3-codex",
@@ -470,7 +426,7 @@ export const DEVIN_VARIANT_COLLAPSE_TABLE: VariantCollapseTable = {
470
426
  high: "gpt-5-3-codex-high",
471
427
  xhigh: "gpt-5-3-codex-xhigh",
472
428
  },
473
- DEVIN_FIVE_TIER_EFFORTS,
429
+ DEVIN_FOUR_TIER_EFFORTS,
474
430
  ),
475
431
  devinTierFamily(
476
432
  "gpt-5-3-codex-fast",
@@ -481,7 +437,7 @@ export const DEVIN_VARIANT_COLLAPSE_TABLE: VariantCollapseTable = {
481
437
  high: "gpt-5-3-codex-high-priority",
482
438
  xhigh: "gpt-5-3-codex-xhigh-priority",
483
439
  },
484
- DEVIN_FIVE_TIER_EFFORTS,
440
+ DEVIN_FOUR_TIER_EFFORTS,
485
441
  ),
486
442
  devinTierFamily(
487
443
  "gpt-5-4",
@@ -493,7 +449,7 @@ export const DEVIN_VARIANT_COLLAPSE_TABLE: VariantCollapseTable = {
493
449
  high: "gpt-5-4-high",
494
450
  xhigh: "gpt-5-4-xhigh",
495
451
  },
496
- DEVIN_FIVE_TIER_EFFORTS,
452
+ DEVIN_FOUR_TIER_EFFORTS,
497
453
  ),
498
454
  devinTierFamily(
499
455
  "gpt-5-4-fast",
@@ -505,7 +461,7 @@ export const DEVIN_VARIANT_COLLAPSE_TABLE: VariantCollapseTable = {
505
461
  high: "gpt-5-4-high-priority",
506
462
  xhigh: "gpt-5-4-xhigh-priority",
507
463
  },
508
- DEVIN_FIVE_TIER_EFFORTS,
464
+ DEVIN_FOUR_TIER_EFFORTS,
509
465
  ),
510
466
  devinTierFamily(
511
467
  "gpt-5-4-mini",
@@ -516,7 +472,7 @@ export const DEVIN_VARIANT_COLLAPSE_TABLE: VariantCollapseTable = {
516
472
  high: "gpt-5-4-mini-high",
517
473
  xhigh: "gpt-5-4-mini-xhigh",
518
474
  },
519
- DEVIN_FIVE_TIER_EFFORTS,
475
+ DEVIN_FOUR_TIER_EFFORTS,
520
476
  ),
521
477
  devinTierFamily(
522
478
  "gpt-5-5",
@@ -528,7 +484,7 @@ export const DEVIN_VARIANT_COLLAPSE_TABLE: VariantCollapseTable = {
528
484
  high: "gpt-5-5-high",
529
485
  xhigh: "gpt-5-5-xhigh",
530
486
  },
531
- DEVIN_FIVE_TIER_EFFORTS,
487
+ DEVIN_FOUR_TIER_EFFORTS,
532
488
  ),
533
489
  devinTierFamily(
534
490
  "gpt-5-5-fast",
@@ -540,7 +496,7 @@ export const DEVIN_VARIANT_COLLAPSE_TABLE: VariantCollapseTable = {
540
496
  high: "gpt-5-5-high-priority",
541
497
  xhigh: "gpt-5-5-xhigh-priority",
542
498
  },
543
- DEVIN_FIVE_TIER_EFFORTS,
499
+ DEVIN_FOUR_TIER_EFFORTS,
544
500
  ),
545
501
  ...devinGpt56Families("luna", "GPT-5.6 Luna"),
546
502
  ...devinGpt56Families("sol", "GPT-5.6 Sol"),
package/src/wire/codex.ts CHANGED
@@ -10,6 +10,15 @@ export const OPENAI_HEADERS = {
10
10
  ORIGINATOR: "originator",
11
11
  SESSION_ID: "session_id",
12
12
  CONVERSATION_ID: "conversation_id",
13
+ SCOPED_SESSION_ID: "session-id",
14
+ THREAD_ID: "thread-id",
15
+ INSTALLATION_ID: "x-codex-installation-id",
16
+ WINDOW_ID: "x-codex-window-id",
17
+ TURN_METADATA: "x-codex-turn-metadata",
18
+ PARENT_THREAD_ID: "x-codex-parent-thread-id",
19
+ SUBAGENT: "x-openai-subagent",
20
+ /** Responses Lite transport marker (codex-rs `add_responses_lite_header`); value is always `"true"`. */
21
+ RESPONSES_LITE: "x-openai-internal-codex-responses-lite",
13
22
  } as const;
14
23
 
15
24
  export const OPENAI_HEADER_VALUES = {