dsh-subscriptions 0.1.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/LICENSE +21 -0
- package/README.md +129 -0
- package/cordis.patch.yml +12 -0
- package/lib/auth/claude-code-creds.d.ts +23 -0
- package/lib/auth/claude-code-creds.js +172 -0
- package/lib/auth/device-flow.d.ts +55 -0
- package/lib/auth/device-flow.js +177 -0
- package/lib/auth/jwt.d.ts +10 -0
- package/lib/auth/jwt.js +25 -0
- package/lib/auth/oauth-flow.d.ts +91 -0
- package/lib/auth/oauth-flow.js +227 -0
- package/lib/auth/pkce.d.ts +31 -0
- package/lib/auth/pkce.js +35 -0
- package/lib/auth/rpc.d.ts +209 -0
- package/lib/auth/rpc.js +386 -0
- package/lib/auth/store.d.ts +196 -0
- package/lib/auth/store.js +468 -0
- package/lib/client/CursorCard.d.ts +9 -0
- package/lib/client/CursorCard.js +113 -0
- package/lib/client/ExternalUsageCards.d.ts +9 -0
- package/lib/client/ExternalUsageCards.js +72 -0
- package/lib/client/ImageGallery.d.ts +54 -0
- package/lib/client/ImageGallery.js +112 -0
- package/lib/client/ImageGenerateToolview.d.ts +48 -0
- package/lib/client/ImageGenerateToolview.js +133 -0
- package/lib/client/ProviderAccountManager.d.ts +13 -0
- package/lib/client/ProviderAccountManager.js +147 -0
- package/lib/client/ProviderModelEditor.d.ts +39 -0
- package/lib/client/ProviderModelEditor.js +107 -0
- package/lib/client/SpeedSelect.d.ts +71 -0
- package/lib/client/SpeedSelect.js +177 -0
- package/lib/client/SubscriptionUsageBadge.d.ts +116 -0
- package/lib/client/SubscriptionUsageBadge.js +543 -0
- package/lib/client/SubscriptionsSection.d.ts +140 -0
- package/lib/client/SubscriptionsSection.js +544 -0
- package/lib/client/UsageBadgeDisplaySetting.d.ts +7 -0
- package/lib/client/UsageBadgeDisplaySetting.js +36 -0
- package/lib/client/VideoGenerateToolview.d.ts +42 -0
- package/lib/client/VideoGenerateToolview.js +175 -0
- package/lib/client/account-preferences.d.ts +24 -0
- package/lib/client/account-preferences.js +21 -0
- package/lib/client/fast-command.d.ts +2 -0
- package/lib/client/fast-command.js +4 -0
- package/lib/client/host-contract.d.ts +90 -0
- package/lib/client/host-contract.js +101 -0
- package/lib/client/host-icons.d.ts +24 -0
- package/lib/client/host-icons.js +21 -0
- package/lib/client/index.d.ts +27 -0
- package/lib/client/index.js +136 -0
- package/lib/client/locales.d.ts +297 -0
- package/lib/client/locales.js +295 -0
- package/lib/client/subscription-card-styles.d.ts +3 -0
- package/lib/client/subscription-card-styles.js +53 -0
- package/lib/client/subscriptions-rpc.d.ts +14 -0
- package/lib/client/subscriptions-rpc.js +34 -0
- package/lib/client/usage-badge-preferences.d.ts +11 -0
- package/lib/client/usage-badge-preferences.js +41 -0
- package/lib/client.js +4472 -0
- package/lib/client.js.map +1 -0
- package/lib/compat.d.ts +36 -0
- package/lib/compat.js +20 -0
- package/lib/http.d.ts +6 -0
- package/lib/http.js +15 -0
- package/lib/index.d.ts +80 -0
- package/lib/index.js +14018 -0
- package/lib/model-defaults.d.ts +23 -0
- package/lib/model-defaults.js +237 -0
- package/lib/provider-settings.d.ts +39 -0
- package/lib/provider-settings.js +151 -0
- package/lib/providers/account-preferences.d.ts +41 -0
- package/lib/providers/account-preferences.js +153 -0
- package/lib/providers/accounts.d.ts +112 -0
- package/lib/providers/accounts.js +142 -0
- package/lib/providers/antigravity-oauth-client.d.ts +7 -0
- package/lib/providers/antigravity-oauth-client.js +7 -0
- package/lib/providers/antigravity.d.ts +110 -0
- package/lib/providers/antigravity.js +516 -0
- package/lib/providers/catalog-store.d.ts +48 -0
- package/lib/providers/catalog-store.js +243 -0
- package/lib/providers/claude-cli-version.d.ts +15 -0
- package/lib/providers/claude-cli-version.js +24 -0
- package/lib/providers/claude.d.ts +181 -0
- package/lib/providers/claude.js +680 -0
- package/lib/providers/codex-client-version.d.ts +8 -0
- package/lib/providers/codex-client-version.js +17 -0
- package/lib/providers/codex-search.d.ts +29 -0
- package/lib/providers/codex-search.js +198 -0
- package/lib/providers/codex.d.ts +229 -0
- package/lib/providers/codex.js +821 -0
- package/lib/providers/common.d.ts +389 -0
- package/lib/providers/common.js +656 -0
- package/lib/providers/copilot.d.ts +344 -0
- package/lib/providers/copilot.js +888 -0
- package/lib/providers/cursor-adapter.d.ts +15 -0
- package/lib/providers/cursor-adapter.js +39 -0
- package/lib/providers/cursor-auth.d.ts +43 -0
- package/lib/providers/cursor-auth.js +169 -0
- package/lib/providers/cursor-model-settings.d.ts +15 -0
- package/lib/providers/cursor-model-settings.js +51 -0
- package/lib/providers/cursor-usage.d.ts +9 -0
- package/lib/providers/cursor-usage.js +112 -0
- package/lib/providers/external-usage-controller.d.ts +19 -0
- package/lib/providers/external-usage-controller.js +32 -0
- package/lib/providers/external-usage.d.ts +8 -0
- package/lib/providers/external-usage.js +82 -0
- package/lib/providers/grok.d.ts +205 -0
- package/lib/providers/grok.js +713 -0
- package/lib/providers/image-pool.d.ts +30 -0
- package/lib/providers/image-pool.js +89 -0
- package/lib/providers/npm-cli-version.d.ts +56 -0
- package/lib/providers/npm-cli-version.js +98 -0
- package/lib/providers/pool-family.d.ts +56 -0
- package/lib/providers/pool-family.js +45 -0
- package/lib/providers/pool-health.d.ts +74 -0
- package/lib/providers/pool-health.js +150 -0
- package/lib/providers/pool-usage.d.ts +86 -0
- package/lib/providers/pool-usage.js +223 -0
- package/lib/providers/pool.d.ts +108 -0
- package/lib/providers/pool.js +368 -0
- package/lib/providers/rate-limit.d.ts +192 -0
- package/lib/providers/rate-limit.js +338 -0
- package/lib/tools/image-generate.d.ts +128 -0
- package/lib/tools/image-generate.js +438 -0
- package/lib/tools/registration.d.ts +15 -0
- package/lib/tools/registration.js +24 -0
- package/lib/tools/video-generate.d.ts +89 -0
- package/lib/tools/video-generate.js +257 -0
- package/lib/tools/x-search.d.ts +58 -0
- package/lib/tools/x-search.js +197 -0
- package/lib/translate/anthropic.d.ts +161 -0
- package/lib/translate/anthropic.js +515 -0
- package/lib/translate/antigravity-schema.d.ts +4 -0
- package/lib/translate/antigravity-schema.js +145 -0
- package/lib/translate/antigravity-thinking.d.ts +5 -0
- package/lib/translate/antigravity-thinking.js +44 -0
- package/lib/translate/antigravity.d.ts +114 -0
- package/lib/translate/antigravity.js +366 -0
- package/lib/translate/chat-completions.d.ts +120 -0
- package/lib/translate/chat-completions.js +382 -0
- package/lib/translate/resolved.d.ts +80 -0
- package/lib/translate/resolved.js +118 -0
- package/lib/translate/responses.d.ts +179 -0
- package/lib/translate/responses.js +408 -0
- package/lib/translate/sse.d.ts +21 -0
- package/lib/translate/sse.js +56 -0
- package/package.json +114 -0
- package/vendor/cursor/LICENSE +21 -0
- package/vendor/cursor/index.d.ts +18 -0
- package/vendor/cursor/index.js +3574 -0
- package/vendor/cursor/proto.js +254 -0
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { CODEX_CLIENT_VERSION } from './codex.js';
|
|
2
|
+
import { NpmCliVersionCache } from './npm-cli-version.js';
|
|
3
|
+
/** Public metadata only: never send subscription credentials to this endpoint. */
|
|
4
|
+
export const CODEX_VERSION_URL = 'https://registry.npmjs.org/@openai%2fcodex/latest';
|
|
5
|
+
/** Lazy, shared-per-plugin lookup of the official CLI's stable version. */
|
|
6
|
+
export class CodexClientVersionCache extends NpmCliVersionCache {
|
|
7
|
+
constructor(fetchFn, now, timeoutMs) {
|
|
8
|
+
super({
|
|
9
|
+
url: CODEX_VERSION_URL,
|
|
10
|
+
label: 'Codex',
|
|
11
|
+
floor: () => ({ version: CODEX_CLIENT_VERSION, source: 'fallback' }),
|
|
12
|
+
...fetchFn === undefined ? {} : { fetchFn },
|
|
13
|
+
...now === undefined ? {} : { now },
|
|
14
|
+
...timeoutMs === undefined ? {} : { timeoutMs },
|
|
15
|
+
});
|
|
16
|
+
}
|
|
17
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import type { WebSearchProvider, WebSearchRequest, WebSearchResult } from '@deepseek-ai/dsh-web';
|
|
2
|
+
import type { CodexSession } from '../auth/store.js';
|
|
3
|
+
import type { AccountTokenManager } from '../providers/accounts.js';
|
|
4
|
+
export declare const CODEX_SEARCH_PROVIDER_ID = "codex";
|
|
5
|
+
export declare const CODEX_SEARCH_URL = "https://chatgpt.com/backend-api/codex/alpha/search";
|
|
6
|
+
export declare const CODEX_SEARCH_MODEL = "gpt-5.6-terra";
|
|
7
|
+
export interface CodexWebSearchOptions {
|
|
8
|
+
tokens: Pick<AccountTokenManager<CodexSession>, 'session'>;
|
|
9
|
+
/**
|
|
10
|
+
* Current state of the Codex `web_search` tool switch. Absent counts as
|
|
11
|
+
* enabled. Read on every {@link CodexWebSearchProvider.available} call so
|
|
12
|
+
* turning the switch off releases the seam to another search provider
|
|
13
|
+
* instead of denying the host's tool.
|
|
14
|
+
*/
|
|
15
|
+
enabled?: () => boolean;
|
|
16
|
+
fetchFn?: typeof fetch;
|
|
17
|
+
requestId?: () => string;
|
|
18
|
+
retryBaseMs?: number;
|
|
19
|
+
}
|
|
20
|
+
/** Search provider registered behind DSH's stock web_search tool and citation UI. */
|
|
21
|
+
export declare class CodexWebSearchProvider implements WebSearchProvider {
|
|
22
|
+
private readonly options;
|
|
23
|
+
readonly id = "codex";
|
|
24
|
+
constructor(options: CodexWebSearchOptions);
|
|
25
|
+
available(): boolean;
|
|
26
|
+
search(request: WebSearchRequest, signal?: AbortSignal): Promise<WebSearchResult>;
|
|
27
|
+
private dispatch;
|
|
28
|
+
}
|
|
29
|
+
export declare function normalizeCodexSearchResponse(value: unknown): WebSearchResult;
|
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
/** Codex-backed provider for DSH's native web_search capability. */
|
|
2
|
+
import { randomUUID } from 'node:crypto';
|
|
3
|
+
import { attributionHeaders } from '@deepseek-ai/dsh-llm';
|
|
4
|
+
import { WebError } from '@deepseek-ai/dsh-web';
|
|
5
|
+
export const CODEX_SEARCH_PROVIDER_ID = 'codex';
|
|
6
|
+
export const CODEX_SEARCH_URL = 'https://chatgpt.com/backend-api/codex/alpha/search';
|
|
7
|
+
export const CODEX_SEARCH_MODEL = 'gpt-5.6-terra';
|
|
8
|
+
const MAX_ATTEMPTS = 5;
|
|
9
|
+
const MAX_RESPONSE_BYTES = 2 * 1024 * 1024;
|
|
10
|
+
const RETRY_BASE_MS = 100;
|
|
11
|
+
/** Search provider registered behind DSH's stock web_search tool and citation UI. */
|
|
12
|
+
export class CodexWebSearchProvider {
|
|
13
|
+
options;
|
|
14
|
+
id = CODEX_SEARCH_PROVIDER_ID;
|
|
15
|
+
constructor(options) {
|
|
16
|
+
this.options = options;
|
|
17
|
+
}
|
|
18
|
+
available() { return this.options.enabled?.() ?? true; }
|
|
19
|
+
async search(request, signal) {
|
|
20
|
+
throwIfAborted(signal);
|
|
21
|
+
let session;
|
|
22
|
+
try {
|
|
23
|
+
session = await this.options.tokens.session();
|
|
24
|
+
}
|
|
25
|
+
catch (cause) {
|
|
26
|
+
throw new WebError('Codex Web Search requires a logged-in Codex account; log in via Settings → Subscriptions', 'CODEX_AUTH_REQUIRED', { cause });
|
|
27
|
+
}
|
|
28
|
+
const body = {
|
|
29
|
+
id: this.options.requestId?.() ?? randomUUID(),
|
|
30
|
+
model: CODEX_SEARCH_MODEL,
|
|
31
|
+
input: request.query,
|
|
32
|
+
commands: { search_query: [{ q: request.query }] },
|
|
33
|
+
settings: {
|
|
34
|
+
search_context_size: 'medium',
|
|
35
|
+
allowed_callers: ['direct'],
|
|
36
|
+
external_web_access: 'live',
|
|
37
|
+
},
|
|
38
|
+
max_output_tokens: 2048,
|
|
39
|
+
};
|
|
40
|
+
const value = await this.dispatch(body, session, signal);
|
|
41
|
+
return normalizeCodexSearchResponse(value);
|
|
42
|
+
}
|
|
43
|
+
async dispatch(body, session, signal) {
|
|
44
|
+
const fetchFn = this.options.fetchFn ?? fetch;
|
|
45
|
+
const retryBaseMs = this.options.retryBaseMs ?? RETRY_BASE_MS;
|
|
46
|
+
for (let attempt = 1; attempt <= MAX_ATTEMPTS; attempt++) {
|
|
47
|
+
throwIfAborted(signal);
|
|
48
|
+
let response;
|
|
49
|
+
try {
|
|
50
|
+
response = await fetchFn(CODEX_SEARCH_URL, {
|
|
51
|
+
method: 'POST',
|
|
52
|
+
headers: {
|
|
53
|
+
'authorization': `Bearer ${session.accessToken}`,
|
|
54
|
+
'chatgpt-account-id': session.accountId,
|
|
55
|
+
'content-type': 'application/json',
|
|
56
|
+
'originator': 'codex_cli_rs',
|
|
57
|
+
...attributionHeaders(),
|
|
58
|
+
},
|
|
59
|
+
body: JSON.stringify(body),
|
|
60
|
+
...(signal === undefined ? {} : { signal }),
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
catch (cause) {
|
|
64
|
+
if (signal?.aborted)
|
|
65
|
+
throw cancelled(cause);
|
|
66
|
+
if (attempt < MAX_ATTEMPTS) {
|
|
67
|
+
await abortableDelay(retryBaseMs * 2 ** (attempt - 1), signal);
|
|
68
|
+
continue;
|
|
69
|
+
}
|
|
70
|
+
throw new WebError('Codex Web Search failed after five transport attempts', 'CODEX_SEARCH_NETWORK', { cause });
|
|
71
|
+
}
|
|
72
|
+
if (response.status === 429) {
|
|
73
|
+
await discard(response);
|
|
74
|
+
throw new WebError('Codex Web Search was rate-limited; retry later', 'CODEX_SEARCH_RATE_LIMIT');
|
|
75
|
+
}
|
|
76
|
+
if (response.status >= 500 && response.status <= 599 && attempt < MAX_ATTEMPTS) {
|
|
77
|
+
await discard(response);
|
|
78
|
+
await abortableDelay(retryBaseMs * 2 ** (attempt - 1), signal);
|
|
79
|
+
continue;
|
|
80
|
+
}
|
|
81
|
+
if (!response.ok) {
|
|
82
|
+
await discard(response);
|
|
83
|
+
throw new WebError(`Codex Web Search returned HTTP ${response.status}`, 'CODEX_SEARCH_UPSTREAM');
|
|
84
|
+
}
|
|
85
|
+
const text = await boundedText(response, signal);
|
|
86
|
+
try {
|
|
87
|
+
return JSON.parse(text);
|
|
88
|
+
}
|
|
89
|
+
catch (cause) {
|
|
90
|
+
throw new WebError('Codex Web Search returned invalid JSON', 'CODEX_SEARCH_RESPONSE', { cause });
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
throw new WebError('Codex Web Search exhausted its retry policy', 'CODEX_SEARCH_UPSTREAM');
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
export function normalizeCodexSearchResponse(value) {
|
|
97
|
+
if (!record(value) || typeof value.output !== 'string') {
|
|
98
|
+
throw new WebError('Codex Web Search returned an unusable response', 'CODEX_SEARCH_RESPONSE');
|
|
99
|
+
}
|
|
100
|
+
const sources = [];
|
|
101
|
+
const seen = new Set();
|
|
102
|
+
if (Array.isArray(value.results))
|
|
103
|
+
for (const candidate of value.results) {
|
|
104
|
+
if (!record(candidate))
|
|
105
|
+
continue;
|
|
106
|
+
const rawUrl = safeString(candidate.url, 8192) ?? safeString(candidate.source_url, 8192);
|
|
107
|
+
const url = rawUrl === undefined ? undefined : httpUrl(rawUrl);
|
|
108
|
+
if (url === undefined || seen.has(url))
|
|
109
|
+
continue;
|
|
110
|
+
seen.add(url);
|
|
111
|
+
const title = safeString(candidate.title, 1000) ?? safeString(candidate.source_title, 1000);
|
|
112
|
+
const snippet = safeString(candidate.snippet, 4000) ?? safeString(candidate.text, 4000);
|
|
113
|
+
sources.push({ url, ...(title ? { title } : {}), ...(snippet ? { snippet } : {}) });
|
|
114
|
+
}
|
|
115
|
+
return { content: value.output, sources, truncated: false };
|
|
116
|
+
}
|
|
117
|
+
function record(value) {
|
|
118
|
+
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
119
|
+
}
|
|
120
|
+
function safeString(value, max) {
|
|
121
|
+
if (typeof value !== 'string')
|
|
122
|
+
return undefined;
|
|
123
|
+
const text = value.trim();
|
|
124
|
+
if (!text || text.length > max || /[\u0000-\u001f]/.test(text))
|
|
125
|
+
return undefined;
|
|
126
|
+
return text;
|
|
127
|
+
}
|
|
128
|
+
function httpUrl(value) {
|
|
129
|
+
try {
|
|
130
|
+
const parsed = new URL(value);
|
|
131
|
+
return parsed.protocol === 'http:' || parsed.protocol === 'https:' ? parsed.href : undefined;
|
|
132
|
+
}
|
|
133
|
+
catch {
|
|
134
|
+
return undefined;
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
async function discard(response) {
|
|
138
|
+
try {
|
|
139
|
+
await response.body?.cancel();
|
|
140
|
+
}
|
|
141
|
+
catch { /* best effort */ }
|
|
142
|
+
}
|
|
143
|
+
function throwIfAborted(signal) {
|
|
144
|
+
if (signal?.aborted)
|
|
145
|
+
throw cancelled(signal.reason);
|
|
146
|
+
}
|
|
147
|
+
function cancelled(cause) {
|
|
148
|
+
return new WebError('Codex Web Search was cancelled', 'CODEX_SEARCH_CANCELLED', { cause });
|
|
149
|
+
}
|
|
150
|
+
function abortableDelay(ms, signal) {
|
|
151
|
+
if (ms <= 0) {
|
|
152
|
+
throwIfAborted(signal);
|
|
153
|
+
return Promise.resolve();
|
|
154
|
+
}
|
|
155
|
+
return new Promise((resolve, reject) => {
|
|
156
|
+
const timer = setTimeout(() => { cleanup(); resolve(); }, ms);
|
|
157
|
+
const onAbort = () => { cleanup(); reject(cancelled(signal?.reason)); };
|
|
158
|
+
const cleanup = () => { clearTimeout(timer); signal?.removeEventListener('abort', onAbort); };
|
|
159
|
+
signal?.addEventListener('abort', onAbort, { once: true });
|
|
160
|
+
});
|
|
161
|
+
}
|
|
162
|
+
async function boundedText(response, signal) {
|
|
163
|
+
const declared = Number(response.headers.get('content-length'));
|
|
164
|
+
if (Number.isFinite(declared) && declared > MAX_RESPONSE_BYTES) {
|
|
165
|
+
await discard(response);
|
|
166
|
+
throw new WebError('Codex Web Search response exceeded the safe size limit', 'CODEX_SEARCH_RESPONSE_TOO_LARGE');
|
|
167
|
+
}
|
|
168
|
+
if (response.body === null)
|
|
169
|
+
return '';
|
|
170
|
+
const reader = response.body.getReader();
|
|
171
|
+
const decoder = new TextDecoder();
|
|
172
|
+
let bytes = 0;
|
|
173
|
+
let text = '';
|
|
174
|
+
try {
|
|
175
|
+
while (true) {
|
|
176
|
+
throwIfAborted(signal);
|
|
177
|
+
const chunk = await reader.read();
|
|
178
|
+
if (chunk.done)
|
|
179
|
+
break;
|
|
180
|
+
bytes += chunk.value.byteLength;
|
|
181
|
+
if (bytes > MAX_RESPONSE_BYTES)
|
|
182
|
+
throw new WebError('Codex Web Search response exceeded the safe size limit', 'CODEX_SEARCH_RESPONSE_TOO_LARGE');
|
|
183
|
+
text += decoder.decode(chunk.value, { stream: true });
|
|
184
|
+
}
|
|
185
|
+
return text + decoder.decode();
|
|
186
|
+
}
|
|
187
|
+
catch (cause) {
|
|
188
|
+
if (signal?.aborted)
|
|
189
|
+
throw cancelled(cause);
|
|
190
|
+
throw cause;
|
|
191
|
+
}
|
|
192
|
+
finally {
|
|
193
|
+
try {
|
|
194
|
+
reader.releaseLock();
|
|
195
|
+
}
|
|
196
|
+
catch { /* best effort */ }
|
|
197
|
+
}
|
|
198
|
+
}
|
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ChatGPT/Codex subscription provider: OAuth against auth.openai.com with the
|
|
3
|
+
* Codex CLI client id, and streaming against the ChatGPT backend Responses
|
|
4
|
+
* endpoint.
|
|
5
|
+
*/
|
|
6
|
+
import { LlmAdapter } from '@deepseek-ai/dsh-llm';
|
|
7
|
+
import type { GenerateOptions, LlmModelInfo, LlmProviderInfo, LlmResolvedModelInfo, StreamChunk } from '@deepseek-ai/dsh-llm';
|
|
8
|
+
import type { FlowSpec } from '../auth/oauth-flow.js';
|
|
9
|
+
import type { CodexSession } from '../auth/store.js';
|
|
10
|
+
import type { PoolAdapter } from './pool.js';
|
|
11
|
+
import type { AttachmentStore } from '@deepseek-ai/dsh-attachment';
|
|
12
|
+
import type { ResponsesRequestInput } from '../translate/responses.js';
|
|
13
|
+
import { AccountTokenManager } from './accounts.js';
|
|
14
|
+
import type { CatalogPersistence, DiscoveredModel, FetchFn, ModelEntry, ProviderUsage } from './common.js';
|
|
15
|
+
import type { RateLimitResetReader, RateLimitWait } from './rate-limit.js';
|
|
16
|
+
export declare const CODEX_CLIENT_ID = "app_EMoamEEZ73f0CkXaXp7hrann";
|
|
17
|
+
export declare const CODEX_AUTHORIZE_URL = "https://auth.openai.com/oauth/authorize";
|
|
18
|
+
export declare const CODEX_TOKEN_URL = "https://auth.openai.com/oauth/token";
|
|
19
|
+
export declare const CODEX_API_URL = "https://chatgpt.com/backend-api/codex/responses";
|
|
20
|
+
/** Refresh when the access token has less than this much life left. */
|
|
21
|
+
export declare const CODEX_PREEMPT_MS: number;
|
|
22
|
+
/**
|
|
23
|
+
* Reads the reset instant of the Codex window that rejected a request.
|
|
24
|
+
*
|
|
25
|
+
* Body only. The `x-codex-{primary,secondary}-reset-after-seconds` headers are
|
|
26
|
+
* rollover snapshots the backend attaches to every response, one per window,
|
|
27
|
+
* so they say nothing about which window refused: a burst 429 that would clear
|
|
28
|
+
* in seconds still carries a primary rollover hours out, and reading it would
|
|
29
|
+
* park the turn for those hours. They reach the operator through
|
|
30
|
+
* `rateLimitDiagnostics` instead.
|
|
31
|
+
*/
|
|
32
|
+
export declare const codexRateLimitReset: RateLimitResetReader;
|
|
33
|
+
/**
|
|
34
|
+
* Fast tier (the codex CLI's "fast mode"): the Responses `service_tier` wire
|
|
35
|
+
* value for priority processing, mirroring codex-rs
|
|
36
|
+
* `ServiceTier::Fast.request_value()`. The legacy catalog spelling is the
|
|
37
|
+
* `additional_speed_tiers` entry "fast".
|
|
38
|
+
*/
|
|
39
|
+
export declare const CODEX_FAST_SERVICE_TIER = "priority";
|
|
40
|
+
/** One session's speed choice: standard routing or the fast (priority) tier. */
|
|
41
|
+
export type CodexSpeedTier = 'standard' | 'fast';
|
|
42
|
+
/** Static codex flow facts for the OAuth flow engine. */
|
|
43
|
+
export declare const codexFlow: FlowSpec;
|
|
44
|
+
/** User identity claims decoded from a codex id token. */
|
|
45
|
+
export interface CodexProfileClaims {
|
|
46
|
+
emailAddress?: string;
|
|
47
|
+
planType?: string;
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Decode the user-identity claims of a codex id token (pure, cheap — no
|
|
51
|
+
* verification, same trust posture as {@link accountIdOf}). Claim paths
|
|
52
|
+
* mirror codex-rs `login/src/token_data.rs`: the email is the top-level
|
|
53
|
+
* `email` claim, falling back to `https://api.openai.com/profile`.email; the
|
|
54
|
+
* plan is `https://api.openai.com/auth`.chatgpt_plan_type.
|
|
55
|
+
* @param idToken - a stored or freshly issued id token, when present.
|
|
56
|
+
* @returns whichever claims the token carried; empty when undecodable.
|
|
57
|
+
*/
|
|
58
|
+
export declare function codexProfileClaims(idToken: string | undefined): CodexProfileClaims;
|
|
59
|
+
/**
|
|
60
|
+
* Exchange an authorization code for a codex session (form-encoded grant).
|
|
61
|
+
* @param code - the authorization code from the callback.
|
|
62
|
+
* @param verifier - the PKCE verifier minted for the attempt.
|
|
63
|
+
* @param redirectUri - the attempt's redirect URI.
|
|
64
|
+
* @returns the session to store.
|
|
65
|
+
*/
|
|
66
|
+
export declare function exchangeCodexCode(code: string, verifier: string, redirectUri: string): Promise<CodexSession>;
|
|
67
|
+
/**
|
|
68
|
+
* Refresh a codex session (JSON grant — unlike the code exchange).
|
|
69
|
+
* @param session - the stored session.
|
|
70
|
+
* @returns the fresh session to store.
|
|
71
|
+
*/
|
|
72
|
+
export declare function refreshCodex(session: CodexSession): Promise<CodexSession>;
|
|
73
|
+
/**
|
|
74
|
+
* Whether a codex refresh failure means the login is permanently gone.
|
|
75
|
+
* @param error - the thrown refresh error.
|
|
76
|
+
* @returns true when re-login is the only fix.
|
|
77
|
+
*/
|
|
78
|
+
export declare function isCodexPermanentRefreshError(error: unknown): boolean;
|
|
79
|
+
export declare const CODEX_USAGE_URL = "https://chatgpt.com/backend-api/wham/usage";
|
|
80
|
+
/**
|
|
81
|
+
* Fetch the codex subscription usage from the ChatGPT backend wham/usage
|
|
82
|
+
* endpoint (the source of the codex CLI `/status` rate-limit lines). The
|
|
83
|
+
* windows are classified by their reported duration (`limit_window_seconds`)
|
|
84
|
+
* rather than by slot, since the backend has been observed to report the
|
|
85
|
+
* weekly lane as `primary_window` without a secondary window; slot order is
|
|
86
|
+
* kept only as a fallback when the duration is absent. The lookup itself
|
|
87
|
+
* consumes no rate-limit budget.
|
|
88
|
+
* @param session - the stored session (used as-is; never refreshed here).
|
|
89
|
+
* @param fetchFn - fetch implementation (injectable for tests).
|
|
90
|
+
* @param signal - caller cancellation from the RPC transport.
|
|
91
|
+
* @returns the mapped usage snapshot.
|
|
92
|
+
*/
|
|
93
|
+
export declare function fetchCodexUsage(session: CodexSession, fetchFn?: FetchFn, signal?: AbortSignal): Promise<ProviderUsage>;
|
|
94
|
+
export declare const CODEX_MODELS_URL = "https://chatgpt.com/backend-api/codex/models";
|
|
95
|
+
/**
|
|
96
|
+
* Client version sent on the /models catalog request. The backend gates the
|
|
97
|
+
* visible model list by client version. Verified 2026-09-05: the same account
|
|
98
|
+
* omitted GPT-6 Astra at 0.147.0 and listed it at stable CLI 0.153.4. This is
|
|
99
|
+
* not an entitlement guarantee; the server remains authoritative.
|
|
100
|
+
*/
|
|
101
|
+
export declare const CODEX_CLIENT_VERSION = "0.153.4";
|
|
102
|
+
/** Validate an explicit catalog compatibility version before using it on the wire. */
|
|
103
|
+
export declare function codexClientVersion(value?: string): string;
|
|
104
|
+
/**
|
|
105
|
+
* Fetch the live codex model catalog with the session's auth headers.
|
|
106
|
+
* @param session - the stored session (used as-is; never refreshed here).
|
|
107
|
+
* @param fetchFn - fetch implementation (injectable for tests).
|
|
108
|
+
* @param signal - caller cancellation (pool-assembly timeout).
|
|
109
|
+
* @param clientVersion - catalog compatibility version, not the plugin version.
|
|
110
|
+
* @returns discovered models: hidden entries dropped, sorted by priority.
|
|
111
|
+
*/
|
|
112
|
+
export declare function fetchCodexModels(session: CodexSession, fetchFn?: FetchFn, signal?: AbortSignal, clientVersion?: string): Promise<DiscoveredModel[]>;
|
|
113
|
+
/** Constructor dependencies for {@link CodexAdapter}. */
|
|
114
|
+
export interface CodexAdapterOptions {
|
|
115
|
+
/** Catalog compatibility version; defaults to the verified stable CLI version. */
|
|
116
|
+
clientVersion?: string;
|
|
117
|
+
/** Automatic lookup used only when no explicit compatibility version is set. */
|
|
118
|
+
resolveClientVersion?: () => Promise<string>;
|
|
119
|
+
models: readonly ModelEntry[];
|
|
120
|
+
streamIdleTimeoutMs: number;
|
|
121
|
+
tokens: AccountTokenManager<CodexSession>;
|
|
122
|
+
/** Late-bound pool facade (wired after adapter construction); pools list under their first member's provider. */
|
|
123
|
+
pool?: () => PoolAdapter | undefined;
|
|
124
|
+
/** Whether to fetch the live catalog when logged in (false when config `models` overrides). */
|
|
125
|
+
discovery: boolean;
|
|
126
|
+
/** Warning sink for discovery failures that fall back to the static catalog. */
|
|
127
|
+
onWarn?: (message: string) => void;
|
|
128
|
+
/** Fetch implementation for discovery (defaults to global fetch). */
|
|
129
|
+
fetchFn?: FetchFn;
|
|
130
|
+
/** Resolve the attachment service per request; absent means image requests fail loudly. */
|
|
131
|
+
resolveAttachments?: () => AttachmentStore | undefined;
|
|
132
|
+
/** Durable catalog store seeding capability metadata across restarts. */
|
|
133
|
+
catalogStore?: CatalogPersistence;
|
|
134
|
+
/** Durable store for one NON-default account's catalog (the default's lives in `catalogStore`). */
|
|
135
|
+
accountCatalogStore?: (account: string) => CatalogPersistence;
|
|
136
|
+
/** Per-account catalog bound for the picker union (defaults to {@link DISCOVERY_TIMEOUT_MS}). */
|
|
137
|
+
discoveryTimeoutMs?: number;
|
|
138
|
+
/** How long this route may hold a turn open waiting for a rate-limit window; defaults to waiting on, six-hour ceiling. */
|
|
139
|
+
rateLimit?: RateLimitWait;
|
|
140
|
+
/**
|
|
141
|
+
* Per-model default reasoning effort override (the Settings page's picker).
|
|
142
|
+
* Returns the user-configured default for one model, or undefined to follow
|
|
143
|
+
* the provider's own default.
|
|
144
|
+
*/
|
|
145
|
+
defaultEffortOf?: (model: string) => string | undefined;
|
|
146
|
+
contextWindowOf?: (model: string) => number | undefined;
|
|
147
|
+
/**
|
|
148
|
+
* Per-request speed lookup (the composer Speed toggle's host half). Returns
|
|
149
|
+
* whether this session's current choice sends the model on the fast tier;
|
|
150
|
+
* absent means every request stays on standard routing.
|
|
151
|
+
*/
|
|
152
|
+
speedFor?: (sessionId: string | undefined, model: string) => Promise<boolean> | boolean;
|
|
153
|
+
}
|
|
154
|
+
/** Text marking a repaired tool output as an unknown outcome; the model must verify before retrying. */
|
|
155
|
+
export declare const CODEX_UNKNOWN_TOOL_OUTCOME = "The tool call has no recorded result. Its outcome is unknown; verify external state before retrying any operation that may have side effects.";
|
|
156
|
+
/**
|
|
157
|
+
* Reconcile one Responses input's tool-call pairing after id normalization:
|
|
158
|
+
* every `function_call` gets an output and every `function_call_output`
|
|
159
|
+
* matches a call. Missing outputs become error-style outputs whose text marks
|
|
160
|
+
* the outcome unknown; orphan outputs are dropped. Duplicate calls of one id
|
|
161
|
+
* receive exactly one repair output. The request is local repair only: the
|
|
162
|
+
* durable history stays authoritative and unchanged.
|
|
163
|
+
* @param input - normalized Responses input items.
|
|
164
|
+
* @returns the same array when already balanced, otherwise a repaired array.
|
|
165
|
+
*/
|
|
166
|
+
export declare function reconcileResponsesToolCalls(input: ResponsesRequestInput['input']): ResponsesRequestInput['input'];
|
|
167
|
+
/**
|
|
168
|
+
* The Responses request body for one generation. A fast-tier request (the
|
|
169
|
+
* composer Speed toggle, the codex CLI's fast mode) carries
|
|
170
|
+
* `service_tier: priority`; the tier field is omitted entirely otherwise,
|
|
171
|
+
* matching the CLI (it never sends an explicit standard tier).
|
|
172
|
+
*/
|
|
173
|
+
export declare function codexRequestBody(options: GenerateOptions, resolved: ResponsesRequestInput, fast: boolean): Record<string, unknown>;
|
|
174
|
+
/** Codex wire adapter: one instance serves the `codex` provider route. */
|
|
175
|
+
export declare class CodexAdapter extends LlmAdapter {
|
|
176
|
+
private readonly options;
|
|
177
|
+
private readonly catalog;
|
|
178
|
+
/** In-memory catalogs for non-default accounts (the persisted cache is the default's). */
|
|
179
|
+
private readonly accountCatalogs;
|
|
180
|
+
/** Account whose snapshot currently lives in {@link catalog}; cleared on default change. */
|
|
181
|
+
private catalogOwner;
|
|
182
|
+
constructor(options: CodexAdapterOptions);
|
|
183
|
+
/** Discovery fetcher: resolves the session through the refresh-aware path. */
|
|
184
|
+
private fetchCatalog;
|
|
185
|
+
/** Drop cached catalogs after login/logout so the next list does not reuse a stale plan. */
|
|
186
|
+
clearAccountCatalog(account?: string): void;
|
|
187
|
+
/** Persisted cache for the default account; a throwaway cache for any other. */
|
|
188
|
+
private catalogFor;
|
|
189
|
+
/** Picker rows for discovered entries (the wire id doubles as the route id). */
|
|
190
|
+
private listed;
|
|
191
|
+
/**
|
|
192
|
+
* The last catalog one account successfully listed, without any network.
|
|
193
|
+
* Routing asks for this when live discovery times out: an account that
|
|
194
|
+
* listed a model minutes ago is still a better answer than "no models".
|
|
195
|
+
*/
|
|
196
|
+
lastKnownOwnModels(provider: string, account: string): Promise<readonly LlmModelInfo[] | undefined>;
|
|
197
|
+
providerInfo(provider: string): LlmProviderInfo;
|
|
198
|
+
providerRetryPolicy(provider: string): import("@deepseek-ai/dsh-llm").ResolvedRetryPolicy;
|
|
199
|
+
private staticModels;
|
|
200
|
+
listModels(provider: string): Promise<readonly LlmModelInfo[]>;
|
|
201
|
+
/** The provider's own catalog: union of every account, or one account when named. */
|
|
202
|
+
listOwnModels(provider: string, account?: string, signal?: AbortSignal): Promise<readonly LlmModelInfo[]>;
|
|
203
|
+
/**
|
|
204
|
+
* The discovered entry for one model. Resolved through the cache's
|
|
205
|
+
* stale-while-revalidate path so capability metadata stays stable across a
|
|
206
|
+
* long conversation: a discovered-only effort (one missing from the static
|
|
207
|
+
* CODEX_EFFORTS list) selected by the user must not vanish — and fail the
|
|
208
|
+
* call — just because the TTL lapsed mid-turn.
|
|
209
|
+
*/
|
|
210
|
+
private discovered;
|
|
211
|
+
/** Whether the discovered catalog advertises a fast tier for this model. */
|
|
212
|
+
supportsFastTier(model: string, account?: string): Promise<boolean>;
|
|
213
|
+
/** Ids of every discovered model with a fast tier (the Speed toggle's visibility list). */
|
|
214
|
+
fastCapableModels(): Promise<string[]>;
|
|
215
|
+
resolveModel(provider: string, model: string): Promise<LlmResolvedModelInfo>;
|
|
216
|
+
/** Capability resolution of the provider's own models (the pool resolves members here). */
|
|
217
|
+
resolveOwnModel(provider: string, model: string, account?: string): Promise<LlmResolvedModelInfo>;
|
|
218
|
+
/** Account-specific bounds; absent maximum conservatively keeps the advertised default. */
|
|
219
|
+
contextLimits(model: string, account?: string): Promise<{
|
|
220
|
+
default: number;
|
|
221
|
+
max: number;
|
|
222
|
+
}>;
|
|
223
|
+
private contextWindowFor;
|
|
224
|
+
stream(options: GenerateOptions): AsyncIterable<StreamChunk>;
|
|
225
|
+
/** Pool seam: stream through one specific account instead of the default. */
|
|
226
|
+
streamAccount(options: GenerateOptions, account: string): AsyncIterable<StreamChunk>;
|
|
227
|
+
private streamCore;
|
|
228
|
+
private request;
|
|
229
|
+
}
|