@push.rocks/smartai 2.3.0 → 4.0.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.
@@ -0,0 +1,249 @@
1
+ import * as fs from 'node:fs/promises';
2
+ import * as os from 'node:os';
3
+ import * as path from 'node:path';
4
+ import { parseOpenAiChatGptTokenInfo, refreshOpenAiChatGptTokenData, } from '../dist_ts/smartai.auth.openai.js';
5
+ const defaultSources = ['smartai', 'opencode', 'codex'];
6
+ const refreshWindowMs = 5 * 60 * 1000;
7
+ export const getDefaultOpenAiChatGptAuthPath = (source, homeDir = os.homedir()) => {
8
+ switch (source) {
9
+ case 'smartai':
10
+ return path.join(homeDir, '.git.zone', 'ide', 'openai-chatgpt-auth.json');
11
+ case 'opencode':
12
+ return path.join(homeDir, '.local', 'share', 'opencode', 'auth.json');
13
+ case 'codex':
14
+ return path.join(homeDir, '.codex', 'auth.json');
15
+ default:
16
+ throw new Error(`Unsupported OpenAI ChatGPT auth source: ${source}`);
17
+ }
18
+ };
19
+ export const normalizeOpenAiChatGptAuth = (input, format = 'auto') => {
20
+ if (format === 'auto') {
21
+ return normalizeOpenAiChatGptAuth(input, 'smartai')
22
+ ?? normalizeOpenAiChatGptAuth(input, 'opencode')
23
+ ?? normalizeOpenAiChatGptAuth(input, 'codex');
24
+ }
25
+ if (!isRecord(input))
26
+ return undefined;
27
+ if (format === 'opencode') {
28
+ return normalizeOpenCodeAuth(input);
29
+ }
30
+ return normalizeTokenObject(isRecord(input.tokens) ? input.tokens : input);
31
+ };
32
+ export const readOpenAiChatGptAuthFile = async (filePath, format = 'auto') => {
33
+ const parsed = JSON.parse(await fs.readFile(filePath, 'utf8'));
34
+ return normalizeOpenAiChatGptAuth(parsed, format);
35
+ };
36
+ export const inspectOpenAiChatGptAuthSources = async (options = {}) => {
37
+ const now = options.now ?? new Date();
38
+ const sourceConfigs = normalizeSourceConfigs(options.sources, options.homeDir);
39
+ return Promise.all(sourceConfigs.map(async (sourceConfig) => {
40
+ try {
41
+ const tokenData = await readOpenAiChatGptAuthFile(sourceConfig.filePath, sourceConfig.format ?? sourceConfig.source);
42
+ if (!tokenData) {
43
+ return {
44
+ source: sourceConfig.source,
45
+ filePath: sourceConfig.filePath,
46
+ exists: true,
47
+ usable: false,
48
+ error: 'No OpenAI ChatGPT auth token found in file.',
49
+ };
50
+ }
51
+ return toInspection(sourceConfig.source, sourceConfig.filePath, tokenData, now);
52
+ }
53
+ catch (error) {
54
+ const nodeError = error;
55
+ return {
56
+ source: sourceConfig.source,
57
+ filePath: sourceConfig.filePath,
58
+ exists: nodeError.code !== 'ENOENT',
59
+ usable: false,
60
+ error: nodeError.code === 'ENOENT' ? undefined : nodeError.message,
61
+ };
62
+ }
63
+ }));
64
+ };
65
+ export const resolveOpenAiChatGptAuth = async (options = {}) => {
66
+ const now = options.now ?? new Date();
67
+ const sourceConfigs = normalizeSourceConfigs(options.sources, options.homeDir);
68
+ const refresh = options.refresh ?? 'ifNeeded';
69
+ for (const sourceConfig of sourceConfigs) {
70
+ let tokenData;
71
+ try {
72
+ tokenData = await readOpenAiChatGptAuthFile(sourceConfig.filePath, sourceConfig.format ?? sourceConfig.source);
73
+ }
74
+ catch (error) {
75
+ const nodeError = error;
76
+ if (nodeError.code === 'ENOENT')
77
+ continue;
78
+ continue;
79
+ }
80
+ if (!tokenData)
81
+ continue;
82
+ const shouldRefresh = refresh === 'ifNeeded' && shouldRefreshToken(tokenData, now);
83
+ const writeBack = sourceConfig.writeBack ?? options.writeBack?.[sourceConfig.source] ?? sourceConfig.source === 'smartai';
84
+ if (!shouldRefresh) {
85
+ return { source: sourceConfig.source, filePath: sourceConfig.filePath, tokenData, refreshed: false };
86
+ }
87
+ if (!writeBack) {
88
+ if (!isExpired(tokenData, now)) {
89
+ return { source: sourceConfig.source, filePath: sourceConfig.filePath, tokenData, refreshed: false };
90
+ }
91
+ continue;
92
+ }
93
+ try {
94
+ const refreshed = await refreshOpenAiChatGptTokenData(tokenData, options.authOptions ?? {});
95
+ await writeOpenAiChatGptAuthFile(sourceConfig.filePath, refreshed, sourceConfig.format ?? sourceConfig.source);
96
+ return { source: sourceConfig.source, filePath: sourceConfig.filePath, tokenData: refreshed, refreshed: true };
97
+ }
98
+ catch {
99
+ continue;
100
+ }
101
+ }
102
+ return undefined;
103
+ };
104
+ export const writeOpenAiChatGptAuthFile = async (filePath, tokenData, format = 'smartai') => {
105
+ const current = await readJsonFileIfExists(filePath);
106
+ const payload = format === 'opencode'
107
+ ? toOpenCodeAuthFile(current, tokenData)
108
+ : format === 'codex'
109
+ ? toCodexAuthFile(current, tokenData)
110
+ : toSmartAiAuthFile(tokenData);
111
+ await writeJsonAtomic(filePath, payload);
112
+ };
113
+ const normalizeSourceConfigs = (sources, homeDir = os.homedir()) => {
114
+ return (sources ?? defaultSources).map((sourceInput) => {
115
+ const sourceConfig = typeof sourceInput === 'string' ? { source: sourceInput } : sourceInput;
116
+ return {
117
+ source: sourceConfig.source,
118
+ filePath: sourceConfig.filePath ?? getDefaultOpenAiChatGptAuthPath(sourceConfig.source, homeDir),
119
+ format: sourceConfig.format ?? sourceConfig.source,
120
+ writeBack: sourceConfig.writeBack,
121
+ };
122
+ });
123
+ };
124
+ const toInspection = (source, filePath, tokenData, now) => {
125
+ const expired = isExpired(tokenData, now);
126
+ return {
127
+ source,
128
+ filePath,
129
+ exists: true,
130
+ usable: !expired,
131
+ expired,
132
+ accountId: tokenData.accountId ?? tokenData.tokenInfo.chatgptAccountId,
133
+ email: tokenData.tokenInfo.email,
134
+ plan: tokenData.tokenInfo.chatgptPlanType,
135
+ expiresAt: tokenData.tokenInfo.expiresAt,
136
+ };
137
+ };
138
+ const normalizeTokenObject = (input) => {
139
+ const accessToken = stringValue(input.accessToken) ?? stringValue(input.access_token);
140
+ const refreshToken = stringValue(input.refreshToken) ?? stringValue(input.refresh_token);
141
+ const idToken = stringValue(input.idToken) ?? stringValue(input.id_token) ?? stringValue(input.tokenInfo?.rawJwt);
142
+ const accountId = stringValue(input.accountId) ?? stringValue(input.account_id);
143
+ return createTokenDataFromValues({ accessToken, refreshToken, idToken, accountId });
144
+ };
145
+ const normalizeOpenCodeAuth = (input) => {
146
+ if (!isRecord(input.openai))
147
+ return undefined;
148
+ const accessToken = stringValue(input.openai.access);
149
+ const refreshToken = stringValue(input.openai.refresh);
150
+ const accountId = stringValue(input.openai.accountId);
151
+ const expiresAt = typeof input.openai.expires === 'number' ? new Date(input.openai.expires).toISOString() : undefined;
152
+ return createTokenDataFromValues({ accessToken, refreshToken, accountId, fallbackExpiresAt: expiresAt });
153
+ };
154
+ const createTokenDataFromValues = (input) => {
155
+ if (!input.accessToken || !input.refreshToken)
156
+ return undefined;
157
+ const parseToken = input.idToken ?? input.accessToken;
158
+ const tokenInfo = parseTokenInfo(parseToken, input.accountId, input.fallbackExpiresAt);
159
+ return {
160
+ accessToken: input.accessToken,
161
+ refreshToken: input.refreshToken,
162
+ idToken: input.idToken,
163
+ accountId: input.accountId ?? tokenInfo.chatgptAccountId,
164
+ tokenInfo,
165
+ };
166
+ };
167
+ const parseTokenInfo = (token, accountId, fallbackExpiresAt) => {
168
+ try {
169
+ const tokenInfo = parseOpenAiChatGptTokenInfo(token);
170
+ return {
171
+ ...tokenInfo,
172
+ chatgptAccountId: tokenInfo.chatgptAccountId ?? accountId,
173
+ expiresAt: tokenInfo.expiresAt ?? fallbackExpiresAt,
174
+ };
175
+ }
176
+ catch {
177
+ return {
178
+ chatgptAccountId: accountId,
179
+ chatgptAccountIsFedramp: false,
180
+ expiresAt: fallbackExpiresAt,
181
+ rawJwt: token,
182
+ };
183
+ }
184
+ };
185
+ const toSmartAiAuthFile = (tokenData) => ({
186
+ accessToken: tokenData.accessToken,
187
+ refreshToken: tokenData.refreshToken,
188
+ idToken: tokenData.idToken,
189
+ accountId: tokenData.accountId,
190
+ tokenInfo: tokenData.tokenInfo,
191
+ });
192
+ const toCodexAuthFile = (current, tokenData) => ({
193
+ ...current,
194
+ OPENAI_API_KEY: current.OPENAI_API_KEY ?? null,
195
+ tokens: {
196
+ ...(isRecord(current.tokens) ? current.tokens : {}),
197
+ id_token: tokenData.idToken,
198
+ access_token: tokenData.accessToken,
199
+ refresh_token: tokenData.refreshToken,
200
+ account_id: tokenData.accountId ?? tokenData.tokenInfo.chatgptAccountId,
201
+ },
202
+ last_refresh: new Date().toISOString(),
203
+ });
204
+ const toOpenCodeAuthFile = (current, tokenData) => ({
205
+ ...current,
206
+ openai: {
207
+ ...(isRecord(current.openai) ? current.openai : {}),
208
+ type: 'oauth',
209
+ refresh: tokenData.refreshToken,
210
+ access: tokenData.accessToken,
211
+ expires: tokenData.tokenInfo.expiresAt ? Date.parse(tokenData.tokenInfo.expiresAt) : undefined,
212
+ accountId: tokenData.accountId ?? tokenData.tokenInfo.chatgptAccountId,
213
+ },
214
+ });
215
+ const shouldRefreshToken = (tokenData, now) => {
216
+ if (!tokenData.tokenInfo.expiresAt)
217
+ return false;
218
+ return Date.parse(tokenData.tokenInfo.expiresAt) - now.getTime() < refreshWindowMs;
219
+ };
220
+ const isExpired = (tokenData, now) => {
221
+ if (!tokenData.tokenInfo.expiresAt)
222
+ return false;
223
+ return Date.parse(tokenData.tokenInfo.expiresAt) <= now.getTime();
224
+ };
225
+ const readJsonFileIfExists = async (filePath) => {
226
+ try {
227
+ const parsed = JSON.parse(await fs.readFile(filePath, 'utf8'));
228
+ return isRecord(parsed) ? parsed : {};
229
+ }
230
+ catch (error) {
231
+ const nodeError = error;
232
+ if (nodeError.code === 'ENOENT')
233
+ return {};
234
+ throw error;
235
+ }
236
+ };
237
+ const writeJsonAtomic = async (filePath, payload) => {
238
+ const tempPath = `${filePath}.${process.pid}.${Date.now()}.tmp`;
239
+ await fs.mkdir(path.dirname(filePath), { recursive: true, mode: 0o700 });
240
+ await fs.writeFile(tempPath, `${JSON.stringify(payload, undefined, 2)}\n`, { mode: 0o600 });
241
+ await fs.rename(tempPath, filePath);
242
+ };
243
+ const isRecord = (value) => {
244
+ return !!value && typeof value === 'object' && !Array.isArray(value);
245
+ };
246
+ const stringValue = (value) => {
247
+ return typeof value === 'string' && value.length > 0 ? value : undefined;
248
+ };
249
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi90c19vcGVuYWlfY2hhdGdwdF9hdXRoL2luZGV4LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sS0FBSyxFQUFFLE1BQU0sa0JBQWtCLENBQUM7QUFDdkMsT0FBTyxLQUFLLEVBQUUsTUFBTSxTQUFTLENBQUM7QUFDOUIsT0FBTyxLQUFLLElBQUksTUFBTSxXQUFXLENBQUM7QUFDbEMsT0FBTyxFQUNMLDJCQUEyQixFQUMzQiw2QkFBNkIsR0FDOUIsTUFBTSw4QkFBOEIsQ0FBQztBQXdEdEMsTUFBTSxjQUFjLEdBQStCLENBQUMsU0FBUyxFQUFFLFVBQVUsRUFBRSxPQUFPLENBQUMsQ0FBQztBQUNwRixNQUFNLGVBQWUsR0FBRyxDQUFDLEdBQUcsRUFBRSxHQUFHLElBQUksQ0FBQztBQUV0QyxNQUFNLENBQUMsTUFBTSwrQkFBK0IsR0FBRyxDQUM3QyxNQUFnQyxFQUNoQyxPQUFPLEdBQUcsRUFBRSxDQUFDLE9BQU8sRUFBRSxFQUNkLEVBQUU7SUFDVixRQUFRLE1BQU0sRUFBRSxDQUFDO1FBQ2YsS0FBSyxTQUFTO1lBQ1osT0FBTyxJQUFJLENBQUMsSUFBSSxDQUFDLE9BQU8sRUFBRSxXQUFXLEVBQUUsS0FBSyxFQUFFLDBCQUEwQixDQUFDLENBQUM7UUFDNUUsS0FBSyxVQUFVO1lBQ2IsT0FBTyxJQUFJLENBQUMsSUFBSSxDQUFDLE9BQU8sRUFBRSxRQUFRLEVBQUUsT0FBTyxFQUFFLFVBQVUsRUFBRSxXQUFXLENBQUMsQ0FBQztRQUN4RSxLQUFLLE9BQU87WUFDVixPQUFPLElBQUksQ0FBQyxJQUFJLENBQUMsT0FBTyxFQUFFLFFBQVEsRUFBRSxXQUFXLENBQUMsQ0FBQztRQUNuRDtZQUNFLE1BQU0sSUFBSSxLQUFLLENBQUMsMkNBQTJDLE1BQXNCLEVBQUUsQ0FBQyxDQUFDO0lBQ3pGLENBQUM7QUFDSCxDQUFDLENBQUM7QUFFRixNQUFNLENBQUMsTUFBTSww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QUFRLEVBQUUsR0FBRyxJQUFJLENBQUMsU0FBUyxDQUFDLE9BQU8sRUFBRSxTQUFTLEVBQUUsQ0FBQyxDQUFDLElBQUksRUFBRSxFQUFFLElBQUksRUFBRSxLQUFLLEVBQUUsQ0FBQyxDQUFDO0lBQzVGLE1BQU0sRUFBRSxDQUFDLE1BQU0sQ0FBQyxRQUFRLEVBQUUsUUFBUSxDQUFDLENBQUM7QUFDdEMsQ0FBQyxDQUFDO0FBRUYsTUFBTSxRQUFRLEdBQUcsQ0FBQyxLQUFjLEVBQW9DLEVBQUU7SUFDcEUsT0FBTyxDQUFDLENBQUMsS0FBSyxJQUFJLE9BQU8sS0FBSyxLQUFLLFFBQVEsSUFBSSxDQUFDLEtBQUssQ0FBQyxPQUFPLENBQUMsS0FBSyxDQUFDLENBQUM7QUFDdkUsQ0FBQyxDQUFDO0FBRUYsTUFBTSxXQUFXLEdBQUcsQ0FBQyxLQUFjLEVBQXNCLEVBQUU7SUFDekQsT0FBTyxPQUFPLEtBQUssS0FBSyxRQUFRLElBQUksS0FBSyxDQUFDLE1BQU0sR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsU0FBUyxDQUFDO0FBQzNFLENBQUMsQ0FBQyJ9
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@push.rocks/smartai",
3
- "version": "2.3.0",
3
+ "version": "4.0.1",
4
4
  "private": false,
5
5
  "description": "Provider registry and capability utilities for ai-sdk (Vercel AI SDK). Core export returns LanguageModel; subpath exports provide vision, audio, image, document and research capabilities.",
6
6
  "main": "dist_ts/index.js",
@@ -30,6 +30,10 @@
30
30
  "./research": {
31
31
  "import": "./dist_ts_research/index.js",
32
32
  "types": "./dist_ts_research/index.d.ts"
33
+ },
34
+ "./openai-chatgpt-auth": {
35
+ "import": "./dist_ts_openai_chatgpt_auth/index.js",
36
+ "types": "./dist_ts_openai_chatgpt_auth/index.d.ts"
33
37
  }
34
38
  },
35
39
  "author": "Task Venture Capital GmbH",
@@ -78,6 +82,7 @@
78
82
  "ts_image/**/*",
79
83
  "ts_document/**/*",
80
84
  "ts_research/**/*",
85
+ "ts_openai_chatgpt_auth/**/*",
81
86
  "dist_*/**/*",
82
87
  "assets/**/*",
83
88
  ".smartconfig.json",
package/readme.hints.md CHANGED
@@ -10,7 +10,8 @@ The package is a **provider registry** built on the Vercel AI SDK (`ai` v6). The
10
10
  - Providers: anthropic, openai, google, groq, mistral, xai, perplexity, ollama
11
11
  - Anthropic prompt caching via `wrapLanguageModel` middleware (enabled by default)
12
12
  - Custom Ollama provider implementing `LanguageModelV3` directly (for think, num_ctx support)
13
- - OpenAI ChatGPT/Max device-code auth in `smartai.auth.openai.ts`; `openAiMaxAuth` routes OpenAI models to the ChatGPT Codex backend
13
+ - OpenAI ChatGPT/Codex device-code auth in `smartai.auth.openai.ts`; `openAiChatGptAuth` routes OpenAI models to the ChatGPT Codex backend
14
+ - Node-only local auth source helpers live in `ts_openai_chatgpt_auth/` and support SmartAI, OpenCode, and Codex auth file formats
14
15
 
15
16
  ### Subpath Exports
16
17
  - `@push.rocks/smartai/vision` — `analyzeImage()` using `generateText` with image content
package/readme.md CHANGED
@@ -107,29 +107,60 @@ console.log(result.text);
107
107
 
108
108
  OpenAI `reasoningEffort` supports `'none'`, `'minimal'`, `'low'`, `'medium'`, `'high'`, and `'xhigh'`. Model IDs are accepted as strings, so new IDs like `'gpt-5.5'` can be used before upstream model unions are updated.
109
109
 
110
- ### OpenAI Max / ChatGPT Auth
110
+ ### OpenAI ChatGPT / Codex Auth
111
111
 
112
- SmartAI can request ChatGPT subscription-backed Codex credentials with OpenAI's device-code flow. The returned credentials are passed to `getModel()` through `openAiMaxAuth`; SmartAI then routes OpenAI model calls through the ChatGPT Codex backend with the required account headers.
112
+ SmartAI can request ChatGPT subscription-backed Codex credentials with OpenAI's device-code flow. The returned credentials are passed to `getModel()` through `openAiChatGptAuth`; SmartAI then routes OpenAI model calls through the ChatGPT Codex backend with the required account headers.
113
113
 
114
114
  ```typescript
115
115
  import {
116
- completeOpenAiMaxDeviceCodeLogin,
116
+ completeOpenAiChatGptDeviceCodeLogin,
117
117
  getModel,
118
- requestOpenAiMaxDeviceCode,
118
+ requestOpenAiChatGptDeviceCode,
119
119
  } from '@push.rocks/smartai';
120
120
 
121
- const deviceCode = await requestOpenAiMaxDeviceCode();
121
+ const deviceCode = await requestOpenAiChatGptDeviceCode();
122
122
  console.log(`Open ${deviceCode.verificationUrl} and enter ${deviceCode.userCode}`);
123
123
 
124
- const openAiMaxAuth = await completeOpenAiMaxDeviceCodeLogin(deviceCode);
124
+ const openAiChatGptAuth = await completeOpenAiChatGptDeviceCodeLogin(deviceCode);
125
125
  const model = getModel({
126
126
  provider: 'openai',
127
127
  model: 'gpt-5.5',
128
- openAiMaxAuth,
128
+ openAiChatGptAuth,
129
129
  });
130
130
  ```
131
131
 
132
- Use `refreshOpenAiMaxTokenData(openAiMaxAuth)` before stored credentials expire, or after receiving an unauthorized response.
132
+ Use `refreshOpenAiChatGptTokenData(openAiChatGptAuth)` before stored credentials expire, or after receiving an unauthorized response.
133
+
134
+ Node.js consumers can inspect and resolve local ChatGPT auth files through the Node-only subpath. This supports SmartAI's canonical auth file, OpenCode's `~/.local/share/opencode/auth.json`, and Codex's `~/.codex/auth.json` without exposing token values in inspection results.
135
+
136
+ ```typescript
137
+ import {
138
+ inspectOpenAiChatGptAuthSources,
139
+ resolveOpenAiChatGptAuth,
140
+ } from '@push.rocks/smartai/openai-chatgpt-auth';
141
+
142
+ const sources = await inspectOpenAiChatGptAuthSources({
143
+ sources: ['smartai', 'opencode', 'codex'],
144
+ });
145
+
146
+ const resolved = await resolveOpenAiChatGptAuth({
147
+ sources: ['smartai', 'opencode', 'codex'],
148
+ refresh: 'ifNeeded',
149
+ writeBack: {
150
+ smartai: true,
151
+ opencode: false,
152
+ codex: false,
153
+ },
154
+ });
155
+
156
+ if (resolved) {
157
+ const model = getModel({
158
+ provider: 'openai',
159
+ model: 'gpt-5.5',
160
+ openAiChatGptAuth: resolved.tokenData,
161
+ });
162
+ }
163
+ ```
133
164
 
134
165
  ### Re-exported AI SDK Functions
135
166
 
@@ -3,6 +3,6 @@
3
3
  */
4
4
  export const commitinfo = {
5
5
  name: '@push.rocks/smartai',
6
- version: '2.3.0',
6
+ version: '4.0.1',
7
7
  description: 'Provider registry and capability utilities for ai-sdk (Vercel AI SDK). Core export returns LanguageModel; subpath exports provide vision, audio, image, document and research capabilities.'
8
8
  }
package/ts/index.ts CHANGED
@@ -1,13 +1,13 @@
1
1
  export { getModel, getModelSetup } from './smartai.classes.smartai.js';
2
2
  export type {
3
3
  IOpenAiProviderOptions,
4
- IOpenAiMaxAuthCredentials,
5
- IOpenAiMaxAuthOptions,
6
- IOpenAiMaxCompleteDeviceCodeOptions,
7
- IOpenAiMaxDeviceCode,
8
- IOpenAiMaxDeviceCodePollOptions,
9
- IOpenAiMaxIdTokenInfo,
10
- IOpenAiMaxTokenData,
4
+ IOpenAiChatGptAuthCredentials,
5
+ IOpenAiChatGptAuthOptions,
6
+ IOpenAiChatGptCompleteDeviceCodeOptions,
7
+ IOpenAiChatGptDeviceCode,
8
+ IOpenAiChatGptDeviceCodePollOptions,
9
+ IOpenAiChatGptTokenData,
10
+ IOpenAiChatGptTokenInfo,
11
11
  ISmartAiModelSetup,
12
12
  ISmartAiOptions,
13
13
  TOpenAiReasoningEffort,
@@ -36,21 +36,21 @@ export type {
36
36
  } from './smartai.cache.js';
37
37
  export { createOllamaModel } from './smartai.provider.ollama.js';
38
38
  export {
39
- OPENAI_MAX_AUTH_ISSUER,
40
- OPENAI_MAX_CLIENT_ID,
41
- OPENAI_MAX_CODEX_BASE_URL,
42
- OPENAI_MAX_DEFAULT_ORIGINATOR,
43
- OpenAiMaxAuthError,
44
- completeOpenAiMaxDeviceCodeLogin,
45
- createOpenAiMaxProviderSettings,
46
- ensureOpenAiMaxWorkspaceAllowed,
47
- exchangeOpenAiMaxAuthorizationCode,
48
- parseOpenAiMaxIdToken,
49
- pollOpenAiMaxDeviceCode,
50
- refreshOpenAiMaxTokenData,
51
- requestOpenAiMaxDeviceCode,
39
+ OPENAI_CHATGPT_AUTH_ISSUER,
40
+ OPENAI_CHATGPT_CLIENT_ID,
41
+ OPENAI_CHATGPT_CODEX_BASE_URL,
42
+ OPENAI_CHATGPT_DEFAULT_ORIGINATOR,
43
+ OpenAiChatGptAuthError,
44
+ completeOpenAiChatGptDeviceCodeLogin,
45
+ createOpenAiChatGptProviderSettings,
46
+ ensureOpenAiChatGptWorkspaceAllowed,
47
+ exchangeOpenAiChatGptAuthorizationCode,
48
+ parseOpenAiChatGptTokenInfo,
49
+ pollOpenAiChatGptDeviceCode,
50
+ refreshOpenAiChatGptTokenData,
51
+ requestOpenAiChatGptDeviceCode,
52
52
  } from './smartai.auth.openai.js';
53
- export type { IOpenAiMaxAuthorizationCode } from './smartai.auth.openai.js';
53
+ export type { IOpenAiChatGptAuthorizationCode } from './smartai.auth.openai.js';
54
54
 
55
55
  // Re-export commonly used ai-sdk functions for consumer convenience
56
56
  export { generateText, streamText, tool, jsonSchema } from 'ai';