@oh-my-pi/pi-catalog 17.3.8 → 17.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 (84) hide show
  1. package/CHANGELOG.md +37 -0
  2. package/LICENSE +22 -0
  3. package/THIRD-PARTY-NOTICES.txt +22909 -0
  4. package/dist/types/build.d.ts +5 -0
  5. package/dist/types/discovery/cursor-proto.d.ts +5368 -0
  6. package/dist/types/discovery/devin-proto.d.ts +1549 -0
  7. package/dist/types/discovery/index.d.ts +1 -0
  8. package/dist/types/discovery/protobuf.d.ts +102 -0
  9. package/dist/types/identity/family.d.ts +17 -0
  10. package/dist/types/index.d.ts +1 -0
  11. package/dist/types/model-manager.d.ts +5 -5
  12. package/dist/types/model-tokenizer.d.ts +8 -0
  13. package/dist/types/provider-models/descriptors.d.ts +1 -1
  14. package/dist/types/provider-models/openai-compat.d.ts +3 -1
  15. package/dist/types/types.d.ts +18 -1
  16. package/dist/types/variant-collapse.d.ts +1 -1
  17. package/dist/types/wire/codex.d.ts +21 -0
  18. package/package.json +8 -7
  19. package/src/build.ts +7 -0
  20. package/src/compat/openai.ts +1 -1
  21. package/src/discovery/codex.ts +4 -0
  22. package/src/discovery/cursor-proto.ts +8329 -0
  23. package/src/discovery/cursor.ts +2 -2
  24. package/src/discovery/devin-proto.ts +2037 -0
  25. package/src/discovery/devin.ts +4 -3
  26. package/src/discovery/index.ts +1 -0
  27. package/src/discovery/protobuf.ts +1073 -0
  28. package/src/hosts.ts +22 -1
  29. package/src/identity/family.ts +31 -0
  30. package/src/index.ts +1 -0
  31. package/src/model-cache.ts +3 -3
  32. package/src/model-manager.ts +5 -5
  33. package/src/model-tokenizer.ts +75 -0
  34. package/src/models.json +185025 -2081
  35. package/src/models.ts +6 -5
  36. package/src/provider-models/bundled-references.ts +12 -2
  37. package/src/provider-models/cache-provider-id.ts +4 -2
  38. package/src/provider-models/google.ts +8 -6
  39. package/src/provider-models/openai-compat.ts +269 -96
  40. package/src/types.ts +27 -1
  41. package/src/variant-collapse.ts +37 -1
  42. package/src/wire/codex.ts +54 -0
  43. package/dist/types/discovery/cursor-gen/agent_pb.d.ts +0 -16854
  44. package/dist/types/discovery/devin-gen/buf/validate/validate_pb.d.ts +0 -1715
  45. package/dist/types/discovery/devin-gen/exa/analytics_pb/analytics_pb.d.ts +0 -693
  46. package/dist/types/discovery/devin-gen/exa/api_server_pb/api_server_pb.d.ts +0 -9158
  47. package/dist/types/discovery/devin-gen/exa/auth_pb/auth_pb.d.ts +0 -52
  48. package/dist/types/discovery/devin-gen/exa/auto_cascade_common_pb/auto_cascade_common_pb.d.ts +0 -276
  49. package/dist/types/discovery/devin-gen/exa/bug_checker_pb/bug_checker_pb.d.ts +0 -78
  50. package/dist/types/discovery/devin-gen/exa/cascade_plugins_pb/cascade_plugins_pb.d.ts +0 -999
  51. package/dist/types/discovery/devin-gen/exa/chat_pb/chat_pb.d.ts +0 -1704
  52. package/dist/types/discovery/devin-gen/exa/code_edit/code_edit_pb/code_edit_pb.d.ts +0 -656
  53. package/dist/types/discovery/devin-gen/exa/codeium_common_pb/codeium_common_pb.d.ts +0 -15014
  54. package/dist/types/discovery/devin-gen/exa/context_module_pb/context_module_pb.d.ts +0 -607
  55. package/dist/types/discovery/devin-gen/exa/cortex_pb/cortex_pb.d.ts +0 -11830
  56. package/dist/types/discovery/devin-gen/exa/diff_action_pb/diff_action_pb.d.ts +0 -248
  57. package/dist/types/discovery/devin-gen/exa/index_pb/index_pb.d.ts +0 -1747
  58. package/dist/types/discovery/devin-gen/exa/knowledge_base_pb/knowledge_base_pb.d.ts +0 -509
  59. package/dist/types/discovery/devin-gen/exa/language_server_pb/language_server_pb.d.ts +0 -9048
  60. package/dist/types/discovery/devin-gen/exa/opensearch_clients_pb/opensearch_clients_pb.d.ts +0 -1760
  61. package/dist/types/discovery/devin-gen/exa/prompt_pb/prompt_pb.d.ts +0 -286
  62. package/dist/types/discovery/devin-gen/exa/reactive_component_pb/reactive_component_pb.d.ts +0 -405
  63. package/dist/types/discovery/devin-gen/exa/trust_pb/trust_pb.d.ts +0 -582
  64. package/src/discovery/cursor-gen/agent_pb.ts +0 -19608
  65. package/src/discovery/devin-gen/buf/validate/validate_pb.ts +0 -1862
  66. package/src/discovery/devin-gen/exa/analytics_pb/analytics_pb.ts +0 -871
  67. package/src/discovery/devin-gen/exa/api_server_pb/api_server_pb.ts +0 -11083
  68. package/src/discovery/devin-gen/exa/auth_pb/auth_pb.ts +0 -71
  69. package/src/discovery/devin-gen/exa/auto_cascade_common_pb/auto_cascade_common_pb.ts +0 -348
  70. package/src/discovery/devin-gen/exa/bug_checker_pb/bug_checker_pb.ts +0 -103
  71. package/src/discovery/devin-gen/exa/cascade_plugins_pb/cascade_plugins_pb.ts +0 -1198
  72. package/src/discovery/devin-gen/exa/chat_pb/chat_pb.ts +0 -2063
  73. package/src/discovery/devin-gen/exa/code_edit/code_edit_pb/code_edit_pb.ts +0 -810
  74. package/src/discovery/devin-gen/exa/codeium_common_pb/codeium_common_pb.ts +0 -18354
  75. package/src/discovery/devin-gen/exa/context_module_pb/context_module_pb.ts +0 -732
  76. package/src/discovery/devin-gen/exa/cortex_pb/cortex_pb.ts +0 -14277
  77. package/src/discovery/devin-gen/exa/diff_action_pb/diff_action_pb.ts +0 -312
  78. package/src/discovery/devin-gen/exa/index_pb/index_pb.ts +0 -2106
  79. package/src/discovery/devin-gen/exa/knowledge_base_pb/knowledge_base_pb.ts +0 -623
  80. package/src/discovery/devin-gen/exa/language_server_pb/language_server_pb.ts +0 -10918
  81. package/src/discovery/devin-gen/exa/opensearch_clients_pb/opensearch_clients_pb.ts +0 -2125
  82. package/src/discovery/devin-gen/exa/prompt_pb/prompt_pb.ts +0 -361
  83. package/src/discovery/devin-gen/exa/reactive_component_pb/reactive_component_pb.ts +0 -450
  84. package/src/discovery/devin-gen/exa/trust_pb/trust_pb.ts +0 -712
@@ -3,3 +3,4 @@ export * from "./codex.js";
3
3
  export * from "./gemini.js";
4
4
  export * from "./gitlab-duo-workflow.js";
5
5
  export * from "./openai-compatible.js";
6
+ export * from "./protobuf.js";
@@ -0,0 +1,102 @@
1
+ /**
2
+ * High-performance, zero-builder protobuf wire codecs for @oh-my-pi/pi-catalog.
3
+ *
4
+ * Schemas are declared as static IR descriptors with near-zero module load overhead
5
+ * and lazy compilation on first encode/decode/create invocation.
6
+ */
7
+ /** JSON values carried by `google.protobuf.Value` fields. */
8
+ export type JsonValue = null | boolean | number | string | JsonValue[] | {
9
+ [key: string]: JsonValue;
10
+ };
11
+ /** An unrecognised wire field retained for forward-compatible round-trips. */
12
+ export interface ProtoUnknownField {
13
+ no: number;
14
+ wireType: number;
15
+ data: Uint8Array;
16
+ }
17
+ /** Shared internal metadata present on every decoded protocol message. */
18
+ export interface ProtoMessage {
19
+ $typeName?: string;
20
+ $unknown?: ProtoUnknownField[];
21
+ }
22
+ /** A bidirectional codec for one protobuf message type. */
23
+ export interface MessageCodec<T extends ProtoMessage = ProtoMessage> {
24
+ (value: T): Uint8Array;
25
+ (value: Uint8Array): T;
26
+ /** Creates a message with protobuf defaults for omitted fields. */
27
+ create(value?: Partial<T>): T;
28
+ /** Encodes one message into protobuf wire bytes. */
29
+ encode(value: T): Uint8Array;
30
+ /** Decodes one protobuf message from wire bytes. */
31
+ decode(value: Uint8Array): T;
32
+ /** Converts a message to its protobuf JSON representation. */
33
+ toJson(value: T): JsonValue;
34
+ }
35
+ /** Infers a message shape from a codec result. */
36
+ export type InferMessage<TCodec> = TCodec extends MessageCodec<infer TMessage> ? TMessage : never;
37
+ /** Erases a referenced message's concrete shape for static field descriptors. */
38
+ export interface MessageReference {
39
+ encode(value: unknown): Uint8Array;
40
+ decode(value: Uint8Array): ProtoMessage;
41
+ toJson(value: unknown): JsonValue;
42
+ }
43
+ export type ScalarKind = "bool" | "bytes" | "double" | "enum" | "float" | "int32" | "int64" | "string" | "uint32" | "uint64";
44
+ export type WireType = 0 | 1 | 2 | 5;
45
+ export interface ScalarFieldDesc {
46
+ readonly no: number;
47
+ readonly name: string;
48
+ readonly kind: ScalarKind;
49
+ readonly optional?: boolean;
50
+ readonly repeat?: boolean;
51
+ }
52
+ export interface MessageFieldDesc {
53
+ readonly no: number;
54
+ readonly name: string;
55
+ readonly kind: "message";
56
+ readonly T: () => MessageReference;
57
+ readonly repeat?: boolean;
58
+ }
59
+ export interface EnumFieldDesc {
60
+ readonly no: number;
61
+ readonly name: string;
62
+ readonly kind: "enum";
63
+ readonly optional?: boolean;
64
+ readonly repeat?: boolean;
65
+ }
66
+ export interface MapFieldDesc {
67
+ readonly no: number;
68
+ readonly name: string;
69
+ readonly kind: "map";
70
+ readonly K: "string";
71
+ readonly V: ScalarKind | (() => MessageReference);
72
+ }
73
+ export type VariantDesc = {
74
+ readonly no: number;
75
+ readonly name: string;
76
+ readonly kind: ScalarKind;
77
+ } | {
78
+ readonly no: number;
79
+ readonly name: string;
80
+ readonly kind: "message";
81
+ readonly T: () => MessageReference;
82
+ };
83
+ export interface OneofFieldDesc {
84
+ readonly kind: "oneof";
85
+ readonly name: string;
86
+ readonly variants: readonly VariantDesc[];
87
+ }
88
+ export type FieldDesc = ScalarFieldDesc | MessageFieldDesc | EnumFieldDesc | MapFieldDesc | OneofFieldDesc;
89
+ /** Creates a high-performance, lazy protobuf message codec from an IR field descriptor list. */
90
+ export declare function pb<T extends ProtoMessage = ProtoMessage>(typeName: string, fields?: readonly FieldDesc[]): MessageCodec<T>;
91
+ /** Creates a message using its codec's protobuf defaults. */
92
+ export declare function create<TMessage extends ProtoMessage>(codec: MessageCodec<TMessage>, value?: Partial<TMessage>): TMessage;
93
+ /** Encodes a message using its codec. */
94
+ export declare function toBinary<TMessage extends ProtoMessage>(codec: MessageCodec<TMessage>, value: TMessage): Uint8Array;
95
+ /** Decodes wire bytes using a message codec. */
96
+ export declare function fromBinary<TMessage extends ProtoMessage>(codec: MessageCodec<TMessage>, value: Uint8Array): TMessage;
97
+ /** Converts a message to protobuf JSON using its codec. */
98
+ export declare function toJson<TMessage extends ProtoMessage>(codec: MessageCodec<TMessage>, value: TMessage): JsonValue;
99
+ /** Encodes a JSON value as `google.protobuf.Value`. */
100
+ export declare function encodeJsonValue(value: JsonValue): Uint8Array;
101
+ /** Decodes `google.protobuf.Value` wire bytes into a JSON value. */
102
+ export declare function decodeJsonValue(value: Uint8Array): JsonValue;
@@ -56,6 +56,8 @@ export declare const isDeepseekModelIdOrName: (modelId: string) => boolean;
56
56
  export declare const isDeepseekV4FlashModelId: (modelId: string) => boolean;
57
57
  /** Xiaomi MiMo family by id or display name. */
58
58
  export declare const isMimoModelIdOrName: (modelId: string) => boolean;
59
+ /** StepFun Step 3.7 Flash SKU in any namespace form (`kilo/stepfun/step-3.7-flash:free`). */
60
+ export declare const isStep37FlashModelId: (modelId: string) => boolean;
59
61
  /** Gemini family ids in any namespace form (`gemini-*`, `google/gemini-*`, `openrouter/google/gemini-…`). */
60
62
  export declare const isGeminiModelId: (modelId: string) => boolean;
61
63
  /** Grok family ids across namespace and delimiter forms (`grok-*`, `cursor-grok-*`, `xai/grok-*`). */
@@ -100,6 +102,13 @@ export declare const isMinimaxM3FamilyModelId: (modelId: string) => boolean;
100
102
  * and `none`.
101
103
  */
102
104
  export declare const isOpenAIGptOssModelId: (modelId: string) => boolean;
105
+ /**
106
+ * Meta Muse Spark ids (`muse-spark-1.1`, `muse-spark-1.2`,
107
+ * `muse-spark-1.2-contributor`, `meta/muse-spark-1.2`). The Responses
108
+ * `reasoning.effort` wire accepts `none` (thinking-off) plus
109
+ * `minimal`/`low`/`medium`/`high`/`xhigh`.
110
+ */
111
+ export declare const isMuseSparkModelId: (modelId: string) => boolean;
103
112
  /** OpenAI model ids (gpt-*, chatgpt-*, o1/o3/o4 SKUs, codex-*, or openai/*). */
104
113
  export declare const isOpenAIModelId: (modelId: string) => boolean;
105
114
  /**
@@ -199,6 +208,14 @@ export declare const hasOpus47ApiRestrictions: (modelId: string) => boolean;
199
208
  * @see https://platform.claude.com/docs/en/build-with-claude/mid-conversation-system-messages
200
209
  */
201
210
  export declare const supportsMidConversationSystemMessages: (modelId: string) => boolean;
211
+ /**
212
+ * Models that reliably follow the hashline line-anchored edit dialect
213
+ * (`[path#TAG]` headers plus 1-indexed anchors). Kimi, MiMo, DeepSeek V4
214
+ * Flash, and Step 3.7 Flash miscount anchors or drop the tag header often
215
+ * enough that hosts fall back to a literal search-replace edit format for
216
+ * them.
217
+ */
218
+ export declare const supportsHashlineEdits: (modelId: string) => boolean;
202
219
  export declare const isAnthropicFableOrMythosModel: (modelId: string) => boolean;
203
220
  /** Thinking-variant token location inside a model id. */
204
221
  export interface ThinkingVariantToken {
@@ -6,6 +6,7 @@ export * from "./identity/index.js";
6
6
  export * from "./model-cache.js";
7
7
  export * from "./model-manager.js";
8
8
  export * from "./model-thinking.js";
9
+ export * from "./model-tokenizer.js";
9
10
  export * from "./models.js";
10
11
  export * from "./provider-models/index.js";
11
12
  export * from "./types.js";
@@ -31,11 +31,11 @@ export interface ModelManagerOptions<TApi extends Api = Api, TModelsDevPayload =
31
31
  /** Cached model ids whose presence forces refresh when the static or migration-policy fingerprint changes. */
32
32
  dropCachedModelIdsOnStaticMismatch?: readonly string[];
33
33
  /**
34
- * Trusted, provider-wide request headers (compile-time constants, never
35
- * credentials) that the cache may restore by value for any model whose live
36
- * headers matched them at write time. Lets header-bearing dynamic models
37
- * without a bundled static entry survive offline reads instead of being
38
- * dropped as unrestorable (e.g. GitHub Copilot's User-Agent + API version).
34
+ * Trusted, provider-wide request headers that can be safely re-derived at
35
+ * cache-read time. The cache never persists their values. Models whose live
36
+ * headers matched this record at write time can survive offline reads without
37
+ * a bundled static source, including configured discovery providers whose
38
+ * bearer header comes from the current local config.
39
39
  */
40
40
  restorableHeaderFallback?: Record<string, string>;
41
41
  /** Optional dynamic endpoint fetcher. */
@@ -0,0 +1,8 @@
1
+ import type { ModelTokenizer } from "./types.js";
2
+ /**
3
+ * Resolve the exact locally embedded tokenizer for a canonical model id.
4
+ *
5
+ * This is catalog policy, not a runtime caller heuristic: [`buildModel`](./build.ts)
6
+ * materializes the result as `Model.tokenizer`; consumers read that property.
7
+ */
8
+ export declare function resolveModelTokenizer(modelId: string): ModelTokenizer | undefined;
@@ -205,7 +205,7 @@ export declare const CATALOG_PROVIDERS: readonly [{
205
205
  readonly id: "litellm";
206
206
  readonly defaultModel: "claude-opus-4-8";
207
207
  readonly envVars: readonly ["LITELLM_API_KEY"];
208
- readonly createModelManagerOptions: (config: ModelManagerConfig) => import("../index.js").ModelManagerOptions<"openai-completions", unknown>;
208
+ readonly createModelManagerOptions: (config: ModelManagerConfig) => import("../index.js").ModelManagerOptions<import("../index.js").Api, unknown>;
209
209
  readonly catalogDiscovery: {
210
210
  readonly label: "LiteLLM";
211
211
  readonly allowUnauthenticated: true;
@@ -568,12 +568,14 @@ export interface FetchLiteLLMRichModelsOptions<TApi extends Api> {
568
568
  signal?: AbortSignal;
569
569
  timeoutMs?: number;
570
570
  referenceResolver?: (modelId: string) => ModelSpec<TApi> | undefined;
571
+ resolveApi?: (entry: Record<string, unknown>, modelId: string) => TApi;
571
572
  }
572
573
  export declare const OPENAI_COMPAT_DISCOVERY_DEFAULT_CONTEXT_WINDOW = 128000;
573
574
  export declare const OPENAI_COMPAT_DISCOVERY_DEFAULT_MAX_TOKENS = 32768;
574
575
  export declare function normalizeLiteLLMManagementBaseUrl(baseUrl: string): string;
576
+ export declare function resolveLiteLLMApi(entry: Record<string, unknown> | undefined, id: string, fallbackApi?: Api): Api;
575
577
  export declare function fetchLiteLLMRichModels<TApi extends Api>(options: FetchLiteLLMRichModelsOptions<TApi>): Promise<ModelSpec<TApi>[] | null>;
576
- export declare function litellmModelManagerOptions(config?: LiteLLMModelManagerConfig): ModelManagerOptions<"openai-completions">;
578
+ export declare function litellmModelManagerOptions(config?: LiteLLMModelManagerConfig): ModelManagerOptions<Api>;
577
579
  export interface VllmModelManagerConfig {
578
580
  apiKey?: string;
579
581
  baseUrl?: string;
@@ -123,7 +123,7 @@ export interface Usage {
123
123
  }
124
124
  export type OpenAIReasoningFormat = "openai" | "openrouter" | "zai" | "kimi" | "qwen" | "qwen-chat-template";
125
125
  export type OpenAIReasoningDisableMode = "omit" | "lowest-effort" | "none-effort" | "openrouter-enabled-false" | "zai-thinking-disabled" | "qwen-enable-thinking-false" | "qwen-template-false";
126
- export type OpenAIStreamMarkupHealingPattern = "kimi" | "dsml" | "thinking";
126
+ export type OpenAIStreamMarkupHealingPattern = "kimi" | "dsml" | "qwen" | "thinking";
127
127
  /**
128
128
  * Compatibility settings for openai-completions API.
129
129
  * Use this to override URL-based auto-detection for custom providers.
@@ -716,6 +716,15 @@ export interface LongContextTokenCost extends TokenCost {
716
716
  export interface ModelCost extends TokenCost {
717
717
  longContext?: LongContextTokenCost;
718
718
  }
719
+ /**
720
+ * Exact local content tokenizer family for a model.
721
+ *
722
+ * Absent means no first-party local tokenizer is known and consumers retain
723
+ * their estimate/default-tokenizer policy. The values name tokenizer
724
+ * generations rather than providers: DeepSeek V3 through V4 share
725
+ * `"deepseek-v3"`; Kimi K2 through K3 share `"kimi-k2"`.
726
+ */
727
+ export type ModelTokenizer = "claude-v3" | "claude-v47" | "claude-v5" | "claude-v5-sonnet" | "qwen3" | "deepseek-v3" | "kimi-k2" | "glm5";
719
728
  export interface Model<TApi extends Api = Api> {
720
729
  id: string;
721
730
  /**
@@ -739,6 +748,12 @@ export interface Model<TApi extends Api = Api> {
739
748
  provider: Provider;
740
749
  baseUrl: string;
741
750
  reasoning: boolean;
751
+ /**
752
+ * Exact local tokenizer family resolved from the model identity or supplied
753
+ * explicitly by a catalog/discovery source. Absent leaves local counting to
754
+ * the consumer's fallback policy.
755
+ */
756
+ tokenizer?: ModelTokenizer;
742
757
  input: ("text" | "image")[];
743
758
  /**
744
759
  * Decoder family used for image inputs when it has narrower format support
@@ -797,6 +812,8 @@ export interface Model<TApi extends Api = Api> {
797
812
  preferWebsockets?: boolean;
798
813
  /** Codex Responses Lite transport: send the lite marker and carry instructions/tools as input items (mirrors codex-rs `use_responses_lite`). */
799
814
  useResponsesLite?: boolean;
815
+ /** Codex Code Mode restriction: model expects tools routed through a programmatic exec surface (mirrors codex-rs `tool_mode`). */
816
+ toolMode?: "code_mode_only";
800
817
  /** Preferred model to switch to when context promotion is triggered (model id or provider/id). */
801
818
  contextPromotionTarget?: string;
802
819
  /** Preferred model to use only for compaction (model id or provider/id); the active session model is unchanged. */
@@ -58,7 +58,7 @@ export declare const ANTIGRAVITY_VARIANT_COLLAPSE_TABLE: VariantCollapseTable;
58
58
  /** `google-gemini-cli` Gemini families on the official CLI's level transport. */
59
59
  export declare const GEMINI_CLI_VARIANT_COLLAPSE_TABLE: VariantCollapseTable;
60
60
  export declare const DEVIN_VARIANT_COLLAPSE_TABLE: VariantCollapseTable;
61
- /** `cursor` Grok families: per-effort siblings collapsed per service-tier lane. */
61
+ /** `cursor` per-effort sibling families collapsed per service-tier lane: Grok 4.5/4.6 plus GPT-5.6 Luna/Sol/Terra. */
62
62
  export declare const CURSOR_VARIANT_COLLAPSE_TABLE: VariantCollapseTable;
63
63
  /** Provider id → hand collapse table. The CCA providers diverge on thinking transport. */
64
64
  export declare const VARIANT_COLLAPSE_TABLES: Readonly<Record<string, VariantCollapseTable>>;
@@ -26,6 +26,8 @@ export declare const OPENAI_HEADERS: {
26
26
  readonly RESPONSES_LITE: "x-openai-internal-codex-responses-lite";
27
27
  /** DeviceCheck attestation envelope (codex-rs `X_OAI_ATTESTATION_HEADER`); sent on ChatGPT-OAuth requests. */
28
28
  readonly ATTESTATION: "x-oai-attestation";
29
+ /** Client-declared data residency for region-pinned enterprise workspaces. */
30
+ readonly RESIDENCY: "x-openai-internal-codex-residency";
29
31
  };
30
32
  export declare const OPENAI_HEADER_VALUES: {
31
33
  readonly BETA_RESPONSES: "responses=experimental";
@@ -43,3 +45,22 @@ export declare const JWT_CLAIM_PATH: "https://api.openai.com/auth";
43
45
  * Returns undefined if the token is not a valid Codex JWT.
44
46
  */
45
47
  export declare function getCodexAccountId(accessToken: string): string | undefined;
48
+ /**
49
+ * Extract the account's data residency from a Codex JWT access token.
50
+ *
51
+ * Enterprise ChatGPT workspaces can be pinned to a region. Such a workspace
52
+ * rejects a Codex request whose egress does not match it — HTTP 401
53
+ * `Workspace is not authorized in this region.` — unless the client declares
54
+ * the residency itself. The token already carries it, so no configuration is
55
+ * needed: `chatgpt_data_residency` is the authoritative claim, with
56
+ * `chatgpt_compute_residency` as the fallback for tokens that only carry that.
57
+ *
58
+ * Returns undefined for a non-JWT token, or for the (common) accounts whose
59
+ * claims omit residency entirely — those workspaces are not region-pinned.
60
+ */
61
+ export declare function getCodexResidency(accessToken: string): string | undefined;
62
+ /**
63
+ * Adds the token's workspace residency to Codex request headers without
64
+ * replacing a caller-supplied value.
65
+ */
66
+ export declare function applyCodexResidencyHeader(headers: Headers | Record<string, string>, accessToken: string): void;
package/package.json CHANGED
@@ -1,10 +1,10 @@
1
1
  {
2
2
  "type": "module",
3
3
  "name": "@oh-my-pi/pi-catalog",
4
- "version": "17.3.8",
4
+ "version": "17.4.1",
5
5
  "description": "Model catalog for omp: bundled model database, provider discovery descriptors, model identity, classification, and equivalence",
6
6
  "homepage": "https://omp.sh",
7
- "author": "Can Boluk",
7
+ "author": "Stencil Labs, Inc.",
8
8
  "license": "MIT",
9
9
  "repository": {
10
10
  "type": "git",
@@ -31,15 +31,14 @@
31
31
  "fix": "biome check --write --unsafe .",
32
32
  "fmt": "biome format --write .",
33
33
  "gen:models": "bun scripts/generate-models.ts",
34
- "gen:cursor-proto": "protoc --plugin=protoc-gen-es=../../node_modules/.bin/protoc-gen-es --es_out=src/discovery/cursor-gen --es_opt=target=ts -I ../ai/src/providers/cursor/proto ../ai/src/providers/cursor/proto/agent.proto"
34
+ "gen:proto": "bun scripts/generate-protocols.ts"
35
35
  },
36
36
  "dependencies": {
37
- "@bufbuild/protobuf": "^2.12.1",
38
- "@oh-my-pi/omptype": "17.3.8",
39
- "@oh-my-pi/pi-utils": "17.3.8"
37
+ "@oh-my-pi/omptype": "17.4.1",
38
+ "@oh-my-pi/pi-utils": "17.4.1"
40
39
  },
41
40
  "devDependencies": {
42
- "@oh-my-pi/pi-ai": "17.3.8",
41
+ "@oh-my-pi/pi-ai": "17.4.1",
43
42
  "@types/bun": "^1.3.14"
44
43
  },
45
44
  "engines": {
@@ -49,6 +48,8 @@
49
48
  "src",
50
49
  "README.md",
51
50
  "CHANGELOG.md",
51
+ "LICENSE",
52
+ "THIRD-PARTY-NOTICES.txt",
52
53
  "dist/types"
53
54
  ],
54
55
  "exports": {
package/src/build.ts CHANGED
@@ -16,6 +16,7 @@ import { buildDevinCompat } from "./compat/devin";
16
16
  import { buildOpenAICompat, buildOpenAIResponsesCompat, buildOpenRouterCompat } from "./compat/openai";
17
17
  import { bareModelId, parseOpenAIModel, semverGte } from "./identity/classify";
18
18
  import { resolveModelThinking } from "./model-thinking";
19
+ import { resolveModelTokenizer } from "./model-tokenizer";
19
20
  import type { Api, CompatOf, Model, ModelSpec } from "./types";
20
21
  import { cleanModelName } from "./utils";
21
22
 
@@ -58,12 +59,18 @@ function supportsOpenAIGAComputerUse(spec: ModelSpec<Api>, explicitSupport: bool
58
59
  return parsed !== null && semverGte(parsed.version, "5.4");
59
60
  }
60
61
 
62
+ /**
63
+ * Build one model from an authored spec. Bundled models.json rows are fully
64
+ * materialized by the generator and consumed directly (see `models.ts`), so
65
+ * this only runs for discovered/custom/override specs.
66
+ */
61
67
  export function buildModel<TApi extends Api>(spec: ModelSpec<TApi>): Model<TApi> {
62
68
  const compat = buildCompat(spec) as CompatOf<TApi>;
63
69
  const supportsComputerUseConfig = explicitComputerUseConfig(spec);
64
70
  return {
65
71
  ...spec,
66
72
  name: cleanModelName(spec.name),
73
+ tokenizer: spec.tokenizer ?? resolveModelTokenizer(spec.requestModelId ?? spec.id),
67
74
  thinking: resolveModelThinking(spec, compat),
68
75
  supportsComputerUse: supportsOpenAIGAComputerUse(spec, supportsComputerUseConfig),
69
76
  supportsComputerUseConfig,
@@ -759,7 +759,7 @@ export function buildOpenAIResponsesCompat(spec: OpenAIResponsesSpecLike): Resol
759
759
  disableReasoningOnForcedToolChoice: isKimiModel,
760
760
  disableReasoningOnToolChoice: isDeepseekFamily && reasoningCapable && !isOpenRouter,
761
761
  supportsToolChoice: true,
762
- supportsForcedToolChoice: true,
762
+ supportsForcedToolChoice: spec.provider !== "opencode-go" && spec.provider !== "opencode-zen",
763
763
  supportsNamedToolChoice: STRING_ONLY_NAMED_TOOL_CHOICE_PROVIDERS[spec.provider] !== true,
764
764
  reasoningContentField: "reasoning_content",
765
765
  requiresReasoningContentForToolCalls:
@@ -68,6 +68,7 @@ const codexModelEntrySchema = type({
68
68
  "priority?": "unknown",
69
69
  "prefer_websockets?": "unknown",
70
70
  "use_responses_lite?": "unknown",
71
+ "tool_mode?": "unknown",
71
72
  });
72
73
 
73
74
  const codexModelsResponseSchema = type({
@@ -282,6 +283,7 @@ interface ParsedCodexModelEntry {
282
283
  input: ("text" | "image")[];
283
284
  preferWebsockets: boolean;
284
285
  useResponsesLite: boolean;
286
+ toolMode: boolean;
285
287
  priority: number;
286
288
  }
287
289
 
@@ -310,6 +312,7 @@ function parseCodexModelEntry(entry: unknown): ParsedCodexModelEntry | null {
310
312
  input: normalizeInputModalities(payload.input_modalities),
311
313
  preferWebsockets: toBoolean(payload.prefer_websockets) === true,
312
314
  useResponsesLite: toBoolean(payload.use_responses_lite) === true,
315
+ toolMode: payload.tool_mode === "code_mode_only",
313
316
  priority: toFiniteNumber(payload.priority) ?? Number.MAX_SAFE_INTEGER,
314
317
  };
315
318
  }
@@ -360,6 +363,7 @@ function buildNormalizedCodexModel(
360
363
  maxTokens,
361
364
  ...(parsed.preferWebsockets ? { preferWebsockets: true } : {}),
362
365
  ...(parsed.useResponsesLite ? { useResponsesLite: true } : {}),
366
+ ...(parsed.toolMode ? { toolMode: "code_mode_only" as const } : {}),
363
367
  ...(parsed.priority !== Number.MAX_SAFE_INTEGER ? { priority: parsed.priority } : {}),
364
368
  },
365
369
  };