@linxiraos/pi-catalog 1.3.2 → 1.4.1

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 (50) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/dist/types/compat/auth-ids.d.ts +2 -2
  3. package/dist/types/compat/image-tokenization.d.ts +13 -1
  4. package/dist/types/compat/prompt-cache-persistent.d.ts +7 -0
  5. package/dist/types/compat/provider-ids.d.ts +1 -1
  6. package/dist/types/compat/request-size.d.ts +11 -6
  7. package/dist/types/discovery/devin.d.ts +1 -1
  8. package/dist/types/hosts.d.ts +3 -1
  9. package/dist/types/provider-models/openai-compat.d.ts +9 -2
  10. package/dist/types/types.d.ts +10 -3
  11. package/dist/types/wire/codex.d.ts +4 -2
  12. package/dist/types/wire/devin.d.ts +1 -15
  13. package/package.json +4 -4
  14. package/src/compat/auth-ids.ts +2 -0
  15. package/src/compat/axes.ts +25 -2
  16. package/src/compat/image-tokenization.ts +55 -1
  17. package/src/compat/prompt-cache-persistent.ts +12 -0
  18. package/src/compat/provider-ids.d.ts +1 -1
  19. package/src/compat/provider-ids.ts +1 -0
  20. package/src/compat/request-size.ts +18 -8
  21. package/src/compat/resolve.ts +1 -0
  22. package/src/compat/rules/README.md +8 -2
  23. package/src/compat/rules/auth/_order.kdl +1 -1
  24. package/src/compat/rules/auth/inception.kdl +11 -0
  25. package/src/compat/rules/classes/anthropic.kdl +23 -21
  26. package/src/compat/rules/classes/deepseek.kdl +31 -0
  27. package/src/compat/rules/classes/gemma.kdl +11 -0
  28. package/src/compat/rules/classes/minimax.kdl +13 -8
  29. package/src/compat/rules/providers/amazon-bedrock.kdl +56 -0
  30. package/src/compat/rules/providers/factory-droid.kdl +12 -0
  31. package/src/compat/rules/providers/inception.kdl +61 -0
  32. package/src/compat/rules/providers/moonshot.kdl +3 -3
  33. package/src/compat/rules/providers/openai-codex.kdl +3 -0
  34. package/src/compat/rules/providers/yolo-auto.kdl +33 -37
  35. package/src/compat/rules/taxonomy/qwen.kdl +1 -1
  36. package/src/compat/rules.json +1 -1
  37. package/src/discovery/devin.d.ts +1 -1
  38. package/src/discovery/devin.ts +33 -66
  39. package/src/hosts.d.ts +3 -1
  40. package/src/hosts.ts +5 -2
  41. package/src/models.json +1 -1
  42. package/src/provider-models/descriptors.ts +2 -0
  43. package/src/provider-models/openai-compat.d.ts +9 -2
  44. package/src/provider-models/openai-compat.ts +47 -5
  45. package/src/types.d.ts +10 -3
  46. package/src/types.ts +10 -3
  47. package/src/wire/codex.d.ts +4 -2
  48. package/src/wire/codex.ts +11 -3
  49. package/src/wire/devin.d.ts +1 -15
  50. package/src/wire/devin.ts +16 -20
package/CHANGELOG.md CHANGED
@@ -1,5 +1,13 @@
1
1
  ## [Unreleased]
2
2
 
3
+ ## [1.4.1] - 2026-10-23
4
+
5
+ - Version alignment with the 1.4.1 release line (no behavioral changes).
6
+
7
+ ## [1.4.0] - 2026-10-21
8
+
9
+ - Version line moves to 1.4.0 with the rest of the suite; no user-visible change in this package.
10
+
3
11
  ## [1.3.2] - 2026-10-19
4
12
 
5
13
  - Version line moves to 1.3.2 with the rest of the suite; no user-visible change in this package.
@@ -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" | "kagi" | "kilo" | "kimi-code" | "litellm" | "llama.cpp" | "lm-studio" | "local" | "meta" | "minimax" | "minimax-code" | "minimax-code-cn" | "mistral" | "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" | "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" | "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" | "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" | "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" | "kagi" | "kilo" | "kimi-code" | "litellm" | "llama.cpp" | "lm-studio" | "meta" | "minimax-code" | "minimax-code-cn" | "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" | "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" | "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" | "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" | "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";
@@ -22,6 +22,18 @@ export interface OpenAiPatchTokenization {
22
22
  /** The level `auto` (and an omitted `detail`) sizes like. */
23
23
  auto: "high" | "original";
24
24
  }
25
+ /** DeepSeek ViT patches merged `downsample`² into one token, plus a newline per row and two delimiters. */
26
+ export interface DeepSeekPatchTokenization {
27
+ regime: "deepseek-patch";
28
+ /** ViT patch edge in pixels. */
29
+ patchSize: number;
30
+ /** Patches merged per token along each axis. */
31
+ downsample: number;
32
+ /** Token budget per image, layout tokens included. */
33
+ maxTokens: number;
34
+ /** Smaller images are upscaled to this pixel area. */
35
+ minPixels: number;
36
+ }
25
37
  /** One model line's image billing rule: the vendor formula and its per-model numbers. */
26
38
  export type ImageTokenization = (OpenAiPatchTokenization
27
39
  /** Anthropic 28px patches, resized to fit a padded-edge limit and a visual-token budget. */
@@ -29,7 +41,7 @@ export type ImageTokenization = (OpenAiPatchTokenization
29
41
  regime: "anthropic-patch";
30
42
  maxEdge: number;
31
43
  maxTokens: number;
32
- }
44
+ } | DeepSeekPatchTokenization
33
45
  /** A fixed per-image budget regardless of pixels (Gemini 3 `media_resolution`). */
34
46
  | {
35
47
  regime: "fixed";
@@ -0,0 +1,7 @@
1
+ import type { Model } from "../types.js";
2
+ /**
3
+ * Whether {@link model}'s prompt-cache entries never expire
4
+ * (`prompt-cache-persistent` axis). Only the provider's own endpoint
5
+ * qualifies: a gateway or proxy reusing the provider id makes no such promise.
6
+ */
7
+ export declare function isPromptCachePersistent(model: Model): boolean;
@@ -1,2 +1,2 @@
1
1
  /** Every chat-model provider with a catalog entry (`default-model` in its provider rules). */
2
- export type KnownProvider = "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" | "factory-droid" | "firepass" | "fireworks" | "github-copilot" | "gitlab-duo" | "gitlab-duo-agent" | "gmi-cloud" | "google" | "google-antigravity" | "google-gemini-cli" | "google-vertex" | "groq" | "helmcode" | "huggingface" | "kilo" | "kimi-code" | "litellm" | "lm-studio" | "local" | "meta" | "minimax" | "minimax-code" | "minimax-code-cn" | "mistral" | "moonshot" | "muse-code" | "nanogpt" | "novita" | "nvidia" | "ollama" | "ollama-cloud" | "openai" | "openai-codex" | "opencode-go" | "opencode-zen" | "openrouter" | "qianfan" | "qwen-portal" | "sakana" | "sambanova" | "siliconflow" | "siliconflow-cn" | "singularityapi-dev" | "singularityapi-tech" | "snowflake" | "stepfun" | "synthetic" | "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" | "zenmux" | "zhipu-coding-plan";
2
+ export type KnownProvider = "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" | "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" | "kilo" | "kimi-code" | "litellm" | "lm-studio" | "local" | "meta" | "minimax" | "minimax-code" | "minimax-code-cn" | "mistral" | "moonshot" | "muse-code" | "nanogpt" | "novita" | "nvidia" | "ollama" | "ollama-cloud" | "openai" | "openai-codex" | "opencode-go" | "opencode-zen" | "openrouter" | "qianfan" | "qwen-portal" | "sakana" | "sambanova" | "siliconflow" | "siliconflow-cn" | "singularityapi-dev" | "singularityapi-tech" | "snowflake" | "stepfun" | "synthetic" | "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" | "zenmux" | "zhipu-coding-plan";
@@ -2,15 +2,20 @@ import type { Model } from "../types.js";
2
2
  /**
3
3
  * Maximum encoded inline-image bytes retained per request for a deployment with a documented body-size limit.
4
4
  * The axis is a host contract: a rerouted endpoint (proxy, gateway) imposes its own limit, so the budget applies
5
- * only when `officialEndpoint` says the request reaches the model's official endpoint. `compat.officialEndpoint`
6
- * classifies only the configured `baseUrl`; pi-ai's `reachesOfficialEndpoint` also follows request-time reroutes.
5
+ * only when `budgetedHost` says the request reaches the host the rules describe: pi-ai's `reachesBudgetedHost`
6
+ * (the model's official endpoint, following request-time reroutes, or Factory's hosted API for a Factory Droid model).
7
7
  */
8
- export declare function resolveInlineImageByteBudget(model: Model, officialEndpoint: boolean): number | undefined;
8
+ export declare function resolveInlineImageByteBudget(model: Model, budgetedHost: boolean): number | undefined;
9
+ /**
10
+ * Largest request body the deployment accepts (`request-body-byte-limit`), or `undefined` when no rule names it.
11
+ * Same gate as {@link resolveInlineImageByteBudget}.
12
+ */
13
+ export declare function resolveRequestBodyByteLimit(model: Model, budgetedHost: boolean): number | undefined;
9
14
  /**
10
15
  * Most images one request to this deployment may carry, or `undefined` when no rule names the host. A configured
11
16
  * `model.imageCountBudget` wins: the user knows the host behind a custom gateway. Otherwise the
12
- * `official-image-count-budget` axis replaces `image-count-budget` only when `officialEndpoint` says the request
13
- * reaches the model's official endpoint (see {@link resolveInlineImageByteBudget}); a rerouted endpoint keeps the
17
+ * `official-image-count-budget` axis replaces `image-count-budget` only when `budgetedHost` says the request
18
+ * reaches the host the rules describe (see {@link resolveInlineImageByteBudget}); a rerouted endpoint keeps the
14
19
  * provider's generic budget.
15
20
  */
16
- export declare function resolveImageCountBudget(model: Model, officialEndpoint: boolean): number | undefined;
21
+ export declare function resolveImageCountBudget(model: Model, budgetedHost: boolean): number | undefined;
@@ -3,7 +3,7 @@ import type { FetchImpl, ModelSpec } from "../types.js";
3
3
  * Options for fetching dynamic Devin (Codeium Cascade) models from `GetCliModelConfigs`.
4
4
  */
5
5
  export interface DevinModelDiscoveryOptions {
6
- /** Codeium session token carried inside protobuf `Metadata.apiKey`. */
6
+ /** Stored Devin credential; encoded into protobuf `Metadata.apiKey` by shape. */
7
7
  apiKey?: string;
8
8
  /** Optional Codeium API base URL override. */
9
9
  baseUrl?: string;
@@ -175,11 +175,13 @@ export declare function isAzureDeploymentsUrl(baseUrl: string): boolean;
175
175
  * - `anthropic`: the Anthropic Messages API under `/anthropic`.
176
176
  * - `openai`: the OpenAI-compatible APIs under `/openai`, plus Mantle's
177
177
  * documented `/v1` base (`https://bedrock-mantle.<region>.api.aws/v1`).
178
+ * - `runtime`: the bedrock-runtime origin itself, where Converse and
179
+ * InvokeModel live under `/model/<id>/…`.
178
180
  *
179
181
  * Hostnames are parsed strictly so proxies that embed these hosts in a path
180
182
  * do not match.
181
183
  */
182
- export declare function isBedrockRouteUrl(baseUrl: string | undefined, route: "openai" | "anthropic"): boolean;
184
+ export declare function isBedrockRouteUrl(baseUrl: string | undefined, route: "openai" | "anthropic" | "runtime"): boolean;
183
185
  /** Amazon Bedrock's OpenAI-compatible routes; see {@link isBedrockRouteUrl}. */
184
186
  export declare function isBedrockOpenAIUrl(baseUrl: string | undefined): boolean;
185
187
  /** Alibaba DashScope consumer `compatible-mode` endpoint (rejects multimodal arrays for some text-only SKUs). */
@@ -419,6 +419,13 @@ export interface TogetherModelManagerConfig {
419
419
  fetch?: FetchImpl;
420
420
  }
421
421
  export declare function togetherModelManagerOptions(config?: TogetherModelManagerConfig): ModelManagerOptions<"openai-completions">;
422
+ /**
423
+ * Builds Inception's authenticated model-discovery manager. A successful
424
+ * `/v1/models` fetch is the complete roster, keeping only rows that advertise
425
+ * `chat.completions` (the shared roster also lists FIM/edit and Decisions-only
426
+ * models); without an API key the bundled Mercury seeds are served.
427
+ */
428
+ export declare function inceptionModelManagerOptions(config?: ModelManagerConfig): ModelManagerOptions<"openai-completions">;
422
429
  export interface CoreWeaveModelManagerConfig {
423
430
  apiKey?: string;
424
431
  baseUrl?: string;
@@ -468,8 +475,8 @@ export interface YoloAutoModelManagerConfig {
468
475
  fetch?: FetchImpl;
469
476
  }
470
477
  /**
471
- * Yolo-Auto model manager: OpenAI-compatible chat completions at the
472
- * flat-rate `deepseek-flash-v4` endpoint. Live `/v1/models` discovery replaces the
478
+ * Yolo-Auto model manager: flat-rate OpenAI-compatible chat completions
479
+ * (`qwen3.8-27b`, `yolo`, ...). Live `/v1/models` discovery replaces the
473
480
  * bundled seed once a key is stored or present in `YOLO_AUTO_API_KEY`. Models
474
481
  * the provider adds later inherit metadata (reasoning, thinking, context)
475
482
  * from the global bundled reference index, so new ids work without a per-id
@@ -688,8 +688,8 @@ export interface AnthropicCompat {
688
688
  fastMode?: boolean;
689
689
  }
690
690
  /**
691
- * Compatibility settings for Bedrock Converse prompt caching. Cache pricing is
692
- * deliberately not used to infer these request-shape capabilities.
691
+ * Compatibility settings for Bedrock Converse requests and native streaming
692
+ * side-compaction. Cache pricing does not imply these capabilities.
693
693
  */
694
694
  export interface BedrockCompat {
695
695
  /** Explicit disabled-thinking wire form; unset preserves the provider's existing behavior. */
@@ -737,8 +737,13 @@ export interface BedrockCompat {
737
737
  * local prefix-binding safeguards. Default: true.
738
738
  */
739
739
  supportsThinkingBindingControls?: boolean;
740
+ /**
741
+ * Whether the model supports a compaction-only Bedrock Runtime
742
+ * InvokeModelWithResponseStream request. Ordinary turns still use Converse.
743
+ */
744
+ supportsServerCompaction?: boolean;
740
745
  }
741
- /** Fully-resolved Bedrock Converse prompt-cache capabilities, materialized once by `buildModel`. */
746
+ /** Fully-resolved Bedrock Converse and side-compaction capabilities, materialized once by `buildModel`. */
742
747
  export interface ResolvedBedrockCompat {
743
748
  /** See {@link BedrockCompat.disabledThinking}. */
744
749
  disabledThinking?: BedrockCompat["disabledThinking"];
@@ -753,6 +758,8 @@ export interface ResolvedBedrockCompat {
753
758
  supportsForcedToolChoice: boolean;
754
759
  /** See {@link BedrockCompat.supportsThinkingBindingControls}. */
755
760
  supportsThinkingBindingControls: boolean;
761
+ /** See {@link BedrockCompat.supportsServerCompaction}; false unless the Bedrock model-card policy opts in. */
762
+ supportsServerCompaction: boolean;
756
763
  /**
757
764
  * Stream-watchdog idle-timeout fallback in ms for hosts with no keepalive
758
765
  * events; 0 disables the idle watchdog. Undefined defers to
@@ -78,8 +78,10 @@ export declare function getCodexAccountId(accessToken: string): string | undefin
78
78
  * needed: `chatgpt_data_residency` is the authoritative claim, with
79
79
  * `chatgpt_compute_residency` as the fallback for tokens that only carry that.
80
80
  *
81
- * Returns undefined for a non-JWT token, or for the (common) accounts whose
82
- * claims omit residency entirely — those workspaces are not region-pinned.
81
+ * Returns undefined for a non-JWT token, or for the (common) accounts that are
82
+ * not region-pinned: their claims omit residency or carry the
83
+ * {@link CODEX_UNCONSTRAINED_RESIDENCY} sentinel. The backend answers 404 to a
84
+ * declared `no_constraint`, and codex-rs never sends it.
83
85
  */
84
86
  export declare function getCodexResidency(accessToken: string): string | undefined;
85
87
  /**
@@ -6,23 +6,9 @@
6
6
  */
7
7
  /** Base host for Codeium/Windsurf's Cascade API (Connect protocol over HTTP/1.1). */
8
8
  export declare const DEVIN_DEFAULT_BASE_URL = "https://server.codeium.com";
9
- /** Session token as the wire format carries it: the scheme prefix is required. */
10
- export declare function normalizeDevinSessionToken(apiKey: string | undefined): string;
11
- /** Released-CLI metadata with credential bytes already encoded for the wire. */
12
- export declare function devinWireMetadata(apiKey: string | undefined, userJwt?: string): {
13
- ideName: "devin-cli";
14
- ideType: "chisel";
15
- ideVersion: "3000.11.3";
16
- extensionName: "chisel";
17
- extensionVersion: "3000.11.3";
18
- locale: "en";
19
- os: "darwin" | "linux" | "windows";
20
- apiKey: string;
21
- userJwt: string;
22
- };
23
9
  /**
24
10
  * Fields for `Metadata` on released-CLI calls (`GetUserJwt`, `AssignModel`,
25
- * `GetChatMessage`, `GetUserStatus`) authenticated by a Devin session token.
11
+ * `GetChatMessage`, `GetUserStatus`).
26
12
  */
27
13
  export declare function devinCliMetadata(apiKey: string | undefined, userJwt?: string): {
28
14
  ideName: "devin-cli";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@linxiraos/pi-catalog",
3
- "version": "1.3.2",
3
+ "version": "1.4.1",
4
4
  "description": "Model catalog for omp: bundled model database, provider discovery descriptors, model identity, classification, and equivalence",
5
5
  "keywords": [
6
6
  "ai",
@@ -90,12 +90,12 @@
90
90
  "gen:proto": "bun scripts/generate-protocols.ts"
91
91
  },
92
92
  "dependencies": {
93
- "@linxiraos/pi-omptype": "1.3.2",
94
- "@linxiraos/pi-utils": "1.3.2"
93
+ "@linxiraos/pi-omptype": "1.4.1",
94
+ "@linxiraos/pi-utils": "1.4.1"
95
95
  },
96
96
  "devDependencies": {
97
97
  "@bgotink/kdl": "0.4.0",
98
- "@linxiraos/pi-ai": "1.3.2",
98
+ "@linxiraos/pi-ai": "1.4.1",
99
99
  "@types/bun": "1.4.3"
100
100
  },
101
101
  "engines": {
@@ -40,6 +40,7 @@ export type AuthProviderId =
40
40
  | "groq"
41
41
  | "helmcode"
42
42
  | "huggingface"
43
+ | "inception"
43
44
  | "kagi"
44
45
  | "kilo"
45
46
  | "kimi-code"
@@ -132,6 +133,7 @@ export type LoginProviderId =
132
133
  | "google-gemini-cli"
133
134
  | "helmcode"
134
135
  | "huggingface"
136
+ | "inception"
135
137
  | "kagi"
136
138
  | "kilo"
137
139
  | "kimi-code"
@@ -267,7 +267,7 @@ export const AXES: Readonly<Record<string, AxisDef>> = {
267
267
  "supports-mid-conversation-system": wire("supportsMidConversationSystem", ["anthropic"]),
268
268
  "supports-mid-conversation-tool-changes": wire("supportsMidConversationToolChanges", ["anthropic"]),
269
269
  "supports-per-message-effort": wire("supportsPerMessageEffort", ["anthropic"]),
270
- "supports-server-compaction": wire("supportsServerCompaction", ["anthropic"]),
270
+ "supports-server-compaction": wire("supportsServerCompaction", ["anthropic", "bedrock"]),
271
271
  "supports-between-tools-thinking": wire("supportsBetweenToolsThinking", ["anthropic"]),
272
272
  "supports-thinking-binding-controls": wire("supportsThinkingBindingControls", ["anthropic", "bedrock"]),
273
273
  "supports-turn-scoped-system": wire("supportsTurnScopedSystem", ["anthropic"]),
@@ -477,7 +477,7 @@ export const AXES: Readonly<Record<string, AxisDef>> = {
477
477
  "image-count-budget": { key: "imageCountBudget", set: "catalog", shape: "scalar" },
478
478
  /**
479
479
  * Replaces `image-count-budget` while the request reaches the official
480
- * endpoint (pi-ai `reachesOfficialEndpoint`): a limit measured or documented
480
+ * endpoint (pi-ai `reachesBudgetedHost`): a limit measured or documented
481
481
  * for the host's own endpoint, which a custom `baseUrl` or an
482
482
  * `ANTHROPIC_BASE_URL`/`FOUNDRY_BASE_URL` reroute (proxy, gateway) need not share.
483
483
  */
@@ -493,6 +493,22 @@ export const AXES: Readonly<Record<string, AxisDef>> = {
493
493
  /** Longest image edge the host passes to the model: it downscales larger images to fit first. */
494
494
  "image-max-edge": { key: "imageMaxEdge", set: "catalog", shape: "scalar" },
495
495
  "inline-image-byte-budget": { key: "inlineImageByteBudget", set: "catalog", shape: "scalar" },
496
+ /**
497
+ * Largest request body the host accepts. Where set, the inline-image byte clamp keeps the newest user message's
498
+ * and newest tool result's images past `inline-image-byte-budget` while they alone fit this limit.
499
+ */
500
+ "request-body-byte-limit": { key: "requestBodyByteLimit", set: "catalog", shape: "scalar" },
501
+ /**
502
+ * Opt-in: the host budgets above apply whenever the request reaches the provider's own catalog endpoint
503
+ * (`endpoint-hosts`, or an unset `baseUrl`), for a hosted gateway whose compat names no official endpoint.
504
+ * Unassigned: they apply only on the official endpoint (pi-ai `reachesOfficialEndpoint`).
505
+ */
506
+ "catalog-endpoint-budgets": {
507
+ key: "catalogEndpointBudgets",
508
+ set: "catalog",
509
+ shape: "scalar",
510
+ values: [true, false],
511
+ },
496
512
  /**
497
513
  * Supported formats and size bounds for judgment-request images; `mime-types`
498
514
  * is comma-separated because object payloads have no array shape.
@@ -544,6 +560,13 @@ export const AXES: Readonly<Record<string, AxisDef>> = {
544
560
  * Unassigned: no known lookback bound.
545
561
  */
546
562
  "prompt-cache-lookback": { key: "promptCacheLookback", set: "catalog", shape: "scalar" },
563
+ /**
564
+ * The provider's own endpoint keeps prompt-cache entries indefinitely
565
+ * (logged-in Codex subscriptions): an idle gap never cools the prefix, so
566
+ * rewriting it while idle only discards a warm cache. Read through
567
+ * `compat/prompt-cache-persistent.ts`. Unassigned: entries expire.
568
+ */
569
+ "prompt-cache-persistent": { key: "promptCachePersistent", set: "catalog", shape: "scalar", values: [true, false] },
547
570
  "long-usage-limit-fallback": { key: "longUsageLimitFallback", set: "catalog", shape: "scalar" },
548
571
  "max-context-window": { key: "maxContextWindow", set: "catalog", shape: "scalar" },
549
572
  /**
@@ -36,11 +36,25 @@ export interface OpenAiPatchTokenization {
36
36
  auto: "high" | "original";
37
37
  }
38
38
 
39
+ /** DeepSeek ViT patches merged `downsample`² into one token, plus a newline per row and two delimiters. */
40
+ export interface DeepSeekPatchTokenization {
41
+ regime: "deepseek-patch";
42
+ /** ViT patch edge in pixels. */
43
+ patchSize: number;
44
+ /** Patches merged per token along each axis. */
45
+ downsample: number;
46
+ /** Token budget per image, layout tokens included. */
47
+ maxTokens: number;
48
+ /** Smaller images are upscaled to this pixel area. */
49
+ minPixels: number;
50
+ }
51
+
39
52
  /** One model line's image billing rule: the vendor formula and its per-model numbers. */
40
53
  export type ImageTokenization = (
41
54
  | OpenAiPatchTokenization
42
55
  /** Anthropic 28px patches, resized to fit a padded-edge limit and a visual-token budget. */
43
56
  | { regime: "anthropic-patch"; maxEdge: number; maxTokens: number }
57
+ | DeepSeekPatchTokenization
44
58
  /** A fixed per-image budget regardless of pixels (Gemini 3 `media_resolution`). */
45
59
  | { regime: "fixed"; tokens: number }
46
60
  ) & {
@@ -54,7 +68,10 @@ const UNCLASSIFIED: Pick<ModelIdentity, "class"> = { class: "unknown" };
54
68
  function isImageTokenization(value: unknown): value is ImageTokenization {
55
69
  return (
56
70
  isRecord(value) &&
57
- (value.regime === "openai-patch" || value.regime === "anthropic-patch" || value.regime === "fixed")
71
+ (value.regime === "openai-patch" ||
72
+ value.regime === "anthropic-patch" ||
73
+ value.regime === "deepseek-patch" ||
74
+ value.regime === "fixed")
58
75
  );
59
76
  }
60
77
 
@@ -169,6 +186,41 @@ function anthropicTokens(size: ImageSize, maxEdge: number, maxTokens: number): n
169
186
  return patches(lo, short(lo));
170
187
  }
171
188
 
189
+ /**
190
+ * DeepSeek visual tokens: the image is upscaled to `minPixels`, padded to
191
+ * whole patches, and when its token grid busts `maxTokens` shrunk to the
192
+ * largest aspect-preserving grid that fits. Port of `plan_image_grid` in the
193
+ * reference processor (`max_wh_ratio` is unset in the V4.1 config):
194
+ * <https://huggingface.co/deepseek-ai/DeepSeek-V4.1-Flash/blob/main/inference/image_processor.py>
195
+ */
196
+ function deepseekTokens(size: ImageSize, rule: DeepSeekPatchTokenization): number {
197
+ const { patchSize, downsample, maxTokens, minPixels } = rule;
198
+ const cell = patchSize * downsample;
199
+ const spanTokens = (height: number, width: number) => {
200
+ const rows = Math.ceil(Math.floor(height / patchSize) / downsample);
201
+ const cols = Math.ceil(Math.floor(width / patchSize) / downsample);
202
+ return rows * (cols + 1) + 2;
203
+ };
204
+ let { width, height } = size;
205
+ if (width * height < minPixels) {
206
+ const scale = Math.sqrt(minPixels / (width * height));
207
+ width = Math.trunc(width * scale);
208
+ height = Math.trunc(height * scale);
209
+ }
210
+ const tokens = spanTokens(Math.ceil(height / patchSize) * patchSize, Math.ceil(width / patchSize) * patchSize);
211
+ if (tokens <= maxTokens) return tokens;
212
+ const aspect = height / width;
213
+ const maxCols = Math.sqrt((maxTokens - 2) / aspect + 0.25) - 0.5;
214
+ const maxRows = maxCols * aspect;
215
+ if (maxCols < 1) return spanTokens(Math.floor((maxTokens - 2) / 2) * cell, cell);
216
+ if (maxRows < 1) return spanTokens(cell, (maxTokens - 3) * cell);
217
+ const beta = Math.min((Math.floor(maxCols) * cell) / width, (Math.floor(maxRows) * cell) / height);
218
+ return spanTokens(
219
+ Math.floor((height * beta) / patchSize) * patchSize,
220
+ Math.floor((width * beta) / patchSize) * patchSize,
221
+ );
222
+ }
223
+
172
224
  /** Billed input tokens for one image of `size` under `rule`; only `openai-patch` reads `detail`. */
173
225
  export function imageTokens(rule: ImageTokenization, size: ImageSize, detail?: ImageDetail): number {
174
226
  switch (rule.regime) {
@@ -180,5 +232,7 @@ export function imageTokens(rule: ImageTokenization, size: ImageSize, detail?: I
180
232
  }
181
233
  case "anthropic-patch":
182
234
  return anthropicTokens(size, rule.maxEdge, rule.maxTokens);
235
+ case "deepseek-patch":
236
+ return deepseekTokens(size, rule);
183
237
  }
184
238
  }
@@ -0,0 +1,12 @@
1
+ import type { Model } from "../types";
2
+ import { isCatalogEndpointUrl } from "./catalog-endpoint";
3
+ import { resolveCatalogPolicy } from "./catalog-policy";
4
+
5
+ /**
6
+ * Whether {@link model}'s prompt-cache entries never expire
7
+ * (`prompt-cache-persistent` axis). Only the provider's own endpoint
8
+ * qualifies: a gateway or proxy reusing the provider id makes no such promise.
9
+ */
10
+ export function isPromptCachePersistent(model: Model): boolean {
11
+ return resolveCatalogPolicy(model).promptCachePersistent === true && isCatalogEndpointUrl(model, model.baseUrl);
12
+ }
@@ -1,2 +1,2 @@
1
1
  /** Every chat-model provider with a catalog entry (`default-model` in its provider rules). */
2
- export type KnownProvider = "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" | "factory-droid" | "firepass" | "fireworks" | "github-copilot" | "gitlab-duo" | "gitlab-duo-agent" | "gmi-cloud" | "google" | "google-antigravity" | "google-gemini-cli" | "google-vertex" | "groq" | "helmcode" | "huggingface" | "kilo" | "kimi-code" | "litellm" | "lm-studio" | "local" | "meta" | "minimax" | "minimax-code" | "minimax-code-cn" | "mistral" | "moonshot" | "muse-code" | "nanogpt" | "novita" | "nvidia" | "ollama" | "ollama-cloud" | "openai" | "openai-codex" | "opencode-go" | "opencode-zen" | "openrouter" | "qianfan" | "qwen-portal" | "sakana" | "sambanova" | "siliconflow" | "siliconflow-cn" | "singularityapi-dev" | "singularityapi-tech" | "snowflake" | "stepfun" | "synthetic" | "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" | "zenmux" | "zhipu-coding-plan";
2
+ export type KnownProvider = "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" | "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" | "kilo" | "kimi-code" | "litellm" | "lm-studio" | "local" | "meta" | "minimax" | "minimax-code" | "minimax-code-cn" | "mistral" | "moonshot" | "muse-code" | "nanogpt" | "novita" | "nvidia" | "ollama" | "ollama-cloud" | "openai" | "openai-codex" | "opencode-go" | "opencode-zen" | "openrouter" | "qianfan" | "qwen-portal" | "sakana" | "sambanova" | "siliconflow" | "siliconflow-cn" | "singularityapi-dev" | "singularityapi-tech" | "snowflake" | "stepfun" | "synthetic" | "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" | "zenmux" | "zhipu-coding-plan";
@@ -39,6 +39,7 @@ export type KnownProvider =
39
39
  | "groq"
40
40
  | "helmcode"
41
41
  | "huggingface"
42
+ | "inception"
42
43
  | "kilo"
43
44
  | "kimi-code"
44
45
  | "litellm"
@@ -9,11 +9,11 @@ const IMAGE_BUDGET_CACHE_MAX = 8192;
9
9
  /**
10
10
  * Maximum encoded inline-image bytes retained per request for a deployment with a documented body-size limit.
11
11
  * The axis is a host contract: a rerouted endpoint (proxy, gateway) imposes its own limit, so the budget applies
12
- * only when `officialEndpoint` says the request reaches the model's official endpoint. `compat.officialEndpoint`
13
- * classifies only the configured `baseUrl`; pi-ai's `reachesOfficialEndpoint` also follows request-time reroutes.
12
+ * only when `budgetedHost` says the request reaches the host the rules describe: pi-ai's `reachesBudgetedHost`
13
+ * (the model's official endpoint, following request-time reroutes, or Factory's hosted API for a Factory Droid model).
14
14
  */
15
- export function resolveInlineImageByteBudget(model: Model, officialEndpoint: boolean): number | undefined {
16
- if (!officialEndpoint) return undefined;
15
+ export function resolveInlineImageByteBudget(model: Model, budgetedHost: boolean): number | undefined {
16
+ if (!budgetedHost) return undefined;
17
17
  const key = `${model.provider} ${model.id} ${model.api}`;
18
18
  let budget = imageBudgetCache.get(key);
19
19
  if (budget === undefined) {
@@ -25,16 +25,26 @@ export function resolveInlineImageByteBudget(model: Model, officialEndpoint: boo
25
25
  return budget ?? undefined;
26
26
  }
27
27
 
28
+ /**
29
+ * Largest request body the deployment accepts (`request-body-byte-limit`), or `undefined` when no rule names it.
30
+ * Same gate as {@link resolveInlineImageByteBudget}.
31
+ */
32
+ export function resolveRequestBodyByteLimit(model: Model, budgetedHost: boolean): number | undefined {
33
+ if (!budgetedHost) return undefined;
34
+ const value = resolveCatalogPolicy(model).requestBodyByteLimit;
35
+ return typeof value === "number" && Number.isFinite(value) && value > 0 ? value : undefined;
36
+ }
37
+
28
38
  /**
29
39
  * Most images one request to this deployment may carry, or `undefined` when no rule names the host. A configured
30
40
  * `model.imageCountBudget` wins: the user knows the host behind a custom gateway. Otherwise the
31
- * `official-image-count-budget` axis replaces `image-count-budget` only when `officialEndpoint` says the request
32
- * reaches the model's official endpoint (see {@link resolveInlineImageByteBudget}); a rerouted endpoint keeps the
41
+ * `official-image-count-budget` axis replaces `image-count-budget` only when `budgetedHost` says the request
42
+ * reaches the host the rules describe (see {@link resolveInlineImageByteBudget}); a rerouted endpoint keeps the
33
43
  * provider's generic budget.
34
44
  */
35
- export function resolveImageCountBudget(model: Model, officialEndpoint: boolean): number | undefined {
45
+ export function resolveImageCountBudget(model: Model, budgetedHost: boolean): number | undefined {
36
46
  if (model.imageCountBudget !== undefined) return model.imageCountBudget;
37
47
  const policy = resolveCatalogPolicy(model);
38
- const value = (officialEndpoint && policy.officialImageCountBudget) || policy.imageCountBudget;
48
+ const value = (budgetedHost && policy.officialImageCountBudget) || policy.imageCountBudget;
39
49
  return typeof value === "number" && Number.isInteger(value) && value > 0 ? value : undefined;
40
50
  }
@@ -952,6 +952,7 @@ function resolveBedrockPolicy(spec: ModelSpec<"bedrock-converse-stream">, axes:
952
952
  // no-checkpoint shape.
953
953
  const compat: ResolvedBedrockCompat = {
954
954
  promptCacheMode: "none",
955
+ supportsServerCompaction: false,
955
956
  supportsLongPromptCacheRetention: false,
956
957
  promptCacheMinimumTokens: 0,
957
958
  promptCacheMaximumCheckpoints: 0,
@@ -225,9 +225,13 @@ One object axis carries a computed form: `long-context-cost` accepts either the
225
225
 
226
226
  `max-tokens-fallback` seeds `maxTokens` only when the row reports none, and `max-tokens-ceiling` lowers a larger reported `maxTokens` to the host's output cap (an unknown budget stays unknown unless a fallback seeded it). Both apply in `buildModel` after `limits-patch`, so discovery mappers pass upstream output budgets through verbatim. See the Kimi rules in [`providers/fireworks.kdl`](providers/fireworks.kdl).
227
227
 
228
- `inline-image-byte-budget` caps retained base64 image characters for a deployment's request body. It leaves room for tool schemas and text beneath the provider's body-size limit; the coding agent reads it through `resolveInlineImageByteBudget` before sending live history, and snapcompact gives its archive frames half of it (`frameDataBytesBudget`). The budget applies only while the request reaches the official endpoint (the Anthropic API, first-party OpenAI, or the Codex backend at its default URL), which callers decide with pi-ai's `reachesOfficialEndpoint`: `compat.officialEndpoint` for the configured `baseUrl`, and for first-party Anthropic models also the `ANTHROPIC_BASE_URL` or Foundry `FOUNDRY_BASE_URL` reroute applied at request time. A custom or rerouted endpoint imposes its own body limit.
228
+ `inline-image-byte-budget` caps retained base64 image characters for a deployment's request body. It leaves room for tool schemas and text beneath the provider's body-size limit; the coding agent reads it through `resolveInlineImageByteBudget` before sending live history, and snapcompact gives its archive frames half of it (`frameDataBytesBudget`). The budget applies only while the request reaches the host the rules describe (the Anthropic API, first-party OpenAI, the Codex backend at its default URL, or Factory Droid's own global or EU API host), which callers decide with pi-ai's `reachesBudgetedHost`: `compat.officialEndpoint` for the configured `baseUrl`, for first-party Anthropic models also the `ANTHROPIC_BASE_URL` or Foundry `FOUNDRY_BASE_URL` reroute applied at request time, and for Factory Droid models the `baseUrl` origin. A custom or rerouted endpoint imposes its own body limit.
229
229
 
230
- `image-count-budget` is the most images one request may carry, archive frames, screenshots and imaged tool results combined. The coding agent reads it through `resolveImageCountBudget`, drops the oldest images past it, and caps snapcompact frames at it; unassigned hosts get a floor of 5. `official-image-count-budget` replaces it while the request reaches the official endpoint (same gate as `inline-image-byte-budget`), for limits established on the host's own endpoint (Anthropic: 600, 100 on 200k-window models; Codex: 2,000); a custom or rerouted endpoint keeps `image-count-budget` (Anthropic 90, Codex 200).
230
+ `request-body-byte-limit` is the largest request body the host accepts (Factory Droid's hosted routes: 4,500,000 bytes), under the same gate. Where it is set, the byte clamp keeps the inline images of the newest user message and then of the newest image-bearing tool result even past `inline-image-byte-budget`, each only while the kept images fit the limit less the request's other serialized bytes, and evicts older images instead; read through `resolveRequestBodyByteLimit`.
231
+
232
+ `catalog-endpoint-budgets #true` makes these host budgets apply whenever a request reaches the provider's own catalog endpoint (an unset `baseUrl`, or an `endpoint-hosts` host; see `isCatalogEndpointUrl`), for a hosted gateway such as Factory Droid whose compat names no official endpoint. Unassigned, they apply only on the official endpoint.
233
+
234
+ `image-count-budget` is the most images one request may carry, archive frames, screenshots and imaged tool results combined. The coding agent reads it through `resolveImageCountBudget`, drops the oldest images past it, and caps snapcompact frames at it; unassigned hosts get a floor of 5. `official-image-count-budget` replaces it while the request reaches the host the rules describe (same gate as `inline-image-byte-budget`), for limits established on the host's own endpoint (Anthropic: 600, 100 on 200k-window models; Codex: 2,000); a custom or rerouted endpoint keeps `image-count-budget` (Anthropic 90, Codex 200).
231
235
 
232
236
  `endpoint-hosts` lists the HTTPS hostnames a provider serves besides its bundled base URL's host, such as Copilot's per-plan `api.<plan>.githubcopilot.com` hosts. That host plus these define the provider's own endpoint (`isCatalogEndpointUrl`), which separates first-party traffic from a custom model or provider override that keeps a catalog provider id but points `baseUrl` at a gateway, proxy, or local server. Connection prewarming and request compression act only on the provider's own endpoint.
233
237
 
@@ -239,6 +243,8 @@ One object axis carries a computed form: `long-context-cost` accepts either the
239
243
 
240
244
  `prompt-cache-lookback` is how many block positions back from a cache breakpoint the model's prompt cache looks for an earlier request's entry (Claude: 20, counting the breakpoint; a run of consecutive `tool_use` or `tool_result` blocks is one position). The coding agent reads it through `resolvePromptCacheLookback` and keeps warm-cache tool-result pruning inside the window; unassigned means no known bound.
241
245
 
246
+ `prompt-cache-persistent #true` marks a provider whose own endpoint keeps prompt-cache entries indefinitely (logged-in Codex accounts). The coding agent reads it through `isPromptCachePersistent` and skips idle compaction, which would only discard a prefix that stays warm; a custom `baseUrl` reusing the provider id does not qualify. Unassigned means entries expire.
247
+
242
248
  `task-sibling-prompt-cache #true` lets Task children use an automatically derived sibling cache key on the matching request model. Missing or `#false` keeps the provider's per-child default; explicit cache keys still win. The session resolves this catalog policy against the actual model for primary turns, handoff, and ephemeral requests that reuse the live context, including model changes, without sharing conversation IDs or response state. The automatic candidate is persisted separately from explicit keys and survives full forks, `/tan`, and session reopening; new and partial sessions discard it. A fork carrying an automatic candidate uses its own conversation ID on unsupported models, and re-enables the candidate when returning to an eligible model. Ordinary forks without an automatic candidate keep their existing inherited cache routing. Conventional compaction keeps its existing cache routing because its serialized summary prompt differs from the primary context. The opt-in covers Muse Code's `muse-spark-1.3`, `muse-spark-1.3-contributor`, `muse-wonder-1.0`, `muse-wonder-1.0-contributor`, `muse-wonder-full-1.0`, and `muse-wonder-full-1.0-contributor` over `openai-responses`. Meta documents shared-prefix `prompt_cache_key` routing for Responses. Warmed sibling cache reuse was measured on Spark 1.3 Contributor; the standard Spark variant shares this scope following maintainer guidance. A bounded synthetic probe observed cache reuse on all four Wonder variants; it does not establish production or latency benefits. Auxiliary-request latency has not been measured. Provider selectors also match custom providers that declare the same `providerType`; no benefit is established for custom endpoints.
243
249
 
244
250
  `image-max-edge` is the longest image edge, in pixels, a host passes to the model; it downscales larger images to fit first (Cursor: 1024 for Claude and GPT). Snapcompact reads it through `resolveImageMaxEdge` and renders frames no wider, so their glyphs reach the model at the size they were drawn; unassigned means the host keeps the image's size.
@@ -5,7 +5,7 @@ login-order "openai-codex" "anthropic" "zai" "zai-coding-plan" "kimi-code" "open
5
5
  "cursor" "devin" "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
- "xiaomi-token-plan-ams" "xiaomi-token-plan-cn" "firepass" "cline-pass" "factory-droid" "commandcode" "charm-hyper" "deepseek" "stepfun" "muse-code" "meta" "moonshot" \
8
+ "xiaomi-token-plan-ams" "xiaomi-token-plan-cn" "firepass" "cline-pass" "factory-droid" "commandcode" "charm-hyper" "deepseek" "stepfun" "muse-code" "meta" "moonshot" "inception" \
9
9
  "cerebras" "baseten" "helmcode" "fireworks" "together" "nvidia" "novita" "deepinfra" "huggingface" "perplexity" \
10
10
  "qianfan" "venice" "siliconflow" "siliconflow-cn" "synthetic" "nanogpt" "wafer-serverless" "coreweave" \
11
11
  "vercel-ai-gateway" "cloudflare-ai-gateway" "cloudflare-workers-ai" "snowflake" "litellm" "kilo" "zenmux" "opencode-zen" "opencode-go" \
@@ -0,0 +1,11 @@
1
+ auth "inception" {
2
+ name "Inception"
3
+ login "api-key" {
4
+ auth-url "https://platform.inceptionlabs.ai/dashboard/api-keys"
5
+ instructions "Create or copy your key from the Inception dashboard"
6
+ prompt "Paste your Inception API key" placeholder="sk_..."
7
+ // Validate against inference, not /models: Inception's models endpoints
8
+ // are public and answer 200 for any key. Costs a few tokens.
9
+ validate "chat-completions" label="Inception" base-url="https://api.inceptionlabs.ai/v1" model="mercury-3" max-tokens-field="max_completion_tokens"
10
+ }
11
+ }