@oh-my-pi/pi-catalog 18.16.0 → 18.18.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 (34) hide show
  1. package/CHANGELOG.md +26 -0
  2. package/dist/types/compat/auth-ids.d.ts +2 -2
  3. package/dist/types/compat/responses-websocket.d.ts +6 -0
  4. package/dist/types/compat/types.d.ts +6 -0
  5. package/dist/types/discovery/devin-proto.d.ts +15 -0
  6. package/dist/types/model-manager.d.ts +2 -0
  7. package/dist/types/types.d.ts +17 -1
  8. package/dist/types/wire/codex.d.ts +0 -1
  9. package/dist/types/wire/factory-droid.d.ts +1 -1
  10. package/package.json +5 -5
  11. package/src/compat/auth-ids.ts +4 -0
  12. package/src/compat/axes.ts +6 -0
  13. package/src/compat/resolve.ts +2 -0
  14. package/src/compat/responses-websocket.ts +12 -0
  15. package/src/compat/rules/auth/_order.kdl +1 -1
  16. package/src/compat/rules/auth/devin-cli.kdl +6 -0
  17. package/src/compat/rules/auth/devin-windsurf.kdl +6 -0
  18. package/src/compat/rules/classes/anthropic.kdl +16 -0
  19. package/src/compat/rules/providers/factory-droid.kdl +56 -4
  20. package/src/compat/rules/providers/muse-code.kdl +16 -0
  21. package/src/compat/rules/providers/openai.kdl +3 -0
  22. package/src/compat/rules/providers/web.kdl +7 -0
  23. package/src/compat/rules/runtime/behavior.kdl +4 -4
  24. package/src/compat/rules.json +1 -1
  25. package/src/compat/types.ts +6 -0
  26. package/src/discovery/codex.ts +0 -1
  27. package/src/discovery/devin-proto.ts +28 -0
  28. package/src/discovery/factory-droid.ts +23 -12
  29. package/src/model-manager.ts +22 -13
  30. package/src/models.json +1 -1
  31. package/src/provider-models/openai-compat.ts +38 -1
  32. package/src/types.ts +17 -1
  33. package/src/wire/codex.ts +0 -1
  34. package/src/wire/factory-droid.ts +1 -1
package/CHANGELOG.md CHANGED
@@ -2,6 +2,32 @@
2
2
 
3
3
  ## [Unreleased]
4
4
 
5
+ ## [18.18.0] - 2026-11-07
6
+
7
+ ### Fixed
8
+
9
+ - Fixed Mistral discovery listing embedding, OCR, moderation, transcription, and speech models as chat models; only rows with `capabilities.completion_chat` are offered, with context, image input, and reasoning read from the row ([#18244](https://github.com/can1357/oh-my-pi/pull/18244) by [@VeigaPunk](https://github.com/VeigaPunk))
10
+ - A failed refresh no longer replaces a cached catalog whose models carry request headers with an empty snapshot; the next launch refetches it instead ([#18227](https://github.com/can1357/oh-my-pi/issues/18227))
11
+
12
+ ## [18.17.0] - 2026-11-06
13
+
14
+ ### Added
15
+
16
+ - Added `tool-name-prefix` compat axis for Responses hosts that reject certain tool names; Muse Code sets it to `_` ([#17435](https://github.com/can1357/oh-my-pi/issues/17435), [#17515](https://github.com/can1357/oh-my-pi/pull/17515) by [@harshav167](https://github.com/harshav167), continued in [#18053](https://github.com/can1357/oh-my-pi/pull/18053) by [@abilliontokens](https://github.com/abilliontokens))
17
+ - Added `supports-message-threads` compat axis (`supportsMessageThreads`), enabled for Claude 4.5+ on first-party Anthropic
18
+ - Added opt-in Responses WebSocket capability via OMP settings or SDK preferences, off by default ([#17354](https://github.com/can1357/oh-my-pi/pull/17354) by [@TatsukiMeng](https://github.com/TatsukiMeng))
19
+ - Added Factory Droid Gemini 4 Argon on Global inference for accounts with the feature flag ([#17861](https://github.com/can1357/oh-my-pi/pull/17861) by [@will-bogusz](https://github.com/will-bogusz))
20
+ - Added Factory Droid Muse Spark 1.3 (Global region, `muse_spark_1_3` flag) with low to xhigh effort ([#17862](https://github.com/can1357/oh-my-pi/pull/17862) by [@will-bogusz](https://github.com/will-bogusz))
21
+
22
+ ### Changed
23
+
24
+ - Updated Factory Droid client version reporting; improved tool-input streaming for Claude via Azure Foundry
25
+
26
+ ### Fixed
27
+
28
+ - Fixed newly published Azure models missing after catalog refresh ([#18173](https://github.com/can1357/oh-my-pi/issues/18173), [#18174](https://github.com/can1357/oh-my-pi/pull/18174) by [@dunkpi](https://github.com/dunkpi))
29
+ - Fixed Factory Droid hiding models when the live-routing family default yields no usable upstream; explicit empty per-model routes still hide them ([#17862](https://github.com/can1357/oh-my-pi/pull/17862) by [@will-bogusz](https://github.com/will-bogusz))
30
+
5
31
  ## [18.16.0] - 2026-11-02
6
32
 
7
33
  ### Added
@@ -1,4 +1,4 @@
1
1
  /** Every provider with an `auth/<id>.kdl` policy. */
2
- export type AuthProviderId = "abliteration" | "aiand" | "aimlapi" | "alibaba-coding-plan" | "alibaba-token-plan" | "amazon-bedrock" | "anthropic" | "apple" | "azure" | "baseten" | "bedrock-mantle" | "cerebras" | "charm-hyper" | "cline-pass" | "cloudflare-ai-gateway" | "cloudflare-workers-ai" | "commandcode" | "coralbricks" | "coreweave" | "cursor" | "deepinfra" | "deepseek" | "devin" | "exa" | "factory-droid" | "firepass" | "fireworks" | "github-copilot" | "gitlab-duo" | "gitlab-duo-agent" | "gmi-cloud" | "google" | "google-antigravity" | "google-gemini-cli" | "google-vertex" | "groq" | "helmcode" | "huggingface" | "inception" | "kagi" | "kilo" | "kimi-code" | "litellm" | "llama.cpp" | "lm-studio" | "local" | "meta" | "minimax" | "minimax-code" | "minimax-code-cn" | "mistral" | "modular" | "moonshot" | "muse-code" | "nanogpt" | "novita" | "nvidia" | "ollama" | "ollama-cloud" | "openai" | "openai-codex" | "openai-codex-device" | "opencode-go" | "opencode-zen" | "openrouter" | "parallel" | "perplexity" | "qianfan" | "qwen-portal" | "sakana" | "sambanova" | "scaleway" | "siliconflow" | "siliconflow-cn" | "singularityapi-dev" | "singularityapi-tech" | "snowflake" | "stencil" | "stepfun" | "synthetic" | "tavily" | "together" | "typesafe" | "umans" | "venice" | "vercel-ai-gateway" | "vllm" | "wafer-serverless" | "web" | "xai" | "xai-oauth" | "xiaomi" | "xiaomi-token-plan-ams" | "xiaomi-token-plan-cn" | "xiaomi-token-plan-sgp" | "yolo-auto" | "zai" | "zai-coding-plan" | "zenmux" | "zhipu-coding-plan";
2
+ export type AuthProviderId = "abliteration" | "aiand" | "aimlapi" | "alibaba-coding-plan" | "alibaba-token-plan" | "amazon-bedrock" | "anthropic" | "apple" | "azure" | "baseten" | "bedrock-mantle" | "cerebras" | "charm-hyper" | "cline-pass" | "cloudflare-ai-gateway" | "cloudflare-workers-ai" | "commandcode" | "coralbricks" | "coreweave" | "cursor" | "deepinfra" | "deepseek" | "devin" | "devin-cli" | "devin-windsurf" | "exa" | "factory-droid" | "firepass" | "fireworks" | "github-copilot" | "gitlab-duo" | "gitlab-duo-agent" | "gmi-cloud" | "google" | "google-antigravity" | "google-gemini-cli" | "google-vertex" | "groq" | "helmcode" | "huggingface" | "inception" | "kagi" | "kilo" | "kimi-code" | "litellm" | "llama.cpp" | "lm-studio" | "local" | "meta" | "minimax" | "minimax-code" | "minimax-code-cn" | "mistral" | "modular" | "moonshot" | "muse-code" | "nanogpt" | "novita" | "nvidia" | "ollama" | "ollama-cloud" | "openai" | "openai-codex" | "openai-codex-device" | "opencode-go" | "opencode-zen" | "openrouter" | "parallel" | "perplexity" | "qianfan" | "qwen-portal" | "sakana" | "sambanova" | "scaleway" | "siliconflow" | "siliconflow-cn" | "singularityapi-dev" | "singularityapi-tech" | "snowflake" | "stencil" | "stepfun" | "synthetic" | "tavily" | "together" | "typesafe" | "umans" | "venice" | "vercel-ai-gateway" | "vllm" | "wafer-serverless" | "web" | "xai" | "xai-oauth" | "xiaomi" | "xiaomi-token-plan-ams" | "xiaomi-token-plan-cn" | "xiaomi-token-plan-sgp" | "yolo-auto" | "zai" | "zai-coding-plan" | "zenmux" | "zhipu-coding-plan";
3
3
  /** Providers whose policy declares a `login` flow (the `/login` roster). */
4
- export type LoginProviderId = "abliteration" | "aiand" | "alibaba-coding-plan" | "alibaba-token-plan" | "anthropic" | "baseten" | "cerebras" | "charm-hyper" | "cline-pass" | "cloudflare-ai-gateway" | "cloudflare-workers-ai" | "commandcode" | "coralbricks" | "coreweave" | "cursor" | "deepinfra" | "deepseek" | "devin" | "exa" | "factory-droid" | "firepass" | "fireworks" | "github-copilot" | "gitlab-duo" | "gitlab-duo-agent" | "gmi-cloud" | "google-antigravity" | "google-gemini-cli" | "helmcode" | "huggingface" | "inception" | "kagi" | "kilo" | "kimi-code" | "litellm" | "llama.cpp" | "lm-studio" | "meta" | "minimax-code" | "minimax-code-cn" | "mistral" | "modular" | "moonshot" | "muse-code" | "nanogpt" | "novita" | "nvidia" | "ollama" | "ollama-cloud" | "openai-codex" | "openai-codex-device" | "opencode-go" | "opencode-zen" | "openrouter" | "parallel" | "perplexity" | "qianfan" | "qwen-portal" | "sakana" | "sambanova" | "scaleway" | "siliconflow" | "siliconflow-cn" | "singularityapi-dev" | "singularityapi-tech" | "snowflake" | "stencil" | "stepfun" | "synthetic" | "tavily" | "together" | "typesafe" | "umans" | "venice" | "vercel-ai-gateway" | "vllm" | "wafer-serverless" | "xai" | "xai-oauth" | "xiaomi" | "xiaomi-token-plan-ams" | "xiaomi-token-plan-cn" | "xiaomi-token-plan-sgp" | "yolo-auto" | "zai" | "zai-coding-plan" | "zenmux" | "zhipu-coding-plan";
4
+ export type LoginProviderId = "abliteration" | "aiand" | "alibaba-coding-plan" | "alibaba-token-plan" | "anthropic" | "baseten" | "cerebras" | "charm-hyper" | "cline-pass" | "cloudflare-ai-gateway" | "cloudflare-workers-ai" | "commandcode" | "coralbricks" | "coreweave" | "cursor" | "deepinfra" | "deepseek" | "devin" | "devin-cli" | "devin-windsurf" | "exa" | "factory-droid" | "firepass" | "fireworks" | "github-copilot" | "gitlab-duo" | "gitlab-duo-agent" | "gmi-cloud" | "google-antigravity" | "google-gemini-cli" | "helmcode" | "huggingface" | "inception" | "kagi" | "kilo" | "kimi-code" | "litellm" | "llama.cpp" | "lm-studio" | "meta" | "minimax-code" | "minimax-code-cn" | "mistral" | "modular" | "moonshot" | "muse-code" | "nanogpt" | "novita" | "nvidia" | "ollama" | "ollama-cloud" | "openai-codex" | "openai-codex-device" | "opencode-go" | "opencode-zen" | "openrouter" | "parallel" | "perplexity" | "qianfan" | "qwen-portal" | "sakana" | "sambanova" | "scaleway" | "siliconflow" | "siliconflow-cn" | "singularityapi-dev" | "singularityapi-tech" | "snowflake" | "stencil" | "stepfun" | "synthetic" | "tavily" | "together" | "typesafe" | "umans" | "venice" | "vercel-ai-gateway" | "vllm" | "wafer-serverless" | "xai" | "xai-oauth" | "xiaomi" | "xiaomi-token-plan-ams" | "xiaomi-token-plan-cn" | "xiaomi-token-plan-sgp" | "yolo-auto" | "zai" | "zai-coding-plan" | "zenmux" | "zhipu-coding-plan";
@@ -0,0 +1,6 @@
1
+ import type { Model } from "../types.js";
2
+ /**
3
+ * Capability is rule-owned; callers must opt in. Either explicit false vetoes
4
+ * the other preference, including a per-request true for a disabled model.
5
+ */
6
+ export declare function resolveResponsesWebSocketPreference(model: Model, requestPreference?: boolean): boolean;
@@ -729,6 +729,12 @@ export interface RequestPolicy {
729
729
  /** Default `tool_choice` to `auto` when the request carries tools and the caller picks none. */
730
730
  responsesToolChoiceAuto?: boolean;
731
731
  googleThinking?: "level" | "level-medium";
732
+ /** Send no `temperature`, `topP` or `topK` in `generationConfig`. */
733
+ googleOmitSampling?: boolean;
734
+ /** Send `generationConfig.maxOutputTokens` as the model's output maximum. */
735
+ googlePinMaxOutputTokens?: boolean;
736
+ /** Replay the model's own turns as the native Gemini content it streamed. */
737
+ googleNativeReplay?: boolean;
732
738
  /** The route locks its upstream for the session (`x-provider-routing-source: session_lock`). */
733
739
  routingSessionLock?: boolean;
734
740
  }
@@ -1297,6 +1297,21 @@ export interface DevinPlanInfo extends ProtoMessage {
1297
1297
  accountDisplayName: string;
1298
1298
  }
1299
1299
  export declare const DevinPlanInfoSchema: MessageCodec<DevinPlanInfo>;
1300
+ /** Devin message exa.seat_management_pb.ExchangePKCEAuthorizationCodeRequest. */
1301
+ export interface ExchangePKCEAuthorizationCodeRequest extends ProtoMessage {
1302
+ authorizationCode: string;
1303
+ codeVerifier: string;
1304
+ }
1305
+ export declare const ExchangePKCEAuthorizationCodeRequestSchema: MessageCodec<ExchangePKCEAuthorizationCodeRequest>;
1306
+ /** Devin message exa.seat_management_pb.ExchangePKCEAuthorizationCodeResponse. */
1307
+ export interface ExchangePKCEAuthorizationCodeResponse extends ProtoMessage {
1308
+ apiKey: string;
1309
+ name: string;
1310
+ apiServerUrl: string;
1311
+ devinWebappHost: string;
1312
+ devinApiUrl: string;
1313
+ }
1314
+ export declare const ExchangePKCEAuthorizationCodeResponseSchema: MessageCodec<ExchangePKCEAuthorizationCodeResponse>;
1300
1315
  /** Devin message exa.codeium_common_pb.ExperimentConfig. */
1301
1316
  export interface ExperimentConfig extends ProtoMessage {
1302
1317
  experiments: ExperimentWithVariant[];
@@ -110,6 +110,8 @@ export interface ModelResolutionResult<TApi extends Api = Api> {
110
110
  stale: boolean;
111
111
  source: ModelResolutionSource;
112
112
  updatedAt?: number;
113
+ /** Why the provider's endpoint fetcher threw this call; the models then come from cache, models.dev or bundled data. */
114
+ fetchError?: string;
113
115
  }
114
116
  /**
115
117
  * Stateful facade over provider model resolution.
@@ -493,6 +493,14 @@ export interface AnthropicCompat {
493
493
  * Sonnet 4.6+, Fable/Mythos 5+ on supported hosts. Default: false.
494
494
  */
495
495
  supportsServerCompaction?: boolean;
496
+ /**
497
+ * Whether the model supports message threads (`message-threads-2026-08-12`):
498
+ * later turns continue a server-held conversation and send only new
499
+ * messages. Enabled on Claude 4.5+ for the first-party provider; the
500
+ * transport still requires the official endpoint unless the caller opts in.
501
+ * Default: false.
502
+ */
503
+ supportsMessageThreads?: boolean;
496
504
  /**
497
505
  * Whether the model is served by the first-party Anthropic provider (its
498
506
  * default route is the official API). Rule-owned on the provider; the
@@ -955,6 +963,14 @@ export interface ResolvedOpenAIResponsesCompat extends ResolvedOpenAISharedCompa
955
963
  * `PI_MUSE_STORE_RESPONSES`); stored runs retain prompts and outputs on the provider.
956
964
  */
957
965
  storeResponses: boolean;
966
+ /**
967
+ * Prefix the `openai-responses` handler puts on every function-tool name it
968
+ * declares or replays, and strips from returned calls through the request's
969
+ * wire-name table. Rule-owned: hosts that reject requests declaring certain
970
+ * exact tool names (Muse Code). Unset sends names unchanged. Other
971
+ * Responses-family handlers do not read it.
972
+ */
973
+ toolNamePrefix?: string;
958
974
  /**
959
975
  * Whether the host binds native history items (`encrypted_content`, item
960
976
  * ids) to the connection that issued them, so a new process must rebuild
@@ -1466,7 +1482,7 @@ export interface Model<TApi extends Api = Api> {
1466
1482
  * dispatch is redirected.
1467
1483
  */
1468
1484
  transport?: "pi-native";
1469
- /** Hint that websocket transport should be preferred when supported by the provider implementation. */
1485
+ /** Standard Responses is opt-in and catalog-gated; either model/request false vetoes true. Codex keeps its independent policy. */
1470
1486
  preferWebsockets?: boolean;
1471
1487
  /** Codex Responses Lite transport: send the lite marker and carry instructions/tools as input items (mirrors codex-rs `use_responses_lite`). */
1472
1488
  useResponsesLite?: boolean;
@@ -46,7 +46,6 @@ export declare const OPENAI_HEADERS: {
46
46
  readonly ROUTING_HINT: "x-codex-routing-hint";
47
47
  };
48
48
  export declare const OPENAI_HEADER_VALUES: {
49
- readonly BETA_RESPONSES: "responses=experimental";
50
49
  readonly BETA_RESPONSES_WEBSOCKETS_V2: "responses_websockets=2026-02-06";
51
50
  readonly REMOTE_COMPACTION_V2: "remote_compaction_v2";
52
51
  readonly ORIGINATOR_CODEX: "omp";
@@ -3,7 +3,7 @@
3
3
  * native request corpus with `packages/ai/scripts/capture-factory-droid-native.ts`
4
4
  * against the matching CLI binary and make `factory-droid-native-parity.test.ts` pass.
5
5
  */
6
- export declare const FACTORY_DROID_CLIENT_VERSION = "0.237.0";
6
+ export declare const FACTORY_DROID_CLIENT_VERSION = "1.1.0";
7
7
  /** Wire protocols the Factory proxy multiplexes; `api-routes provider="factory-droid"` picks one per model. */
8
8
  export declare const FACTORY_DROID_WIRES: readonly ["openai-completions", "openai-responses", "anthropic-messages", "google-generate"];
9
9
  /** Wire protocol used by the Factory proxy for each model. */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@oh-my-pi/pi-catalog",
3
- "version": "18.16.0",
3
+ "version": "18.18.0",
4
4
  "description": "Model catalog for omp: bundled model database, provider discovery descriptors, model identity, classification, and equivalence",
5
5
  "keywords": [
6
6
  "ai",
@@ -78,7 +78,7 @@
78
78
  },
79
79
  "scripts": {
80
80
  "check": "oxlint . && oxfmt --check --no-error-on-unmatched-pattern 'src/**/*.{ts,tsx}' '{test,bench,examples,scripts}/**/*.ts' '*.ts' && bun run check:types",
81
- "check:types": "tsgo -p tsconfig.json --noEmit",
81
+ "check:types": "bun check --no-script -p tsconfig.json",
82
82
  "lint": "oxlint .",
83
83
  "test": "bun test --parallel",
84
84
  "fix": "oxlint --fix --fix-suggestions . && bun run fmt",
@@ -88,12 +88,12 @@
88
88
  "gen:proto": "bun scripts/generate-protocols.ts"
89
89
  },
90
90
  "dependencies": {
91
- "@oh-my-pi/omptype": "18.16.0",
92
- "@oh-my-pi/pi-utils": "18.16.0"
91
+ "@oh-my-pi/omptype": "18.18.0",
92
+ "@oh-my-pi/pi-utils": "18.18.0"
93
93
  },
94
94
  "devDependencies": {
95
95
  "@bgotink/kdl": "0.4.0",
96
- "@oh-my-pi/pi-ai": "18.16.0",
96
+ "@oh-my-pi/pi-ai": "18.18.0",
97
97
  "@types/bun": "^1.3.14"
98
98
  },
99
99
  "engines": {
@@ -25,6 +25,8 @@ export type AuthProviderId =
25
25
  | "deepinfra"
26
26
  | "deepseek"
27
27
  | "devin"
28
+ | "devin-cli"
29
+ | "devin-windsurf"
28
30
  | "exa"
29
31
  | "factory-droid"
30
32
  | "firepass"
@@ -123,6 +125,8 @@ export type LoginProviderId =
123
125
  | "deepinfra"
124
126
  | "deepseek"
125
127
  | "devin"
128
+ | "devin-cli"
129
+ | "devin-windsurf"
126
130
  | "exa"
127
131
  | "factory-droid"
128
132
  | "firepass"
@@ -126,6 +126,9 @@ export const AXES: Readonly<Record<string, AxisDef>> = {
126
126
  "responses-tool-choice-auto": wire("responsesToolChoiceAuto", ["request"]),
127
127
  "routing-session-lock": wire("routingSessionLock", ["request"]),
128
128
  "google-thinking": wire("googleThinking", ["request"], "scalar", ["level", "level-medium"]),
129
+ "google-omit-sampling": wire("googleOmitSampling", ["request"]),
130
+ "google-pin-max-output-tokens": wire("googlePinMaxOutputTokens", ["request"]),
131
+ "google-native-replay": wire("googleNativeReplay", ["request"]),
129
132
  // ── wire: OpenAI-compatible surfaces (chat completions + Responses) ──
130
133
  "allows-synthetic-reasoning-content-for-tool-calls": wire("allowsSyntheticReasoningContentForToolCalls", OAI),
131
134
  "always-send-max-tokens": wire("alwaysSendMaxTokens", OAI),
@@ -207,6 +210,7 @@ export const AXES: Readonly<Record<string, AxisDef>> = {
207
210
  "supports-reasoning-params": wire("supportsReasoningParams", OAI),
208
211
  "supports-reasoning-summary": wire("supportsReasoningSummary", ["openai-responses"]),
209
212
  "store-responses": wire("storeResponses", ["openai-responses"]),
213
+ "tool-name-prefix": wire("toolNamePrefix", ["openai-responses"], "scalar", ["_"]),
210
214
  "supports-store": wire("supportsStore", ["openai"]),
211
215
  "supports-strict-mode": wire("supportsStrictMode", OAI),
212
216
  "supports-tool-choice": wire("supportsToolChoice", OAI),
@@ -271,6 +275,7 @@ export const AXES: Readonly<Record<string, AxisDef>> = {
271
275
  "supports-mid-conversation-tool-changes": wire("supportsMidConversationToolChanges", ["anthropic"]),
272
276
  "supports-per-message-effort": wire("supportsPerMessageEffort", ["anthropic"]),
273
277
  "supports-server-compaction": wire("supportsServerCompaction", ["anthropic", "bedrock"]),
278
+ "supports-message-threads": wire("supportsMessageThreads", ["anthropic"]),
274
279
  "supports-between-tools-thinking": wire("supportsBetweenToolsThinking", ["anthropic"]),
275
280
  "supports-thinking-binding-controls": wire("supportsThinkingBindingControls", ["anthropic", "bedrock"]),
276
281
  "supports-turn-scoped-system": wire("supportsTurnScopedSystem", ["anthropic"]),
@@ -339,6 +344,7 @@ export const AXES: Readonly<Record<string, AxisDef>> = {
339
344
  "thinking-unverified": { key: "unverified", set: "thinking", shape: "scalar" },
340
345
 
341
346
  // ── catalog metadata ──
347
+ "supports-websockets": { key: "supportsWebsockets", set: "catalog", shape: "scalar", values: [true, false] },
342
348
  "apply-patch-tool-type": {
343
349
  key: "applyPatchToolType",
344
350
  set: "catalog",
@@ -870,6 +870,7 @@ function pickResponsesOnly(compat: ResolvedOpenAIResponsesCompat): ResponsesOnly
870
870
  supportsImageDetailOriginal: compat.supportsImageDetailOriginal,
871
871
  supportsObfuscationOptOut: compat.supportsObfuscationOptOut,
872
872
  storeResponses: compat.storeResponses,
873
+ toolNamePrefix: compat.toolNamePrefix,
873
874
  connectionBoundNativeHistory: compat.connectionBoundNativeHistory,
874
875
  supportsAllTurnsReasoningContext: compat.supportsAllTurnsReasoningContext,
875
876
  supportsConfigurationUpdate: compat.supportsConfigurationUpdate,
@@ -903,6 +904,7 @@ function resolveAnthropicPolicy(
903
904
  signingEndpoint,
904
905
  supportsContextManagement: true,
905
906
  supportsServerCompaction: false,
907
+ supportsMessageThreads: false,
906
908
  firstPartyProvider: false,
907
909
  honorsClaudeCodeBetaKillSwitch: false,
908
910
  supportsOutputEffort: true,
@@ -0,0 +1,12 @@
1
+ import type { Model } from "../types";
2
+ import { resolveCatalogPolicy } from "./catalog-policy";
3
+
4
+ /**
5
+ * Capability is rule-owned; callers must opt in. Either explicit false vetoes
6
+ * the other preference, including a per-request true for a disabled model.
7
+ */
8
+ export function resolveResponsesWebSocketPreference(model: Model, requestPreference?: boolean): boolean {
9
+ if (resolveCatalogPolicy(model).supportsWebsockets !== true) return false;
10
+ if (requestPreference === false || model.preferWebsockets === false) return false;
11
+ return requestPreference === true || model.preferWebsockets === true;
12
+ }
@@ -2,7 +2,7 @@
2
2
  // (and does not set `show-in-login-list #false`) must appear here; providers
3
3
  // without a login flow sort alphabetically after this list.
4
4
  login-order "openai-codex" "anthropic" "zai" "zai-coding-plan" "kimi-code" "openrouter" "github-copilot" \
5
- "cursor" "devin" "google-antigravity" "google-gemini-cli" "openai-codex-device" "xai" "xai-oauth" \
5
+ "cursor" "devin" "devin-cli" "devin-windsurf" "google-antigravity" "google-gemini-cli" "openai-codex-device" "xai" "xai-oauth" \
6
6
  "gitlab-duo" "gitlab-duo-agent" "alibaba-coding-plan" "alibaba-token-plan" "aiand" "abliteration" "zhipu-coding-plan" \
7
7
  "umans" "qwen-portal" "sakana" "sambanova" "minimax-code" "minimax-code-cn" "xiaomi" "xiaomi-token-plan-sgp" \
8
8
  "xiaomi-token-plan-ams" "xiaomi-token-plan-cn" "firepass" "cline-pass" "factory-droid" "commandcode" "charm-hyper" "deepseek" "stepfun" "muse-code" "meta" "moonshot" "inception" \
@@ -0,0 +1,6 @@
1
+ auth "devin-cli" {
2
+ name "Devin (adopt CLI credentials)"
3
+ login "custom" hook="devin-cli"
4
+ refresh "none"
5
+ store-as "devin"
6
+ }
@@ -0,0 +1,6 @@
1
+ auth "devin-windsurf" {
2
+ name "Devin (Windsurf Enterprise)"
3
+ login "custom" hook="devin-windsurf"
4
+ refresh "none"
5
+ store-as "devin"
6
+ }
@@ -209,6 +209,22 @@ class "anthropic" {
209
209
  stops-output-at-context-window #true
210
210
  }
211
211
  }
212
+ // Message threads (`message-threads-2026-08-12`) keep the conversation on
213
+ // the server so later turns send only new messages. Claude 4.5 and newer
214
+ // support them on the Claude API; the transport checks the effective URL
215
+ // per request because `ANTHROPIC_BASE_URL` / Foundry reroutes leave this
216
+ // flag stale. Vertex and Bedrock do not support them.
217
+ // https://platform.claude.com/docs/en/build-with-claude/message-threads
218
+ on "anthropic" {
219
+ on-api "anthropic-messages" {
220
+ revision ">=4.5" {
221
+ supports-message-threads #true
222
+ }
223
+ models "claude-mythos-preview" {
224
+ supports-message-threads #true
225
+ }
226
+ }
227
+ }
212
228
  // Opus 5.5 rejects forced tool selection the way Fable/Mythos do — a
213
229
  // `tool_choice` of `tool` or `any` fails the request with 400
214
230
  // `invalid_request_error`: `tool_choice: type "tool" and "any" are not
@@ -279,6 +279,12 @@ provider "factory-droid" {
279
279
  cost input=0 output=0 cache-read=0 cache-write=0
280
280
  limits context=1000000 max-tokens=65536
281
281
  }
282
+ model "gemini-4-argon" name="Gemini 4 Argon" {
283
+ reasoning #true
284
+ input "text" "image"
285
+ cost input=0 output=0 cache-read=0 cache-write=0
286
+ limits context=934464 max-tokens=65536
287
+ }
282
288
  model "gemini-3.1-pro-preview" name="Gemini 3.1 Pro" {
283
289
  reasoning #true
284
290
  input "text" "image"
@@ -393,6 +399,12 @@ provider "factory-droid" {
393
399
  cost input=0 output=0 cache-read=0 cache-write=0
394
400
  limits context=908928 max-tokens=131072
395
401
  }
402
+ model "muse-spark-1.3" name="Muse Spark 1.3" {
403
+ reasoning #true
404
+ input "text"
405
+ cost input=0 output=0 cache-read=0 cache-write=0
406
+ limits context=908928 max-tokens=131072
407
+ }
396
408
  model "beam-1.0" name="Beam 1.0" {
397
409
  reasoning #true
398
410
  input "text"
@@ -937,6 +949,18 @@ provider "factory-droid" {
937
949
  thinking-default-level "high"
938
950
  entitlement { feature-flag "garnet_0715" }
939
951
  }
952
+ // Launches Global-only: Factory serves it from neither US nor EU inference.
953
+ models "gemini-4-argon" {
954
+ routing-family "google"
955
+ upstream-rotation "google"
956
+ region-upstreams-us
957
+ credit-rates { input 1.6; output 5; cache-read 0.05 }
958
+ list-price-from "google"
959
+ thinking-efforts "low" "medium" "high"
960
+ thinking-requires-effort #true
961
+ thinking-default-level "medium"
962
+ entitlement { feature-flag "gemini_4_argon" }
963
+ }
940
964
  models "gemini-3.1-pro-preview" {
941
965
  routing-family "google"
942
966
  upstream-rotation "google"
@@ -1171,6 +1195,19 @@ provider "factory-droid" {
1171
1195
  thinking-requires-effort #true
1172
1196
  thinking-default-level "high"
1173
1197
  }
1198
+ // Vertex Model Garden serves 1.3 on its global endpoint only and rejects the
1199
+ // `none` and `max` tiers; the ladder outranks the Meta class ladder as 1.2's does.
1200
+ models "muse-spark-1.3" priority=1 {
1201
+ routing-family "factory"
1202
+ upstream-rotation "google"
1203
+ region-upstreams-us
1204
+ credit-rates { input 0.5; output 3.4; cache-read 0.12 }
1205
+ list-price-from "meta"
1206
+ thinking-efforts "low" "medium" "high" "xhigh"
1207
+ thinking-requires-effort #true
1208
+ thinking-default-level "high"
1209
+ entitlement { feature-flag "muse_spark_1_3" }
1210
+ }
1174
1211
  models "beam-1.0" {
1175
1212
  routing-family "factory"
1176
1213
  upstream-rotation "baseten"
@@ -1448,9 +1485,9 @@ provider "factory-droid" {
1448
1485
  server-side-fallback-models "claude-opus-5"
1449
1486
  }
1450
1487
  }
1451
- // With tools, Anthropic and Vertex stream tool input eagerly and advertise
1452
- // fine-grained tool streaming; Bedrock takes the beta alone.
1453
- on-upstream "anthropic" "vertex_anthropic" {
1488
+ // With tools, Anthropic, Vertex and Azure Foundry stream tool input eagerly
1489
+ // and advertise fine-grained tool streaming; Bedrock takes the beta alone.
1490
+ on-upstream "anthropic" "vertex_anthropic" "azure_anthropic" {
1454
1491
  supports-eager-tool-input-streaming #true
1455
1492
  anthropic-tool-streaming-beta #true
1456
1493
  }
@@ -1515,12 +1552,27 @@ provider "factory-droid" {
1515
1552
  models "grok-*" {
1516
1553
  supports-reasoning-summary #false
1517
1554
  }
1555
+ // Muse Spark 1.3 rides Responses through Vertex. Native asks for encrypted
1556
+ // reasoning but never replays it: Factory-served models fall outside the
1557
+ // reasoning it carries across Responses turns. It requests the model's full
1558
+ // output cap, above the generic Responses clamp.
1559
+ models "muse-spark-1.3" {
1560
+ filter-reasoning-history #true
1561
+ clamp-output-to-model-max #true
1562
+ }
1518
1563
  models "gemini-*" "garnet-07-15" {
1519
1564
  omit-max-output-tokens #true
1520
1565
  google-thinking "level"
1521
1566
  }
1522
- models "gemini-3.1-pro-preview" "gemini-3.7-flash" "gemini-3.8-flash" {
1567
+ models "gemini-4-argon" "gemini-3.1-pro-preview" "gemini-3.7-flash" "gemini-3.8-flash" {
1523
1568
  google-thinking "level-medium"
1524
1569
  }
1570
+ // Argon's request policy: no sampling parameters, the output cap pinned
1571
+ // to the model maximum, and its own model turns replayed as Gemini sent them.
1572
+ models "gemini-4-argon" {
1573
+ google-omit-sampling #true
1574
+ google-pin-max-output-tokens #true
1575
+ google-native-replay #true
1576
+ }
1525
1577
  // FACTORY_API_KEY is a control-plane key, not a subscription proxy token.
1526
1578
  }
@@ -67,7 +67,23 @@ provider "muse-code" {
67
67
  // `custom` tools are rejected with 400 "`custom` tools are not supported
68
68
  // on this endpoint", so apply-patch must stay a function tool here.
69
69
  edit-prompt-variant "compact"
70
+ // A Muse Code subscription key answers 403 `client_attestation_denied` when
71
+ // the request declares a tool with certain exact, case-sensitive names:
72
+ // `bash`, `shell`, `web_search`, `web_fetch`, `apply_patch`, `read_file`
73
+ // and `update_plan` (measured 2026-10-31, still 2026-11-03; `Bash`,
74
+ // `run_shell`, `local_shell` and omp's other built-in names pass, and the
75
+ // list is not exhaustive). Only declared names count: a replayed `bash`
76
+ // call in history is accepted. Prefixing every function tool with `_` was
77
+ // accepted with all of omp's built-in tools declared. Meta pay-as-you-go
78
+ // keys are not attested and keep plain names.
79
+ tool-name-prefix "_"
70
80
  on-api "openai-responses" {
81
+ // api.meta.ai answers 400 "name must be at most 64 characters" for a longer
82
+ // tool name (#9130), and omp caps MCP names at exactly 64 for it. Scoped by
83
+ // provider and API so it outranks the 128 Responses default in
84
+ // tool-call-names.kdl. A name the `_` prefix would push past it goes out
85
+ // unprefixed.
86
+ tool-call-name-max-length 64
71
87
  // Spark 1.3 Contributor warmed siblings hit 10/10 vs 0/10 with per-child keys (2026-10-12).
72
88
  // Meta documents shared-prefix prompt_cache_key routing; keep the opt-in on these exact Muse Code IDs.
73
89
  models "muse-spark-1.3" "muse-spark-1.3-contributor" "muse-wonder-1.0" "muse-wonder-1.0-contributor" "muse-wonder-full-1.0" "muse-wonder-full-1.0-contributor" {
@@ -4,6 +4,9 @@ provider "openai" {
4
4
  default-model "gpt-5.5"
5
5
  env "OPENAI_API_KEY"
6
6
  image-count-budget 200
7
+ on-api "openai-responses" {
8
+ supports-websockets #true
9
+ }
7
10
  kind-apis {
8
11
  embedding "openai-embeddings"
9
12
  image "openai-responses"
@@ -48,6 +48,13 @@ provider "web" {
48
48
  limits
49
49
  supports-tools #false
50
50
  }
51
+ model "keenable" name="Keenable" {
52
+ reasoning #false
53
+ input "text"
54
+ cost input=0 output=0 cache-read=0 cache-write=0
55
+ limits
56
+ supports-tools #false
57
+ }
51
58
  model "jina" name="Jina" {
52
59
  reasoning #false
53
60
  input "text"
@@ -109,10 +109,10 @@ behavior {
109
109
  "claude-sonnet-4-6" "claude-sonnet-4-5-20250929" "claude-haiku-5-5" "claude-haiku-4-5-20251001" "gpt-6-astra" \
110
110
  "gpt-6.1-sol" "gpt-6-sol" "gpt-6-luna" "gpt-5.6-sol" "gpt-5.6-sol-fast" "gpt-5.6-terra" \
111
111
  "gpt-6-astra-ultrafast" "gpt-6.1-sol-ultrafast" "gpt-6.1-terra" "gpt-6-sol-fast" "gpt-6-luna-fast" \
112
- "muse-spark-open" "muse-spark-1.2" \
112
+ "muse-spark-open" "muse-spark-1.2" "muse-spark-1.3" \
113
113
  "gpt-5.6-luna" "gpt-5.5" "gpt-5.5-fast" "gpt-5.5-pro" "gpt-5.4" "gpt-5.4-fast" "gpt-5.4-mini" \
114
114
  "gpt-5.4-mini-fast" "gpt-5.3-codex" "gpt-5.3-codex-fast" "gpt-5.2" "garnet-07-15" \
115
- "gemini-3.1-pro-preview" "gemini-3.8-flash" "gemini-3.7-flash" "gemini-3.6-flash" \
115
+ "gemini-4-argon" "gemini-3.1-pro-preview" "gemini-3.8-flash" "gemini-3.7-flash" "gemini-3.6-flash" \
116
116
  "gemini-3.5-flash" "gemini-3-flash-preview" "grok-4.7" "grok-4.6" "grok-4.5" "atlas-07-21" \
117
117
  "aster-07-15" "gpt-image-2.5-sunburst" "gpt-image-2.5-flare" "gemini-3-pro-image-preview"
118
118
  }
@@ -316,13 +316,13 @@ behavior {
316
316
  exact="minimax-m2.7"
317
317
  route "openai-responses" exact="gpt-6-astra" exact="gpt-6.1-sol" exact="gpt-6-sol" exact="gpt-6-luna" \
318
318
  exact="gpt-6-astra-ultrafast" exact="gpt-6.1-sol-ultrafast" exact="gpt-6.1-terra" exact="gpt-6-sol-fast" \
319
- exact="gpt-6-luna-fast" \
319
+ exact="gpt-6-luna-fast" exact="muse-spark-1.3" \
320
320
  exact="gpt-5.6-sol" exact="gpt-5.6-sol-fast" exact="gpt-5.6-terra" exact="gpt-5.6-luna" \
321
321
  exact="gpt-5.5" exact="gpt-5.5-fast" exact="gpt-5.5-pro" exact="gpt-5.4" exact="gpt-5.4-fast" \
322
322
  exact="gpt-5.4-mini" exact="gpt-5.4-mini-fast" exact="gpt-5.3-codex" exact="gpt-5.3-codex-fast" \
323
323
  exact="gpt-5.2" exact="grok-4.7" exact="grok-4.6" exact="grok-4.5" exact="gpt-image-2.5-sunburst" \
324
324
  exact="gpt-image-2.5-flare"
325
- route "google-generate" exact="garnet-07-15" exact="gemini-3.1-pro-preview" exact="gemini-3.8-flash" \
325
+ route "google-generate" exact="garnet-07-15" exact="gemini-4-argon" exact="gemini-3.1-pro-preview" exact="gemini-3.8-flash" \
326
326
  exact="gemini-3.7-flash" exact="gemini-3.6-flash" exact="gemini-3.5-flash" \
327
327
  exact="gemini-3-flash-preview" exact="gemini-3-pro-image-preview"
328
328
  route "openai-completions" exact="inkling" exact="mistral-large-4" exact="mistral-medium-3.5" exact="glm-5.3-flash" \