@oh-my-pi/pi-catalog 17.3.3 → 17.3.4
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 +11 -0
- package/dist/types/wire/codex.d.ts +3 -0
- package/dist/types/wire/github-copilot.d.ts +8 -0
- package/package.json +4 -4
- package/src/model-thinking.ts +10 -3
- package/src/provider-models/cache-provider-id.ts +14 -0
- package/src/provider-models/openai-compat.ts +14 -5
- package/src/wire/codex.ts +3 -0
- package/src/wire/github-copilot.ts +32 -0
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,17 @@
|
|
|
2
2
|
|
|
3
3
|
## [Unreleased]
|
|
4
4
|
|
|
5
|
+
## [17.3.4] - 2026-08-14
|
|
6
|
+
|
|
7
|
+
### Added
|
|
8
|
+
|
|
9
|
+
- Added wire constants for Codex V2 remote-compaction feature negotiation.
|
|
10
|
+
|
|
11
|
+
### Fixed
|
|
12
|
+
|
|
13
|
+
- Fixed raw `COPILOT_GITHUB_TOKEN` credentials skipping plan-specific endpoint discovery, which routed GitHub Copilot Business model requests to the personal endpoint and returned HTTP 403. The GitHub Copilot model cache is now scoped per credential, so switching the token no longer serves another account's stale endpoint for the cache TTL ([#8507](https://github.com/can1357/oh-my-pi/issues/8507)).
|
|
14
|
+
- Fixed the OpenRouter `deepseek/deepseek-v4-pro-0813` route silently clamping the reasoning effort to `high`: the dated SKU advertises (and accepts) the wire-exact `low`/`high`/`max` ladder, so its effort override no longer collapses to `high`-only. The undated `deepseek/deepseek-v4-pro` OpenRouter route stays `high`-only. ([#8517](https://github.com/can1357/oh-my-pi/issues/8517))
|
|
15
|
+
|
|
5
16
|
## [17.3.2] - 2026-08-13
|
|
6
17
|
|
|
7
18
|
### Added
|
|
@@ -8,6 +8,8 @@ export declare const CODEX_BASE_URL = "https://chatgpt.com/backend-api";
|
|
|
8
8
|
export declare const CODEX_CLIENT_VERSION = "0.144.1";
|
|
9
9
|
export declare const OPENAI_HEADERS: {
|
|
10
10
|
readonly BETA: "OpenAI-Beta";
|
|
11
|
+
/** Codex feature-negotiation header; values identify opt-in wire protocols. */
|
|
12
|
+
readonly CODEX_BETA_FEATURES: "x-codex-beta-features";
|
|
11
13
|
readonly ACCOUNT_ID: "chatgpt-account-id";
|
|
12
14
|
readonly ORIGINATOR: "originator";
|
|
13
15
|
readonly VERSION: "version";
|
|
@@ -28,6 +30,7 @@ export declare const OPENAI_HEADERS: {
|
|
|
28
30
|
export declare const OPENAI_HEADER_VALUES: {
|
|
29
31
|
readonly BETA_RESPONSES: "responses=experimental";
|
|
30
32
|
readonly BETA_RESPONSES_WEBSOCKETS_V2: "responses_websockets=2026-02-06";
|
|
33
|
+
readonly REMOTE_COMPACTION_V2: "remote_compaction_v2";
|
|
31
34
|
readonly ORIGINATOR_CODEX: "pi";
|
|
32
35
|
};
|
|
33
36
|
export declare const URL_PATHS: {
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { FetchImpl } from "../types.js";
|
|
1
2
|
/**
|
|
2
3
|
* GitHub Copilot wire metadata: API-key envelope parsing and endpoint
|
|
3
4
|
* derivation shared by catalog discovery and the pi-ai OAuth flow. The device
|
|
@@ -34,6 +35,13 @@ export declare const PERSONAL_GITHUB_COPILOT_BASE_URL: "https://api.githubcopilo
|
|
|
34
35
|
export declare function isPersonalGitHubCopilotBaseUrl(baseUrl: string | undefined): boolean;
|
|
35
36
|
export declare function normalizeGitHubCopilotEnterpriseDomain(input: string | undefined): string | undefined;
|
|
36
37
|
export declare function normalizeGitHubCopilotApiEndpoint(input: string | undefined): string | undefined;
|
|
38
|
+
/**
|
|
39
|
+
* Resolve the plan-specific Copilot API endpoint advertised for a GitHub token.
|
|
40
|
+
* Login and raw environment-token discovery share this best-effort probe. Pass
|
|
41
|
+
* a `signal` to bound it against the same discovery deadline as `/models`; a
|
|
42
|
+
* stalled probe otherwise blocks discovery indefinitely.
|
|
43
|
+
*/
|
|
44
|
+
export declare function discoverGitHubCopilotApiEndpoint(token: string, fetchImpl: FetchImpl, signal?: AbortSignal): Promise<string | undefined>;
|
|
37
45
|
export declare function parseGitHubCopilotApiKey(apiKeyRaw: string): ParsedGitHubCopilotApiKey;
|
|
38
46
|
export declare function normalizeDomain(input: string): string | null;
|
|
39
47
|
export declare function getGitHubCopilotBaseUrl(enterpriseDomain?: string): string;
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"type": "module",
|
|
3
3
|
"name": "@oh-my-pi/pi-catalog",
|
|
4
|
-
"version": "17.3.
|
|
4
|
+
"version": "17.3.4",
|
|
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",
|
|
@@ -35,11 +35,11 @@
|
|
|
35
35
|
},
|
|
36
36
|
"dependencies": {
|
|
37
37
|
"@bufbuild/protobuf": "^2.12.1",
|
|
38
|
-
"@oh-my-pi/omptype": "17.3.
|
|
39
|
-
"@oh-my-pi/pi-utils": "17.3.
|
|
38
|
+
"@oh-my-pi/omptype": "17.3.4",
|
|
39
|
+
"@oh-my-pi/pi-utils": "17.3.4"
|
|
40
40
|
},
|
|
41
41
|
"devDependencies": {
|
|
42
|
-
"@oh-my-pi/pi-ai": "17.3.
|
|
42
|
+
"@oh-my-pi/pi-ai": "17.3.4",
|
|
43
43
|
"@types/bun": "^1.3.14"
|
|
44
44
|
},
|
|
45
45
|
"engines": {
|
package/src/model-thinking.ts
CHANGED
|
@@ -374,13 +374,20 @@ function getModelDefinedEfforts<TApi extends Api>(
|
|
|
374
374
|
// on every first-party/aggregator host — the direct API, aggregators, and
|
|
375
375
|
// Ollama Cloud alike (medium/xhigh fold into high, max is a real wire
|
|
376
376
|
// tier). See https://api-docs.deepseek.com/api/create-chat-completion.
|
|
377
|
-
// OpenRouter's non-Flash V4 route
|
|
378
|
-
//
|
|
377
|
+
// OpenRouter's non-Flash V4 route exposes only high, except the dated
|
|
378
|
+
// `deepseek-v4-pro-0813` SKU: its /models metadata advertises (and the
|
|
379
|
+
// route accepts) the full low/high/max ladder like every other host.
|
|
380
|
+
// The older reasoners (V3.x, R1, deepseek-reasoner) top out at high/max.
|
|
379
381
|
if (isDeepseekV4FlashModelId(spec.id)) {
|
|
380
382
|
return LOW_HIGH_MAX_REASONING_EFFORTS;
|
|
381
383
|
}
|
|
382
384
|
if (bareModelId(spec.id).toLowerCase().includes("deepseek-v4")) {
|
|
383
|
-
|
|
385
|
+
if (!isOpenRouterThinkingFormat(compat)) {
|
|
386
|
+
return LOW_HIGH_MAX_REASONING_EFFORTS;
|
|
387
|
+
}
|
|
388
|
+
return bareModelId(spec.id).toLowerCase() === "deepseek-v4-pro-0813"
|
|
389
|
+
? LOW_HIGH_MAX_REASONING_EFFORTS
|
|
390
|
+
: HIGH_ONLY_REASONING_EFFORTS;
|
|
384
391
|
}
|
|
385
392
|
return isOpenRouterThinkingFormat(compat) ? HIGH_ONLY_REASONING_EFFORTS : HIGH_MAX_REASONING_EFFORTS;
|
|
386
393
|
}
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { PERSONAL_GITHUB_COPILOT_BASE_URL } from "../wire/github-copilot";
|
|
2
|
+
|
|
1
3
|
export interface ModelCacheProviderIdOptions {
|
|
2
4
|
apiKey?: string;
|
|
3
5
|
baseUrl?: string;
|
|
@@ -56,6 +58,18 @@ export function resolveModelCacheProviderId(providerId: string, options: ModelCa
|
|
|
56
58
|
const scope = `${options.apiKey ?? ""}\u0000${discoveryBaseUrl}`;
|
|
57
59
|
return `${providerId}:models-v1:${Bun.hash(scope).toString(36)}`;
|
|
58
60
|
}
|
|
61
|
+
case "github-copilot": {
|
|
62
|
+
// Copilot model specs bake in the plan-specific endpoint (personal vs
|
|
63
|
+
// Business/Enterprise) resolved from the credential. Discovery writes an
|
|
64
|
+
// authoritative cache, so `online-if-uncached` serves it for the full
|
|
65
|
+
// TTL without re-probing. Keying the namespace on the credential means
|
|
66
|
+
// switching `COPILOT_GITHUB_TOKEN` to a different account misses the
|
|
67
|
+
// prior endpoint's cache and re-runs discovery instead of hitting the
|
|
68
|
+
// stale host and 403ing (PR #8510 review).
|
|
69
|
+
const baseUrl = options.baseUrl ?? PERSONAL_GITHUB_COPILOT_BASE_URL;
|
|
70
|
+
const scope = `${options.apiKey ?? ""}\u0000${baseUrl}`;
|
|
71
|
+
return `github-copilot:models-v1:${Bun.hash(scope).toString(36)}`;
|
|
72
|
+
}
|
|
59
73
|
case "openrouter":
|
|
60
74
|
return "openrouter:pseudo-api";
|
|
61
75
|
case "vllm": {
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { USER_AGENT } from "@oh-my-pi/pi-utils";
|
|
2
2
|
import * as logger from "@oh-my-pi/pi-utils/logger";
|
|
3
3
|
import {
|
|
4
|
+
DEFAULT_OPENAI_COMPATIBLE_DISCOVERY_TIMEOUT_MS,
|
|
4
5
|
fetchOpenAICompatibleModels,
|
|
5
6
|
type OpenAICompatibleModelMapperContext,
|
|
6
7
|
type OpenAICompatibleModelRecord,
|
|
@@ -25,6 +26,7 @@ import { ALIBABA_TOKEN_PLAN_BASE_URL, parseAlibabaTokenPlanCredential } from "..
|
|
|
25
26
|
import { coreWeaveProjectHeaders } from "../wire/coreweave";
|
|
26
27
|
import {
|
|
27
28
|
COPILOT_API_HEADERS,
|
|
29
|
+
discoverGitHubCopilotApiEndpoint,
|
|
28
30
|
getGitHubCopilotBaseUrl,
|
|
29
31
|
isPersonalGitHubCopilotBaseUrl,
|
|
30
32
|
parseGitHubCopilotApiKey,
|
|
@@ -5191,6 +5193,7 @@ export function githubCopilotModelManagerOptions(config?: GithubCopilotModelMana
|
|
|
5191
5193
|
const resolveReference = createReferenceResolver(getProviderReferences);
|
|
5192
5194
|
return {
|
|
5193
5195
|
providerId: "github-copilot",
|
|
5196
|
+
cacheProviderId: resolveModelCacheProviderId("github-copilot", { apiKey: rawApiKey, baseUrl }),
|
|
5194
5197
|
dropCachedModelIdsOnStaticMismatch: COPILOT_CACHE_INVALIDATED_MODEL_IDS,
|
|
5195
5198
|
// COPILOT_API_HEADERS are compile-time constants (User-Agent + API
|
|
5196
5199
|
// version), not credentials. The cache omits all request headers for
|
|
@@ -5201,11 +5204,17 @@ export function githubCopilotModelManagerOptions(config?: GithubCopilotModelMana
|
|
|
5201
5204
|
restorableHeaderFallback: { ...COPILOT_API_HEADERS },
|
|
5202
5205
|
...(apiKey && {
|
|
5203
5206
|
fetchDynamicModels: async () => {
|
|
5207
|
+
const fetchImpl = discoveryFetch(config?.fetch);
|
|
5208
|
+
const requestBaseUrl = isPersonalGitHubCopilotBaseUrl(baseUrl)
|
|
5209
|
+
? ((await withCatalogDiscoveryTimeout(DEFAULT_OPENAI_COMPATIBLE_DISCOVERY_TIMEOUT_MS, signal =>
|
|
5210
|
+
discoverGitHubCopilotApiEndpoint(apiKey, fetchImpl, signal),
|
|
5211
|
+
)) ?? baseUrl)
|
|
5212
|
+
: baseUrl;
|
|
5204
5213
|
const longContextVariants: ModelSpec<Api>[] = [];
|
|
5205
5214
|
const models = await fetchOpenAICompatibleModels<Api>({
|
|
5206
5215
|
api: "openai-completions",
|
|
5207
5216
|
provider: "github-copilot",
|
|
5208
|
-
baseUrl,
|
|
5217
|
+
baseUrl: requestBaseUrl,
|
|
5209
5218
|
apiKey,
|
|
5210
5219
|
headers: COPILOT_API_HEADERS,
|
|
5211
5220
|
mapModel: (
|
|
@@ -5251,7 +5260,7 @@ export function githubCopilotModelManagerOptions(config?: GithubCopilotModelMana
|
|
|
5251
5260
|
const input: ModelSpec<Api>["input"] =
|
|
5252
5261
|
supportsVision === true
|
|
5253
5262
|
? ["text", "image"]
|
|
5254
|
-
: supportsVision === false || !isPersonalGitHubCopilotBaseUrl(
|
|
5263
|
+
: supportsVision === false || !isPersonalGitHubCopilotBaseUrl(requestBaseUrl)
|
|
5255
5264
|
? ["text"]
|
|
5256
5265
|
: (reference?.input ?? defaults.input);
|
|
5257
5266
|
// With COPILOT_API_HEADERS the served window is the long-context
|
|
@@ -5272,7 +5281,7 @@ export function githubCopilotModelManagerOptions(config?: GithubCopilotModelMana
|
|
|
5272
5281
|
...reference,
|
|
5273
5282
|
api,
|
|
5274
5283
|
provider: "github-copilot",
|
|
5275
|
-
baseUrl,
|
|
5284
|
+
baseUrl: requestBaseUrl,
|
|
5276
5285
|
name,
|
|
5277
5286
|
input,
|
|
5278
5287
|
contextWindow: defaultTierWindow,
|
|
@@ -5294,7 +5303,7 @@ export function githubCopilotModelManagerOptions(config?: GithubCopilotModelMana
|
|
|
5294
5303
|
: {
|
|
5295
5304
|
...defaults,
|
|
5296
5305
|
api,
|
|
5297
|
-
baseUrl,
|
|
5306
|
+
baseUrl: requestBaseUrl,
|
|
5298
5307
|
name,
|
|
5299
5308
|
input,
|
|
5300
5309
|
contextWindow: defaultTierWindow,
|
|
@@ -5340,7 +5349,7 @@ export function githubCopilotModelManagerOptions(config?: GithubCopilotModelMana
|
|
|
5340
5349
|
}
|
|
5341
5350
|
return base;
|
|
5342
5351
|
},
|
|
5343
|
-
fetch:
|
|
5352
|
+
fetch: fetchImpl,
|
|
5344
5353
|
});
|
|
5345
5354
|
if (models === null) {
|
|
5346
5355
|
return null;
|
package/src/wire/codex.ts
CHANGED
|
@@ -11,6 +11,8 @@ export const CODEX_CLIENT_VERSION = "0.144.1";
|
|
|
11
11
|
|
|
12
12
|
export const OPENAI_HEADERS = {
|
|
13
13
|
BETA: "OpenAI-Beta",
|
|
14
|
+
/** Codex feature-negotiation header; values identify opt-in wire protocols. */
|
|
15
|
+
CODEX_BETA_FEATURES: "x-codex-beta-features",
|
|
14
16
|
ACCOUNT_ID: "chatgpt-account-id",
|
|
15
17
|
ORIGINATOR: "originator",
|
|
16
18
|
VERSION: "version",
|
|
@@ -32,6 +34,7 @@ export const OPENAI_HEADERS = {
|
|
|
32
34
|
export const OPENAI_HEADER_VALUES = {
|
|
33
35
|
BETA_RESPONSES: "responses=experimental",
|
|
34
36
|
BETA_RESPONSES_WEBSOCKETS_V2: "responses_websockets=2026-02-06",
|
|
37
|
+
REMOTE_COMPACTION_V2: "remote_compaction_v2",
|
|
35
38
|
ORIGINATOR_CODEX: "pi",
|
|
36
39
|
} as const;
|
|
37
40
|
|
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
import type { FetchImpl } from "../types";
|
|
2
|
+
import { isRecord } from "../utils";
|
|
3
|
+
|
|
1
4
|
/**
|
|
2
5
|
* GitHub Copilot wire metadata: API-key envelope parsing and endpoint
|
|
3
6
|
* derivation shared by catalog discovery and the pi-ai OAuth flow. The device
|
|
@@ -72,6 +75,35 @@ export function normalizeGitHubCopilotApiEndpoint(input: string | undefined): st
|
|
|
72
75
|
return undefined;
|
|
73
76
|
}
|
|
74
77
|
}
|
|
78
|
+
/**
|
|
79
|
+
* Resolve the plan-specific Copilot API endpoint advertised for a GitHub token.
|
|
80
|
+
* Login and raw environment-token discovery share this best-effort probe. Pass
|
|
81
|
+
* a `signal` to bound it against the same discovery deadline as `/models`; a
|
|
82
|
+
* stalled probe otherwise blocks discovery indefinitely.
|
|
83
|
+
*/
|
|
84
|
+
export async function discoverGitHubCopilotApiEndpoint(
|
|
85
|
+
token: string,
|
|
86
|
+
fetchImpl: FetchImpl,
|
|
87
|
+
signal?: AbortSignal,
|
|
88
|
+
): Promise<string | undefined> {
|
|
89
|
+
try {
|
|
90
|
+
const response = await fetchImpl("https://api.github.com/copilot_internal/user", {
|
|
91
|
+
headers: {
|
|
92
|
+
Accept: "application/json",
|
|
93
|
+
Authorization: `token ${token}`,
|
|
94
|
+
...OPENCODE_HEADERS,
|
|
95
|
+
},
|
|
96
|
+
signal,
|
|
97
|
+
});
|
|
98
|
+
if (!response.ok) return undefined;
|
|
99
|
+
const data: unknown = await response.json();
|
|
100
|
+
if (!isRecord(data) || !isRecord(data.endpoints)) return undefined;
|
|
101
|
+
const endpoint = data.endpoints.api;
|
|
102
|
+
return typeof endpoint === "string" ? normalizeGitHubCopilotApiEndpoint(endpoint) : undefined;
|
|
103
|
+
} catch {
|
|
104
|
+
return undefined;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
75
107
|
|
|
76
108
|
export function parseGitHubCopilotApiKey(apiKeyRaw: string): ParsedGitHubCopilotApiKey {
|
|
77
109
|
try {
|