@oh-my-pi/pi-catalog 16.1.22 → 16.2.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.
- package/CHANGELOG.md +25 -0
- package/README.md +1 -1
- package/dist/types/discovery/gitlab-duo-workflow.d.ts +30 -0
- package/dist/types/discovery/index.d.ts +1 -0
- package/dist/types/index.d.ts +1 -0
- package/dist/types/provider-models/descriptor-types.d.ts +1 -1
- package/dist/types/provider-models/descriptors.d.ts +14 -0
- package/dist/types/provider-models/openai-compat.d.ts +23 -1
- package/dist/types/provider-models/special.d.ts +10 -0
- package/dist/types/types.d.ts +51 -2
- package/dist/types/wire/coreweave.d.ts +11 -0
- package/package.json +4 -4
- package/src/compat/openai.ts +19 -0
- package/src/discovery/gitlab-duo-workflow.ts +855 -0
- package/src/discovery/index.ts +1 -0
- package/src/index.ts +1 -0
- package/src/models.json +1279 -338
- package/src/provider-models/descriptor-types.ts +1 -1
- package/src/provider-models/descriptors.ts +21 -1
- package/src/provider-models/openai-compat.ts +295 -12
- package/src/provider-models/special.ts +64 -1
- package/src/types.ts +53 -0
- package/src/wire/coreweave.ts +42 -0
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,31 @@
|
|
|
2
2
|
|
|
3
3
|
## [Unreleased]
|
|
4
4
|
|
|
5
|
+
## [16.2.0] - 2026-06-27
|
|
6
|
+
|
|
7
|
+
### Added
|
|
8
|
+
|
|
9
|
+
- Added GitLab Duo Agent catalog discovery, including namespace selection, live model mapping, and a bundled fallback model for fresh installs.
|
|
10
|
+
- Added OpenAICompat.supportsNamedToolChoice to support forced tool use on string-only OpenAI-compatible chat servers without emitting the named function-object tool_choice shape.
|
|
11
|
+
- Added model metadata support for provider-native remote compaction and compaction-only model selection.
|
|
12
|
+
|
|
13
|
+
### Changed
|
|
14
|
+
|
|
15
|
+
- Disabled the thinking-effort selector for GitLab Duo Agent models since the underlying platform parameters are server-fixed.
|
|
16
|
+
|
|
17
|
+
### Fixed
|
|
18
|
+
|
|
19
|
+
- Improved GitLab Duo Agent and Duo Workflow namespace and project discovery to robustly handle paginated groups, SSH remotes with custom ports, Git worktrees, self-managed GitLab instances with relative paths, and configuration via GITLAB_DUO_PROJECT_PATH or GITLAB_DUO_PROJECT_ID.
|
|
20
|
+
- Fixed built-in LiteLLM discovery to prefer rich proxy metadata from management endpoints and avoid caching stale capability data.
|
|
21
|
+
- Fixed GitLab Duo Workflow model specifications to resolve correct static context windows, enabling accurate context usage tracking and auto-compaction.
|
|
22
|
+
|
|
23
|
+
## [16.1.23] - 2026-06-26
|
|
24
|
+
|
|
25
|
+
### Added
|
|
26
|
+
|
|
27
|
+
- Added `OpenAICompat.qwenPreserveThinking` — auto-enabled when the resolved `thinkingFormat` is `"qwen"` or `"qwen-chat-template"` AND `replayReasoningContent` is on (i.e. the four built-in local OpenAI-compatible providers, or a custom provider pointed at a loopback / RFC1918 / `*.local` baseUrl). Pairs with the chat-completions encoder change so the request body carries `preserve_thinking: true` (twin top-level + `chat_template_kwargs` emission), keeping Qwen3.6+ from stripping `<think>...</think>` off older assistant turns and breaking the local slot's KV cache between user messages. Non-Qwen chat templates ignore the parameter, so the flag stays a no-op outside the Qwen path; users on a cloud Qwen host (Alibaba Dashscope / Qwen Portal) can opt in with `compat.qwenPreserveThinking: true`. ([#3541](https://github.com/can1357/oh-my-pi/issues/3541))
|
|
28
|
+
- Added CoreWeave Serverless Inference as an OpenAI-compatible provider with models.dev-backed bundled catalog metadata.
|
|
29
|
+
|
|
5
30
|
## [16.1.22] - 2026-06-26
|
|
6
31
|
|
|
7
32
|
### Added
|
package/README.md
CHANGED
|
@@ -24,7 +24,7 @@ Import from subpaths (`@oh-my-pi/pi-catalog/<module>`) or the root barrel.
|
|
|
24
24
|
Never edit `src/models.json` by hand — it is produced from upstream sources (models.dev, provider catalog discovery, OpenCode docs) by `scripts/generate-models.ts` and the resolvers in `src/provider-models/`. Regenerate with:
|
|
25
25
|
|
|
26
26
|
```sh
|
|
27
|
-
bun
|
|
27
|
+
bun run gen:models
|
|
28
28
|
```
|
|
29
29
|
|
|
30
30
|
To change an entry, fix the source: resolver overrides in `provider-models/openai-compat.ts`, provider entries in `provider-models/descriptors.ts`, generator fixups in `scripts/generate-models.ts`, or thinking policies in `model-thinking.ts`.
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import type { FetchImpl, ModelSpec } from "../types";
|
|
2
|
+
type GitLabDuoWorkflowCandidateSource = "override" | "project" | "remote" | "group";
|
|
3
|
+
export interface GitLabDuoWorkflowModelRef {
|
|
4
|
+
name: string;
|
|
5
|
+
ref: string;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* GitLab Duo Workflow model/namespace discovery configuration.
|
|
9
|
+
*/
|
|
10
|
+
export interface GitLabDuoWorkflowDiscoveryConfig {
|
|
11
|
+
apiKey: string;
|
|
12
|
+
baseUrl?: string;
|
|
13
|
+
fetch?: FetchImpl;
|
|
14
|
+
namespaceId?: string;
|
|
15
|
+
projectId?: string;
|
|
16
|
+
projectPath?: string;
|
|
17
|
+
cwd?: string;
|
|
18
|
+
}
|
|
19
|
+
export interface GitLabDuoWorkflowNamespaceSelection {
|
|
20
|
+
rootNamespaceId: string;
|
|
21
|
+
namespacePath?: string;
|
|
22
|
+
projectPath?: string;
|
|
23
|
+
source: GitLabDuoWorkflowCandidateSource;
|
|
24
|
+
}
|
|
25
|
+
export declare function discoverGitLabDuoWorkflowNamespace(config: GitLabDuoWorkflowDiscoveryConfig): Promise<GitLabDuoWorkflowNamespaceSelection>;
|
|
26
|
+
export declare function discoverGitLabDuoWorkflowRuntimeNamespace(config: GitLabDuoWorkflowDiscoveryConfig): Promise<GitLabDuoWorkflowNamespaceSelection>;
|
|
27
|
+
export declare function fetchGitLabDuoWorkflowModels(config: GitLabDuoWorkflowDiscoveryConfig): Promise<readonly ModelSpec<"gitlab-duo-agent">[] | null>;
|
|
28
|
+
export declare function buildGitLabDuoWorkflowModelSpec(model: GitLabDuoWorkflowModelRef, baseUrl?: string, rootNamespaceId?: string): ModelSpec<"gitlab-duo-agent">;
|
|
29
|
+
export declare function buildGitLabDuoWorkflowFallbackModel(id?: string, name?: string, baseUrl?: string): ModelSpec<"gitlab-duo-agent">;
|
|
30
|
+
export {};
|
package/dist/types/index.d.ts
CHANGED
|
@@ -50,7 +50,7 @@ export declare function allowsUnauthenticatedCatalogDiscovery(descriptor: Catalo
|
|
|
50
50
|
* - Every entry is a member of `KnownProvider`.
|
|
51
51
|
* - `createModelManagerOptions` present (and not `specialModelManager`) ⇒
|
|
52
52
|
* appears in `PROVIDER_DESCRIPTORS` for runtime model discovery.
|
|
53
|
-
* -
|
|
53
|
+
* - \`catalogDiscovery\` present ⇒ participates in \`generate-models.ts\`.
|
|
54
54
|
*/
|
|
55
55
|
export interface ProviderCatalogEntry {
|
|
56
56
|
readonly id: string;
|
|
@@ -101,6 +101,12 @@ export declare const CATALOG_PROVIDERS: readonly [{
|
|
|
101
101
|
readonly id: "gitlab-duo";
|
|
102
102
|
readonly defaultModel: "duo-chat-opus-4-6";
|
|
103
103
|
readonly envVars: readonly ["GITLAB_TOKEN"];
|
|
104
|
+
}, {
|
|
105
|
+
readonly id: "gitlab-duo-agent";
|
|
106
|
+
readonly defaultModel: "claude_sonnet_4_6_vertex";
|
|
107
|
+
readonly envVars: readonly ["GITLAB_TOKEN"];
|
|
108
|
+
readonly createModelManagerOptions: (config: ModelManagerConfig) => import("..").ModelManagerOptions<"gitlab-duo-agent", unknown>;
|
|
109
|
+
readonly dynamicModelsAuthoritative: true;
|
|
104
110
|
}, {
|
|
105
111
|
readonly id: "google";
|
|
106
112
|
readonly defaultModel: "gemini-3.1-pro-preview";
|
|
@@ -339,6 +345,14 @@ export declare const CATALOG_PROVIDERS: readonly [{
|
|
|
339
345
|
readonly label: "Wafer Serverless";
|
|
340
346
|
readonly oauthProvider: "wafer-serverless";
|
|
341
347
|
};
|
|
348
|
+
}, {
|
|
349
|
+
readonly id: "coreweave";
|
|
350
|
+
readonly defaultModel: "openai/gpt-oss-120b";
|
|
351
|
+
readonly envVars: readonly ["COREWEAVE_API_KEY", "WANDB_API_KEY"];
|
|
352
|
+
readonly createModelManagerOptions: (config: ModelManagerConfig) => import("..").ModelManagerOptions<"openai-completions", unknown>;
|
|
353
|
+
readonly catalogDiscovery: {
|
|
354
|
+
readonly label: "CoreWeave Serverless Inference";
|
|
355
|
+
};
|
|
342
356
|
}, {
|
|
343
357
|
readonly id: "xai";
|
|
344
358
|
readonly defaultModel: "grok-4-fast-non-reasoning";
|
|
@@ -34,10 +34,12 @@ export interface ModelsDevModel {
|
|
|
34
34
|
* by the generator's policy pass (scripts/generated-policies.ts).
|
|
35
35
|
*/
|
|
36
36
|
export declare const ANTHROPIC_CURATED_FALLBACK_MODELS: readonly ModelSpec<"anthropic-messages">[];
|
|
37
|
+
type SimpleProviderDiscoveryHeaders = Record<string, string> | (() => Record<string, string> | undefined);
|
|
37
38
|
type SimpleProviderConfig = {
|
|
38
39
|
apiKey?: string;
|
|
39
40
|
baseUrl?: string;
|
|
40
41
|
fetch?: FetchImpl;
|
|
42
|
+
headers?: SimpleProviderDiscoveryHeaders;
|
|
41
43
|
};
|
|
42
44
|
export declare function createSimpleOpenAICompletionsOptions(providerId: Parameters<typeof getBundledModels>[0], defaultBaseUrl: string, config?: SimpleProviderConfig): ModelManagerOptions<"openai-completions">;
|
|
43
45
|
export interface UmansModelManagerConfig {
|
|
@@ -116,7 +118,7 @@ export declare const XAI_OAUTH_CURATED_MODELS: readonly XAICuratedModel[];
|
|
|
116
118
|
* Single source of truth for the curated to Model fan-in, consumed by both
|
|
117
119
|
* - {@link xaiOAuthModelManagerOptions} (runtime static seed handed to the model
|
|
118
120
|
* manager so the picker is populated on a fresh login), and
|
|
119
|
-
* -
|
|
121
|
+
* - \`packages/catalog/scripts/generate-models.ts\` (bundles the same entries into
|
|
120
122
|
* `models.json`, so the synchronous `ModelRegistry.#loadModels()` boot path
|
|
121
123
|
* sees `xai-oauth` without waiting for a refresh — fixes the boot-time
|
|
122
124
|
* default-model reset when `modelRoles.default = "xai-oauth/<id>"`).
|
|
@@ -307,6 +309,12 @@ export interface TogetherModelManagerConfig {
|
|
|
307
309
|
fetch?: FetchImpl;
|
|
308
310
|
}
|
|
309
311
|
export declare function togetherModelManagerOptions(config?: TogetherModelManagerConfig): ModelManagerOptions<"openai-completions">;
|
|
312
|
+
export interface CoreWeaveModelManagerConfig {
|
|
313
|
+
apiKey?: string;
|
|
314
|
+
baseUrl?: string;
|
|
315
|
+
fetch?: FetchImpl;
|
|
316
|
+
}
|
|
317
|
+
export declare function coreWeaveModelManagerOptions(config?: CoreWeaveModelManagerConfig): ModelManagerOptions<"openai-completions">;
|
|
310
318
|
export interface MoonshotModelManagerConfig {
|
|
311
319
|
apiKey?: string;
|
|
312
320
|
baseUrl?: string;
|
|
@@ -355,6 +363,20 @@ export interface LiteLLMModelManagerConfig {
|
|
|
355
363
|
baseUrl?: string;
|
|
356
364
|
fetch?: FetchImpl;
|
|
357
365
|
}
|
|
366
|
+
export interface FetchLiteLLMRichModelsOptions<TApi extends Api> {
|
|
367
|
+
api: TApi;
|
|
368
|
+
provider: Provider;
|
|
369
|
+
baseUrl: string;
|
|
370
|
+
apiKey?: string;
|
|
371
|
+
headers?: Record<string, string>;
|
|
372
|
+
fetch?: FetchImpl;
|
|
373
|
+
signal?: AbortSignal;
|
|
374
|
+
referenceResolver?: (modelId: string) => ModelSpec<TApi> | undefined;
|
|
375
|
+
}
|
|
376
|
+
export declare const OPENAI_COMPAT_DISCOVERY_DEFAULT_CONTEXT_WINDOW = 128000;
|
|
377
|
+
export declare const OPENAI_COMPAT_DISCOVERY_DEFAULT_MAX_TOKENS = 32768;
|
|
378
|
+
export declare function normalizeLiteLLMManagementBaseUrl(baseUrl: string): string;
|
|
379
|
+
export declare function fetchLiteLLMRichModels<TApi extends Api>(options: FetchLiteLLMRichModelsOptions<TApi>): Promise<ModelSpec<TApi>[] | null>;
|
|
358
380
|
export declare function litellmModelManagerOptions(config?: LiteLLMModelManagerConfig): ModelManagerOptions<"openai-completions">;
|
|
359
381
|
export interface VllmModelManagerConfig {
|
|
360
382
|
apiKey?: string;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { DevinModelDiscoveryOptions } from "../discovery/devin";
|
|
2
2
|
import type { ModelManagerOptions } from "../model-manager";
|
|
3
|
+
import type { FetchImpl } from "../types";
|
|
3
4
|
export interface OpenAICodexModelManagerConfig {
|
|
4
5
|
accessToken?: string;
|
|
5
6
|
accountId?: string;
|
|
@@ -12,6 +13,15 @@ export interface CursorModelManagerConfig {
|
|
|
12
13
|
clientVersion?: string;
|
|
13
14
|
}
|
|
14
15
|
export declare function cursorModelManagerOptions(config?: CursorModelManagerConfig): ModelManagerOptions<"cursor-agent">;
|
|
16
|
+
export interface GitLabDuoWorkflowModelManagerConfig {
|
|
17
|
+
apiKey?: string;
|
|
18
|
+
baseUrl?: string;
|
|
19
|
+
fetch?: FetchImpl;
|
|
20
|
+
namespaceId?: string;
|
|
21
|
+
projectId?: string;
|
|
22
|
+
cwd?: string;
|
|
23
|
+
}
|
|
24
|
+
export declare function gitLabDuoWorkflowModelManagerOptions(config?: GitLabDuoWorkflowModelManagerConfig): ModelManagerOptions<"gitlab-duo-agent">;
|
|
15
25
|
export interface DevinModelManagerConfig {
|
|
16
26
|
apiKey?: string;
|
|
17
27
|
baseUrl?: string;
|
package/dist/types/types.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { Effort } from "./effort";
|
|
2
2
|
export type { KnownProvider } from "./provider-models/descriptors";
|
|
3
|
-
export type KnownApi = "openai-completions" | "openai-responses" | "openrouter" | "openai-codex-responses" | "azure-openai-responses" | "anthropic-messages" | "bedrock-converse-stream" | "google-generative-ai" | "google-gemini-cli" | "google-vertex" | "ollama-chat" | "cursor-agent" | "devin-agent";
|
|
3
|
+
export type KnownApi = "openai-completions" | "openai-responses" | "openrouter" | "openai-codex-responses" | "azure-openai-responses" | "anthropic-messages" | "bedrock-converse-stream" | "google-generative-ai" | "google-gemini-cli" | "google-vertex" | "ollama-chat" | "cursor-agent" | "gitlab-duo-agent" | "devin-agent";
|
|
4
4
|
export type Api = KnownApi | (string & {});
|
|
5
5
|
/** Canonical thinking transport used by a model. */
|
|
6
6
|
export type ThinkingControlMode = "effort" | "budget" | "google-level" | "anthropic-adaptive" | "anthropic-budget-effort";
|
|
@@ -199,6 +199,28 @@ export interface OpenAICompat {
|
|
|
199
199
|
* models).
|
|
200
200
|
*/
|
|
201
201
|
replayReasoningContent?: boolean;
|
|
202
|
+
/**
|
|
203
|
+
* Send `preserve_thinking: true` so the Qwen3.6+ chat template renders
|
|
204
|
+
* `<think>...</think>` markup for EVERY assistant turn (not just turns
|
|
205
|
+
* after the last user message). Without it, the template strips the think
|
|
206
|
+
* block from older assistant turns:
|
|
207
|
+
*
|
|
208
|
+
* ```jinja
|
|
209
|
+
* {%- if (preserve_thinking is defined and preserve_thinking is true)
|
|
210
|
+
* or (loop.index0 > ns.last_query_index) %}
|
|
211
|
+
* <|im_start|>assistant\n<think>\n{rc}\n</think>\n\n{content}
|
|
212
|
+
* {%- else %}
|
|
213
|
+
* <|im_start|>assistant\n{content}
|
|
214
|
+
* ```
|
|
215
|
+
*
|
|
216
|
+
* The cache from the original generation has `<think>...</think>` tokens,
|
|
217
|
+
* so once a new user message arrives the prior assistant turns become
|
|
218
|
+
* "older" and the stripped re-render diverges — full prompt re-processing
|
|
219
|
+
* on SWA models (#3541). Default: auto-detected (Qwen thinking format on
|
|
220
|
+
* a local llama.cpp-style backend, paired with `replayReasoningContent`).
|
|
221
|
+
* Non-Qwen templates ignore the flag, so the auto-detection is safe.
|
|
222
|
+
*/
|
|
223
|
+
qwenPreserveThinking?: boolean;
|
|
202
224
|
/** Whether assistant tool-call messages must include non-empty content. Default: false. */
|
|
203
225
|
requiresAssistantContentForToolCalls?: boolean;
|
|
204
226
|
/** Whether the provider supports the `tool_choice` parameter. Default: true. */
|
|
@@ -209,6 +231,14 @@ export interface OpenAICompat {
|
|
|
209
231
|
* to provider-default auto selection. Default: true.
|
|
210
232
|
*/
|
|
211
233
|
supportsForcedToolChoice?: boolean;
|
|
234
|
+
/**
|
|
235
|
+
* Whether the chat-completions endpoint accepts the object form that pins one
|
|
236
|
+
* named function (`{ type: "function", function: { name } }`). Some
|
|
237
|
+
* OpenAI-compatible hosts such as llama.cpp only accept string
|
|
238
|
+
* `tool_choice` values; request builders downgrade a named force to
|
|
239
|
+
* `"required"` when this is false. Default: true.
|
|
240
|
+
*/
|
|
241
|
+
supportsNamedToolChoice?: boolean;
|
|
212
242
|
/**
|
|
213
243
|
* Drop reasoning fields (`reasoning_effort`, OpenRouter `reasoning`) for
|
|
214
244
|
* the request when `tool_choice` forces a tool call. Mirrors the Anthropic
|
|
@@ -401,11 +431,13 @@ export interface ResolvedOpenAISharedCompat {
|
|
|
401
431
|
disableReasoningOnToolChoice: boolean;
|
|
402
432
|
supportsToolChoice: boolean;
|
|
403
433
|
supportsForcedToolChoice: boolean;
|
|
434
|
+
supportsNamedToolChoice: boolean;
|
|
404
435
|
reasoningContentField?: OpenAICompat["reasoningContentField"];
|
|
405
436
|
requiresReasoningContentForToolCalls: boolean;
|
|
406
437
|
requiresReasoningContentForAllAssistantTurns: boolean;
|
|
407
438
|
allowsSyntheticReasoningContentForToolCalls: boolean;
|
|
408
439
|
replayReasoningContent: boolean;
|
|
440
|
+
qwenPreserveThinking: boolean;
|
|
409
441
|
requiresThinkingAsText: boolean;
|
|
410
442
|
requiresMistralToolIds: boolean;
|
|
411
443
|
requiresToolResultName: boolean;
|
|
@@ -433,7 +465,7 @@ export interface ResolvedOpenAISharedCompat {
|
|
|
433
465
|
* `buildModel`; request handlers read fields and never detect, resolve, or
|
|
434
466
|
* allocate.
|
|
435
467
|
*/
|
|
436
|
-
export type ResolvedOpenAICompat = ResolvedOpenAISharedCompat & Required<Omit<OpenAICompat, "supportsDeveloperRole" | "supportsReasoningEffort" | "reasoningEffortMap" | "supportsReasoningParams" | "thinkingFormat" | "reasoningDisableMode" | "omitReasoningEffort" | "includeEncryptedReasoning" | "filterReasoningHistory" | "disableReasoningOnForcedToolChoice" | "disableReasoningOnToolChoice" | "supportsToolChoice" | "supportsForcedToolChoice" | "reasoningContentField" | "requiresReasoningContentForToolCalls" | "requiresReasoningContentForAllAssistantTurns" | "allowsSyntheticReasoningContentForToolCalls" | "replayReasoningContent" | "requiresThinkingAsText" | "requiresMistralToolIds" | "requiresToolResultName" | "requiresAssistantAfterToolResult" | "requiresAssistantContentForToolCalls" | "stripDeepseekSpecialTokens" | "streamMarkupHealingPattern" | "reasoningDeltasMayBeCumulative" | "emptyLengthFinishIsContextError" | "usesOpenAIToolCallIdLimit" | "promptCacheSessionHeader" | "openRouterRouting" | "isOpenRouterHost" | "supportsStrictMode" | "supportsLongPromptCacheRetention" | "alwaysSendMaxTokens" | "wireModelIdMode" | "vercelGatewayRouting" | "extraBody" | "toolStrictMode" | "toolSchemaFlavor" | "streamIdleTimeoutMs" | "cacheControlFormat" | "thinkingKeep" | "strictResponsesPairing" | "supportsImageDetailOriginal" | "requiresJuiceZeroHack" | "enableGeminiThinkingLoopGuard" | "whenThinking">> & {
|
|
468
|
+
export type ResolvedOpenAICompat = ResolvedOpenAISharedCompat & Required<Omit<OpenAICompat, "supportsDeveloperRole" | "supportsReasoningEffort" | "reasoningEffortMap" | "supportsReasoningParams" | "thinkingFormat" | "reasoningDisableMode" | "omitReasoningEffort" | "includeEncryptedReasoning" | "filterReasoningHistory" | "disableReasoningOnForcedToolChoice" | "disableReasoningOnToolChoice" | "supportsToolChoice" | "supportsForcedToolChoice" | "supportsNamedToolChoice" | "reasoningContentField" | "requiresReasoningContentForToolCalls" | "requiresReasoningContentForAllAssistantTurns" | "allowsSyntheticReasoningContentForToolCalls" | "replayReasoningContent" | "qwenPreserveThinking" | "requiresThinkingAsText" | "requiresMistralToolIds" | "requiresToolResultName" | "requiresAssistantAfterToolResult" | "requiresAssistantContentForToolCalls" | "stripDeepseekSpecialTokens" | "streamMarkupHealingPattern" | "reasoningDeltasMayBeCumulative" | "emptyLengthFinishIsContextError" | "usesOpenAIToolCallIdLimit" | "promptCacheSessionHeader" | "openRouterRouting" | "isOpenRouterHost" | "supportsStrictMode" | "supportsLongPromptCacheRetention" | "alwaysSendMaxTokens" | "wireModelIdMode" | "vercelGatewayRouting" | "extraBody" | "toolStrictMode" | "toolSchemaFlavor" | "streamIdleTimeoutMs" | "cacheControlFormat" | "thinkingKeep" | "strictResponsesPairing" | "supportsImageDetailOriginal" | "requiresJuiceZeroHack" | "enableGeminiThinkingLoopGuard" | "whenThinking">> & {
|
|
437
469
|
vercelGatewayRouting?: OpenAICompat["vercelGatewayRouting"];
|
|
438
470
|
extraBody?: OpenAICompat["extraBody"];
|
|
439
471
|
cacheControlFormat?: OpenAICompat["cacheControlFormat"];
|
|
@@ -494,6 +526,17 @@ export type ResolvedDevinCompat = Required<DevinCompat>;
|
|
|
494
526
|
export type CompatConfigOf<TApi extends Api> = TApi extends "openai-completions" | "openrouter" | "openai-responses" | "azure-openai-responses" | "openai-codex-responses" ? OpenAICompat : TApi extends "anthropic-messages" ? AnthropicCompat : TApi extends "devin-agent" ? DevinCompat : undefined;
|
|
495
527
|
/** Resolved compat for a given API: complete record, materialized once by `buildModel`. */
|
|
496
528
|
export type CompatOf<TApi extends Api> = TApi extends "openrouter" ? ResolvedOpenRouterCompat : TApi extends "openai-completions" ? ResolvedOpenAICompat : TApi extends "openai-responses" | "azure-openai-responses" | "openai-codex-responses" ? ResolvedOpenAIResponsesCompat : TApi extends "anthropic-messages" ? ResolvedAnthropicCompat : TApi extends "devin-agent" ? ResolvedDevinCompat : undefined;
|
|
529
|
+
/** Provider-native compaction endpoint configuration for one model. */
|
|
530
|
+
export interface RemoteCompactionConfig<TApi extends Api = Api> {
|
|
531
|
+
/** Enables provider-native compaction for providers not enabled by built-in policy. */
|
|
532
|
+
enabled?: boolean;
|
|
533
|
+
/** Adapter family used by the configured compaction endpoint. */
|
|
534
|
+
api?: TApi;
|
|
535
|
+
/** Absolute compact endpoint URL; when omitted, the adapter derives it from the model base URL. */
|
|
536
|
+
endpoint?: string;
|
|
537
|
+
/** Model id sent to the compaction endpoint when it differs from the active model id. */
|
|
538
|
+
model?: string;
|
|
539
|
+
}
|
|
497
540
|
export interface Model<TApi extends Api = Api> {
|
|
498
541
|
id: string;
|
|
499
542
|
/**
|
|
@@ -523,6 +566,8 @@ export interface Model<TApi extends Api = Api> {
|
|
|
523
566
|
* reports that native tool calling is unsupported.
|
|
524
567
|
*/
|
|
525
568
|
supportsTools?: boolean;
|
|
569
|
+
/** GitLab Duo Workflow root namespace selected during catalog discovery. */
|
|
570
|
+
gitlabDuoWorkflowRootNamespaceId?: string;
|
|
526
571
|
cost: {
|
|
527
572
|
input: number;
|
|
528
573
|
output: number;
|
|
@@ -565,6 +610,10 @@ export interface Model<TApi extends Api = Api> {
|
|
|
565
610
|
preferWebsockets?: boolean;
|
|
566
611
|
/** Preferred model to switch to when context promotion is triggered (model id or provider/id). */
|
|
567
612
|
contextPromotionTarget?: string;
|
|
613
|
+
/** Preferred model to use only for compaction (model id or provider/id); the active session model is unchanged. */
|
|
614
|
+
compactionModel?: string;
|
|
615
|
+
/** Provider-native compaction endpoint configuration. */
|
|
616
|
+
remoteCompaction?: RemoteCompactionConfig<TApi>;
|
|
568
617
|
/** Provider-assigned priority value (lower = higher priority). */
|
|
569
618
|
priority?: number;
|
|
570
619
|
/** Canonical thinking capability metadata for this model. */
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export declare const COREWEAVE_PROJECT_HEADER: "OpenAI-Project";
|
|
2
|
+
export interface CoreWeaveProjectEnv {
|
|
3
|
+
[key: string]: string | undefined;
|
|
4
|
+
COREWEAVE_PROJECT?: string;
|
|
5
|
+
WANDB_INFERENCE_PROJECT?: string;
|
|
6
|
+
WANDB_ENTITY?: string;
|
|
7
|
+
WANDB_PROJECT?: string;
|
|
8
|
+
}
|
|
9
|
+
export declare function resolveCoreWeaveProject(env: CoreWeaveProjectEnv): string | undefined;
|
|
10
|
+
export declare function coreWeaveProjectHeaders(env: CoreWeaveProjectEnv): Record<string, string> | undefined;
|
|
11
|
+
export declare function hasCoreWeaveProjectHeader(headers: Record<string, string>): boolean;
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"type": "module",
|
|
3
3
|
"name": "@oh-my-pi/pi-catalog",
|
|
4
|
-
"version": "16.
|
|
4
|
+
"version": "16.2.0",
|
|
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
7
|
"author": "Can Boluk",
|
|
@@ -30,16 +30,16 @@
|
|
|
30
30
|
"test": "bun test --parallel",
|
|
31
31
|
"fix": "biome check --write --unsafe .",
|
|
32
32
|
"fmt": "biome format --write .",
|
|
33
|
-
"
|
|
33
|
+
"gen:models": "bun scripts/generate-models.ts"
|
|
34
34
|
},
|
|
35
35
|
"dependencies": {
|
|
36
36
|
"@bufbuild/protobuf": "^2.12.0",
|
|
37
|
-
"@oh-my-pi/pi-utils": "16.
|
|
37
|
+
"@oh-my-pi/pi-utils": "16.2.0",
|
|
38
38
|
"arktype": "^2.2.0",
|
|
39
39
|
"zod": "^4"
|
|
40
40
|
},
|
|
41
41
|
"devDependencies": {
|
|
42
|
-
"@oh-my-pi/pi-ai": "16.
|
|
42
|
+
"@oh-my-pi/pi-ai": "16.2.0",
|
|
43
43
|
"@types/bun": "^1.3.14"
|
|
44
44
|
},
|
|
45
45
|
"engines": {
|
package/src/compat/openai.ts
CHANGED
|
@@ -403,6 +403,7 @@ export function buildOpenAICompat(spec: ModelSpec<"openai-completions">): Resolv
|
|
|
403
403
|
disableReasoningOnToolChoice: isDeepseekFamily && Boolean(spec.reasoning) && !isOpenRouter,
|
|
404
404
|
supportsToolChoice: !isDirectDeepseekReasoning,
|
|
405
405
|
supportsForcedToolChoice: true,
|
|
406
|
+
supportsNamedToolChoice: provider !== "llama.cpp",
|
|
406
407
|
maxTokensField: useMaxTokens ? "max_tokens" : "max_completion_tokens",
|
|
407
408
|
requiresToolResultName: isMistral,
|
|
408
409
|
requiresAssistantAfterToolResult: isMistral,
|
|
@@ -468,6 +469,20 @@ export function buildOpenAICompat(spec: ModelSpec<"openai-completions">): Resolv
|
|
|
468
469
|
replayReasoningContent:
|
|
469
470
|
!PROXY_OPENAI_COMPAT_PROVIDERS.has(provider) &&
|
|
470
471
|
(LOCAL_OPENAI_COMPAT_PROVIDERS.has(provider) || hasLocalLoopbackBaseUrl(baseUrl)),
|
|
472
|
+
// `preserve_thinking: true` makes the Qwen3.6+ chat template render
|
|
473
|
+
// `<think>...</think>` for older assistant turns too, instead of
|
|
474
|
+
// stripping it the moment a new user message moves them past
|
|
475
|
+
// `last_query_index`. Without it, the slot's KV cache (which holds the
|
|
476
|
+
// raw `<think>X</think>` tokens emitted during generation) diverges
|
|
477
|
+
// from the next-turn render and llama.cpp falls back to full prompt
|
|
478
|
+
// re-processing — the exact symptom reported in #3541. Auto-enabled
|
|
479
|
+
// for Qwen thinking dialects on local llama.cpp-style backends (paired
|
|
480
|
+
// with `replayReasoningContent` above). Non-Qwen templates ignore the
|
|
481
|
+
// parameter, so the flag stays a no-op outside the Qwen path.
|
|
482
|
+
qwenPreserveThinking:
|
|
483
|
+
(thinkingFormat === "qwen" || thinkingFormat === "qwen-chat-template") &&
|
|
484
|
+
!PROXY_OPENAI_COMPAT_PROVIDERS.has(provider) &&
|
|
485
|
+
(LOCAL_OPENAI_COMPAT_PROVIDERS.has(provider) || hasLocalLoopbackBaseUrl(baseUrl)),
|
|
471
486
|
requiresAssistantContentForToolCalls: isKimiModel || isDirectDeepseekReasoning,
|
|
472
487
|
cacheControlFormat: isOpenRouter && spec.id.startsWith("anthropic/") ? "anthropic" : undefined,
|
|
473
488
|
openRouterRouting: undefined,
|
|
@@ -579,6 +594,7 @@ export function buildOpenAIResponsesCompat(spec: OpenAIResponsesSpecLike): Resol
|
|
|
579
594
|
disableReasoningOnToolChoice: isDeepseekFamily && reasoningCapable && !isOpenRouter,
|
|
580
595
|
supportsToolChoice: true,
|
|
581
596
|
supportsForcedToolChoice: true,
|
|
597
|
+
supportsNamedToolChoice: true,
|
|
582
598
|
reasoningContentField: "reasoning_content",
|
|
583
599
|
requiresReasoningContentForToolCalls:
|
|
584
600
|
(isKimiModel || (isDeepseekFamily && reasoningCapable) || (isOpenRouter && reasoningCapable)) &&
|
|
@@ -589,6 +605,9 @@ export function buildOpenAIResponsesCompat(spec: OpenAIResponsesSpecLike): Resol
|
|
|
589
605
|
// not via a top-level `reasoning_content` field — this flag is
|
|
590
606
|
// chat-completions-only.
|
|
591
607
|
replayReasoningContent: false,
|
|
608
|
+
// Responses-only; the Qwen `preserve_thinking` template knob lives on
|
|
609
|
+
// the chat-completions wire shape, never on Responses.
|
|
610
|
+
qwenPreserveThinking: false,
|
|
592
611
|
requiresThinkingAsText: false,
|
|
593
612
|
requiresMistralToolIds: false,
|
|
594
613
|
requiresToolResultName: false,
|