@oh-my-pi/pi-catalog 18.2.10 → 18.3.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.
Files changed (36) hide show
  1. package/CHANGELOG.md +20 -0
  2. package/README.md +1 -1
  3. package/THIRD-PARTY-NOTICES.txt +1 -1
  4. package/dist/types/compat/auth-ids.d.ts +2 -2
  5. package/dist/types/compat/provider-ids.d.ts +1 -1
  6. package/dist/types/compat/types.d.ts +4 -0
  7. package/dist/types/discovery/cursor-proto.d.ts +1 -1
  8. package/dist/types/discovery/devin-proto.d.ts +1 -1
  9. package/dist/types/provider-models/openai-compat.d.ts +25 -0
  10. package/dist/types/types.d.ts +24 -6
  11. package/package.json +8 -5
  12. package/src/compat/auth-ids.ts +3 -0
  13. package/src/compat/provider-ids.ts +2 -0
  14. package/src/compat/rules/README.md +4 -0
  15. package/src/compat/rules/auth/_order.kdl +1 -1
  16. package/src/compat/rules/auth/anthropic.kdl +1 -0
  17. package/src/compat/rules/auth/apple.kdl +4 -0
  18. package/src/compat/rules/auth/openai-codex.kdl +1 -0
  19. package/src/compat/rules/auth/stepfun.kdl +13 -0
  20. package/src/compat/rules/auth/xai-oauth.kdl +1 -0
  21. package/src/compat/rules/classes/anthropic.kdl +23 -18
  22. package/src/compat/rules/providers/apple.kdl +8 -0
  23. package/src/compat/rules/providers/openai-codex.kdl +16 -0
  24. package/src/compat/rules/providers/stepfun.kdl +95 -0
  25. package/src/compat/rules/runtime/behavior.kdl +10 -2
  26. package/src/compat/rules.json +1 -1
  27. package/src/compat/types.ts +4 -0
  28. package/src/discovery/codex.ts +29 -4
  29. package/src/discovery/cursor-proto.ts +1 -1
  30. package/src/discovery/devin-proto.ts +1 -1
  31. package/src/model-manager.ts +8 -2
  32. package/src/models.json +1 -1
  33. package/src/provider-models/descriptors.ts +2 -0
  34. package/src/provider-models/openai-compat.ts +92 -1
  35. package/src/provider-models/special.ts +11 -2
  36. package/src/types.ts +26 -6
@@ -61,6 +61,7 @@ import {
61
61
  siliconflowModelManagerOptions,
62
62
  singularityApiDevModelManagerOptions,
63
63
  singularityApiTechModelManagerOptions,
64
+ stepfunModelManagerOptions,
64
65
  syntheticModelManagerOptions,
65
66
  togetherModelManagerOptions,
66
67
  umansModelManagerOptions,
@@ -141,6 +142,7 @@ const MODEL_MANAGER_FACTORIES: Readonly<Partial<Record<KnownProvider, ModelManag
141
142
  "siliconflow-cn": config => siliconflowCnModelManagerOptions(config),
142
143
  "singularityapi-dev": config => singularityApiDevModelManagerOptions(config),
143
144
  "singularityapi-tech": config => singularityApiTechModelManagerOptions(config),
145
+ stepfun: config => stepfunModelManagerOptions(config),
144
146
  synthetic: config => syntheticModelManagerOptions(config),
145
147
  together: config => togetherModelManagerOptions(config),
146
148
  typesafe: config => typesafeModelManagerOptions(config),
@@ -4956,6 +4956,86 @@ export function yoloAutoModelManagerOptions(
4956
4956
  }
4957
4957
 
4958
4958
  // ---------------------------------------------------------------------------
4959
+ // 16.9 StepFun
4960
+ // ---------------------------------------------------------------------------
4961
+
4962
+ /**
4963
+ * StepFun discovery configuration: the API key plus optional base-URL and
4964
+ * fetch overrides. Consumed by {@link stepfunModelManagerOptions}, and exported
4965
+ * for extensions and tests that construct the manager directly.
4966
+ */
4967
+ export interface StepfunModelManagerConfig {
4968
+ apiKey?: string;
4969
+ baseUrl?: string;
4970
+ fetch?: FetchImpl;
4971
+ }
4972
+
4973
+ /** StepFun's `/v1/models` row shape beyond the generic OpenAI-compatible fields. */
4974
+ interface StepfunModelRecord extends OpenAICompatibleModelRecord {
4975
+ /** Reasoning tiers the endpoint advertises for the model, e.g. `["low","medium","high"]`. */
4976
+ reasoning_effort_support_list?: unknown;
4977
+ }
4978
+
4979
+ /**
4980
+ * Translate StepFun's per-model `reasoning_effort_support_list` into a ladder.
4981
+ * Every advertised value that names an OMP tier maps verbatim, in OMP's tier
4982
+ * order; a row advertising nothing (or only tiers this client does not know)
4983
+ * resolves to no thinking, so the wire path never sends a `reasoning_effort`
4984
+ * the endpoint rejects. Same shape as `mapOpenRouterThinking` for OpenRouter's
4985
+ * `reasoning.supported_efforts`.
4986
+ */
4987
+ function mapStepfunThinking(entry: StepfunModelRecord): ThinkingConfig | undefined {
4988
+ const advertised = Array.isArray(entry.reasoning_effort_support_list)
4989
+ ? entry.reasoning_effort_support_list.filter((value): value is string => typeof value === "string")
4990
+ : [];
4991
+ const efforts = THINKING_EFFORTS.filter(effort => advertised.includes(effort));
4992
+ return efforts.length === 0 ? undefined : { mode: "effort", efforts };
4993
+ }
4994
+
4995
+ /**
4996
+ * Whether a StepFun `/v1/models` id is a chat model omp can route. StepFun's
4997
+ * roster interleaves its audio and image SKUs with the chat models; the
4998
+ * exclusion policy itself lives in `runtime/behavior.kdl` (`exclude-models
4999
+ * provider="stepfun"`), not here.
5000
+ */
5001
+ export function isStepfunChatModelId(id: string): boolean {
5002
+ const normalized = id.trim().toLowerCase();
5003
+ if (!normalized) return false;
5004
+ return !isExcludedModel("stepfun", normalized);
5005
+ }
5006
+
5007
+ /**
5008
+ * StepFun model manager: plain OpenAI-compatible chat completions at
5009
+ * `api.stepfun.ai/v1`. A successful `/v1/models` snapshot is authoritative over
5010
+ * the bundled seed rows (`providers/stepfun.kdl`), so a model StepFun retires
5011
+ * leaves the picker instead of lingering as a dead seed row, while models added
5012
+ * later become selectable without an omp release.
5013
+ */
5014
+ export function stepfunModelManagerOptions(
5015
+ config?: StepfunModelManagerConfig,
5016
+ ): ModelManagerOptions<"openai-completions"> {
5017
+ return createOpenAICompatibleModelManagerOptions({
5018
+ api: "openai-completions",
5019
+ providerId: "stepfun",
5020
+ defaultBaseUrl: "https://api.stepfun.ai/v1",
5021
+ config,
5022
+ requireApiKey: true,
5023
+ filterModel: (_entry, model) => isStepfunChatModelId(model.id),
5024
+ mapModel: (entry, model, reference) => {
5025
+ const mapped = mapWithBundledReference(entry, model, reference);
5026
+ // A model StepFun ships later has no bundled reference, so it starts
5027
+ // from the generic defaults (`reasoning: false`, no thinking) and
5028
+ // `mergeDynamicModels` adds it verbatim — the endpoint's own tiers are
5029
+ // then the only thing that can give it a reasoning dial.
5030
+ if (reference) return mapped;
5031
+ const thinking = mapStepfunThinking(entry);
5032
+ return thinking === undefined ? mapped : { ...mapped, reasoning: true, thinking };
5033
+ },
5034
+ // Must live on the manager options, not only the KDL descriptor:
5035
+ // `createModelManager()` prunes the bundled slice from this flag.
5036
+ dynamicModelsAuthoritative: true,
5037
+ });
5038
+ }
4959
5039
 
4960
5040
  // ---------------------------------------------------------------------------
4961
5041
  // 17. Qwen Portal
@@ -5936,6 +6016,9 @@ export interface GithubCopilotModelManagerConfig {
5936
6016
  fetch?: FetchImpl;
5937
6017
  }
5938
6018
 
6019
+ // Copilot ids whose cached route predates the Responses pin: a cache written by
6020
+ // an older build still says openai-completions, which Copilot answers with 400
6021
+ // unsupported_api_for_model (#7096, #8807, #12901).
5939
6022
  const COPILOT_CACHE_INVALIDATED_MODEL_IDS = [
5940
6023
  "gpt-6-astra",
5941
6024
  "gpt-6-astra-1m",
@@ -5943,6 +6026,8 @@ const COPILOT_CACHE_INVALIDATED_MODEL_IDS = [
5943
6026
  "grok-4.5-1m",
5944
6027
  "grok-4.6",
5945
6028
  "grok-4.6-1m",
6029
+ "grok-4.7",
6030
+ "grok-4.7-1m",
5946
6031
  "mai-code-1-flash-picker",
5947
6032
  ];
5948
6033
 
@@ -6211,7 +6296,13 @@ export function githubCopilotModelManagerOptions(config?: GithubCopilotModelMana
6211
6296
  supportsReasoningEffort: false,
6212
6297
  },
6213
6298
  }
6214
- : {}),
6299
+ : // The bundled row for an id whose route later moved to
6300
+ // Responses/Messages still carries this chat-completions
6301
+ // block, and `supportsReasoningEffort: false` suppresses
6302
+ // the effort dial on a transport that supports it
6303
+ // (grok-4.7, #12901). Compat is transport-scoped: let the
6304
+ // rules resolve it for the route actually in use.
6305
+ { compat: undefined }),
6215
6306
  }
6216
6307
  : {
6217
6308
  ...defaults,
@@ -77,7 +77,8 @@ export function openaiCodexModelManagerOptions(
77
77
 
78
78
  /**
79
79
  * Merge complete per-account Codex catalogs into one authoritative list,
80
- * deduped by model id (first account to expose an id wins).
80
+ * deduped by model id. The first account to expose an id supplies its spec;
81
+ * account access is merged from every account whose catalog lists that id.
81
82
  *
82
83
  * Returns `null` when any account's fetch failed transiently, so a partial list
83
84
  * cannot replace the previous or bundled authoritative catalog. An account
@@ -102,7 +103,15 @@ function unionCodexModels(
102
103
  }
103
104
  catalogs++;
104
105
  for (const model of result.models) {
105
- if (!byId.has(model.id)) byId.set(model.id, model);
106
+ const existing = byId.get(model.id);
107
+ if (!existing) {
108
+ byId.set(model.id, model);
109
+ } else if (model.accountAccess) {
110
+ byId.set(model.id, {
111
+ ...existing,
112
+ accountAccess: { ...existing.accountAccess, ...model.accountAccess },
113
+ });
114
+ }
106
115
  }
107
116
  }
108
117
  return catalogs > 0 ? [...byId.values()] : null;
package/src/types.ts CHANGED
@@ -20,7 +20,8 @@ export type KnownApi =
20
20
  | "ollama-chat"
21
21
  | "cursor-agent"
22
22
  | "gitlab-duo-agent"
23
- | "devin-agent";
23
+ | "devin-agent"
24
+ | "apple-foundation-models";
24
25
  export type Api = KnownApi | (string & {});
25
26
 
26
27
  /** Catalog kinds used to isolate role-specific runners from session chat models. */
@@ -519,17 +520,17 @@ export interface AnthropicCompat {
519
520
  /** Whether thinking requests may include `context_management` and its beta header. Default: true. */
520
521
  supportsContextManagement?: boolean;
521
522
  /**
522
- * Whether the model lineage supports Anthropic server-side compaction
523
- * (`compact-2026-01-12`: the `compact_20260112` edit and replayed
524
- * `compaction` blocks). Rule-owned per model line; the beta covers the
525
- * adaptive-thinking generation onward and rejects older lines. Default: false.
523
+ * Whether the model and host support Anthropic on-demand compaction
524
+ * (`compact-2026-09-04` requests and signed replay). Enabled on Opus 4.6+,
525
+ * Sonnet 4.6+, Fable/Mythos 5+ on supported hosts. Default: false.
526
526
  */
527
527
  supportsServerCompaction?: boolean;
528
528
  /**
529
529
  * Whether the model is served by the first-party Anthropic provider (its
530
530
  * default route is the official API). Rule-owned on the provider; the
531
531
  * compaction transport pairs it with a per-request effective-URL check
532
- * because reroutes leave it stale-true. Default: false.
532
+ * because reroutes leave it stale-true. Vertex is selected by its provider
533
+ * contract instead. Default: false.
533
534
  */
534
535
  firstPartyProvider?: boolean;
535
536
  /**
@@ -1163,6 +1164,16 @@ export type ModelTokenizer =
1163
1164
  | "kimi-k2"
1164
1165
  | "glm5";
1165
1166
 
1167
+ /** One account's discovered entitlements on a model; see {@link Model.accountAccess}. */
1168
+ export interface ModelAccountAccess {
1169
+ /**
1170
+ * Codex `available_access_programs.cyber`: cyber access programs this account
1171
+ * may request on the model (`standard`, `daybreak_blue`, `daybreak_red`).
1172
+ * Absent when the backend reported no program metadata.
1173
+ */
1174
+ cyberPrograms?: readonly string[];
1175
+ }
1176
+
1166
1177
  // Model interface for the unified model system
1167
1178
  export interface Model<TApi extends Api = Api> {
1168
1179
  id: string;
@@ -1257,6 +1268,15 @@ export interface Model<TApi extends Api = Api> {
1257
1268
  * their single wire id) and on bundled snapshots that predate discovery.
1258
1269
  */
1259
1270
  cursorMaxModeRoutes?: Readonly<Record<string, boolean>>;
1271
+ /**
1272
+ * Per-account availability recorded by multi-account discovery: provider
1273
+ * account id (Codex: ChatGPT `chatgpt_account_id`) → that account's
1274
+ * entitlements on this model. An account appears only when its own catalog
1275
+ * lists the model, so credential selection can route account-gated models
1276
+ * (e.g. `gpt-daybreak-blue-latest`) straight to eligible accounts. Absent on
1277
+ * bundled/config rows and on single-account discovery.
1278
+ */
1279
+ accountAccess?: Readonly<Record<string, ModelAccountAccess>>;
1260
1280
  cost: ModelCost;
1261
1281
  /** Premium Copilot requests charged per user-initiated request (defaults to 1). */
1262
1282
  premiumMultiplier?: number;