egaki 0.3.0 → 0.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +51 -0
- package/README.md +15 -0
- package/dist/chatgpt-auth.d.ts +25 -0
- package/dist/chatgpt-auth.d.ts.map +1 -0
- package/dist/chatgpt-auth.js +18 -11
- package/dist/cli.js +234 -15
- package/dist/credentials.d.ts +17 -4
- package/dist/credentials.d.ts.map +1 -1
- package/dist/credentials.js +50 -10
- package/dist/login.d.ts +1 -1
- package/dist/login.d.ts.map +1 -1
- package/dist/login.js +44 -3
- package/dist/model-catalog.d.ts.map +1 -1
- package/dist/model-catalog.js +36 -3
- package/dist/models.d.ts +5 -0
- package/dist/models.d.ts.map +1 -1
- package/dist/models.js +11 -1
- package/package.json +3 -2
- package/src/chatgpt-auth.ts +387 -0
- package/src/cli.ts +304 -18
- package/src/credentials.ts +70 -17
- package/src/login.ts +49 -4
- package/src/model-catalog.ts +38 -3
- package/src/models.ts +11 -1
package/dist/credentials.js
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
// Credential storage for egaki.
|
|
2
2
|
// Reads and writes API keys from ~/.config/egaki/credentials.json.
|
|
3
3
|
// Keys are stored per-provider and injected as env vars at runtime.
|
|
4
|
+
//
|
|
5
|
+
// Most providers store a plain API key string. The 'chatgpt' provider stores
|
|
6
|
+
// a structured ChatGptAuth object with OAuth tokens for the Codex backend flow.
|
|
4
7
|
import fs from 'node:fs';
|
|
5
8
|
import path from 'node:path';
|
|
6
9
|
import os from 'node:os';
|
|
@@ -13,6 +16,12 @@ export const PROVIDERS = {
|
|
|
13
16
|
label: 'Egaki (all models, one subscription)',
|
|
14
17
|
hint: 'Subscribe at https://egaki.org/buy or run: egaki subscribe',
|
|
15
18
|
},
|
|
19
|
+
chatgpt: {
|
|
20
|
+
envVar: 'OPENAI_API_KEY',
|
|
21
|
+
label: 'ChatGPT (use your subscription)',
|
|
22
|
+
hint: 'Sign in with your ChatGPT account via browser',
|
|
23
|
+
oauth: true,
|
|
24
|
+
},
|
|
16
25
|
google: {
|
|
17
26
|
envVar: 'GOOGLE_GENERATIVE_AI_API_KEY',
|
|
18
27
|
label: 'Google AI (Gemini, Imagen)',
|
|
@@ -25,7 +34,7 @@ export const PROVIDERS = {
|
|
|
25
34
|
},
|
|
26
35
|
openai: {
|
|
27
36
|
envVar: 'OPENAI_API_KEY',
|
|
28
|
-
label: 'OpenAI (
|
|
37
|
+
label: 'OpenAI (API key)',
|
|
29
38
|
hint: 'Get your key at https://platform.openai.com/api-keys',
|
|
30
39
|
},
|
|
31
40
|
replicate: {
|
|
@@ -70,6 +79,19 @@ export function saveProviderKey(provider, key) {
|
|
|
70
79
|
creds[provider] = key;
|
|
71
80
|
writeCredentials(creds);
|
|
72
81
|
}
|
|
82
|
+
export function saveChatGptAuth(auth) {
|
|
83
|
+
const creds = readCredentials();
|
|
84
|
+
creds['chatgpt'] = auth;
|
|
85
|
+
writeCredentials(creds);
|
|
86
|
+
}
|
|
87
|
+
export function getChatGptAuth() {
|
|
88
|
+
const creds = readCredentials();
|
|
89
|
+
const val = creds['chatgpt'];
|
|
90
|
+
if (val && typeof val === 'object') {
|
|
91
|
+
return val;
|
|
92
|
+
}
|
|
93
|
+
return undefined;
|
|
94
|
+
}
|
|
73
95
|
export function removeProviderKey(provider) {
|
|
74
96
|
const creds = readCredentials();
|
|
75
97
|
delete creds[provider];
|
|
@@ -77,23 +99,33 @@ export function removeProviderKey(provider) {
|
|
|
77
99
|
}
|
|
78
100
|
export function getProviderKey(provider) {
|
|
79
101
|
const creds = readCredentials();
|
|
80
|
-
|
|
102
|
+
const val = creds[provider];
|
|
103
|
+
return typeof val === 'string' ? val : undefined;
|
|
81
104
|
}
|
|
82
|
-
// Inject all stored credentials as env vars so the AI SDK
|
|
83
|
-
// providers pick them up automatically. Env vars already set
|
|
84
|
-
//
|
|
105
|
+
// Inject all stored non-ChatGPT credentials as env vars so the AI SDK
|
|
106
|
+
// providers pick them up automatically. Env vars already set by the user take
|
|
107
|
+
// precedence (we don't overwrite them).
|
|
85
108
|
export function injectCredentialsToEnv() {
|
|
86
109
|
const creds = readCredentials();
|
|
87
|
-
for (const [provider,
|
|
110
|
+
for (const [provider, value] of Object.entries(creds)) {
|
|
88
111
|
const info = PROVIDERS[provider];
|
|
89
|
-
if (!info)
|
|
112
|
+
if (!info)
|
|
90
113
|
continue;
|
|
91
|
-
|
|
92
|
-
if (
|
|
93
|
-
|
|
114
|
+
// Skip ChatGPT OAuth entries — handled separately
|
|
115
|
+
if (provider === 'chatgpt')
|
|
116
|
+
continue;
|
|
117
|
+
if (typeof value === 'string' && !process.env[info.envVar]) {
|
|
118
|
+
process.env[info.envVar] = value;
|
|
94
119
|
}
|
|
95
120
|
}
|
|
96
121
|
}
|
|
122
|
+
/**
|
|
123
|
+
* Returns true when the current run should use the ChatGPT/Codex backend flow
|
|
124
|
+
* for OpenAI image models instead of a direct OpenAI API key.
|
|
125
|
+
*/
|
|
126
|
+
export function shouldUseChatGptBackend() {
|
|
127
|
+
return !process.env['OPENAI_API_KEY'] && Boolean(getChatGptAuth());
|
|
128
|
+
}
|
|
97
129
|
// Check if a provider has a key available (from env or stored credentials).
|
|
98
130
|
// Returns the source of the key for display purposes.
|
|
99
131
|
export function getKeyStatus(provider) {
|
|
@@ -101,6 +133,14 @@ export function getKeyStatus(provider) {
|
|
|
101
133
|
if (!info) {
|
|
102
134
|
return { available: false, source: 'none' };
|
|
103
135
|
}
|
|
136
|
+
// ChatGPT OAuth is a special case
|
|
137
|
+
if (provider === 'chatgpt') {
|
|
138
|
+
const auth = getChatGptAuth();
|
|
139
|
+
if (auth) {
|
|
140
|
+
return { available: true, source: 'oauth' };
|
|
141
|
+
}
|
|
142
|
+
return { available: false, source: 'none' };
|
|
143
|
+
}
|
|
104
144
|
if (process.env[info.envVar]) {
|
|
105
145
|
return { available: true, source: 'env' };
|
|
106
146
|
}
|
package/dist/login.d.ts
CHANGED
|
@@ -2,7 +2,7 @@ export declare function loginInteractive(): Promise<void>;
|
|
|
2
2
|
export declare function loginNonInteractive({ provider, key, }: {
|
|
3
3
|
provider: string;
|
|
4
4
|
key: string;
|
|
5
|
-
}): void
|
|
5
|
+
}): Promise<void>;
|
|
6
6
|
export declare function showLoginStatus(): void;
|
|
7
7
|
export declare function removeLogin(provider: string): void;
|
|
8
8
|
export declare function readKeyFromStdin(): Promise<string>;
|
package/dist/login.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"login.d.ts","sourceRoot":"","sources":["../src/login.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"login.d.ts","sourceRoot":"","sources":["../src/login.ts"],"names":[],"mappings":"AAyBA,wBAAsB,gBAAgB,IAAI,OAAO,CAAC,IAAI,CAAC,CAkFtD;AAED,wBAAsB,mBAAmB,CAAC,EACxC,QAAQ,EACR,GAAG,GACJ,EAAE;IACD,QAAQ,EAAE,MAAM,CAAA;IAChB,GAAG,EAAE,MAAM,CAAA;CACZ,GAAG,OAAO,CAAC,IAAI,CAAC,CAyBhB;AAED,wBAAgB,eAAe,IAAI,IAAI,CAyCtC;AAED,wBAAgB,WAAW,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAalD;AAGD,wBAAsB,gBAAgB,IAAI,OAAO,CAAC,MAAM,CAAC,CAMxD"}
|
package/dist/login.js
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
// Login command — interactive and non-interactive API key management.
|
|
2
2
|
// Interactive mode uses clack prompts for provider selection and key input.
|
|
3
3
|
// Non-interactive mode supports --provider + --key flags and stdin piping.
|
|
4
|
+
// ChatGPT OAuth uses a browser flow instead of pasting a key.
|
|
4
5
|
import { intro, outro, select, password, isCancel, cancel, log, note, } from '@clack/prompts';
|
|
5
6
|
import pc from 'picocolors';
|
|
6
|
-
import { PROVIDERS, saveProviderKey, removeProviderKey, getKeyStatus,
|
|
7
|
+
import { PROVIDERS, saveProviderKey, removeProviderKey, getKeyStatus, getChatGptAuth, saveChatGptAuth, } from './credentials.js';
|
|
8
|
+
import { chatGptOAuthLogin, extractPlanType } from './chatgpt-auth.js';
|
|
7
9
|
export async function loginInteractive() {
|
|
8
10
|
intro(pc.bold('egaki login'));
|
|
9
11
|
const providerOptions = Object.entries(PROVIDERS).map(([key, info]) => {
|
|
@@ -15,6 +17,11 @@ export async function loginInteractive() {
|
|
|
15
17
|
if (status.source === 'stored') {
|
|
16
18
|
return pc.green('(saved)');
|
|
17
19
|
}
|
|
20
|
+
if (status.source === 'oauth') {
|
|
21
|
+
const auth = getChatGptAuth();
|
|
22
|
+
const email = auth?.email;
|
|
23
|
+
return pc.green(`(signed in${email ? ` as ${email}` : ''})`);
|
|
24
|
+
}
|
|
18
25
|
return pc.dim('(not configured)');
|
|
19
26
|
})();
|
|
20
27
|
// Highlight the egaki option as recommended
|
|
@@ -40,6 +47,13 @@ export async function loginInteractive() {
|
|
|
40
47
|
log.error(`Unknown provider: ${provider}`);
|
|
41
48
|
process.exit(1);
|
|
42
49
|
}
|
|
50
|
+
// ChatGPT uses browser OAuth instead of key paste
|
|
51
|
+
if (provider === 'chatgpt') {
|
|
52
|
+
const auth = await chatGptOAuthLogin();
|
|
53
|
+
saveChatGptAuth(auth);
|
|
54
|
+
outro('Done — ChatGPT OAuth saved');
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
43
57
|
log.info(`${pc.dim('Env var:')} ${info.envVar} ${pc.dim('(also used by the CLI when set)')}`);
|
|
44
58
|
log.info(`${pc.dim('Get key:')} ${info.hint}`);
|
|
45
59
|
const key = await password({
|
|
@@ -59,13 +73,20 @@ export async function loginInteractive() {
|
|
|
59
73
|
note(`You can also set ${pc.bold(info.envVar)} as an env var.\nThe CLI reads it automatically, so you can pass it inline too:\n ${pc.dim(`${info.envVar}=... egaki generate "prompt"`)}`, 'Tip');
|
|
60
74
|
outro('Done');
|
|
61
75
|
}
|
|
62
|
-
export function loginNonInteractive({ provider, key, }) {
|
|
76
|
+
export async function loginNonInteractive({ provider, key, }) {
|
|
63
77
|
const info = PROVIDERS[provider];
|
|
64
78
|
if (!info) {
|
|
65
79
|
const available = Object.keys(PROVIDERS).join(', ');
|
|
66
80
|
console.error(pc.red(`Unknown provider: ${provider}. Available: ${available}`));
|
|
67
81
|
process.exit(1);
|
|
68
82
|
}
|
|
83
|
+
// ChatGPT uses browser OAuth — key flag is not needed
|
|
84
|
+
if (provider === 'chatgpt') {
|
|
85
|
+
const auth = await chatGptOAuthLogin();
|
|
86
|
+
saveChatGptAuth(auth);
|
|
87
|
+
console.log(pc.green('ChatGPT OAuth saved'));
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
69
90
|
if (!key || key.trim().length === 0) {
|
|
70
91
|
console.error(pc.red('API key cannot be empty'));
|
|
71
92
|
process.exit(1);
|
|
@@ -77,6 +98,25 @@ export function showLoginStatus() {
|
|
|
77
98
|
console.log(pc.bold('Configured providers:\n'));
|
|
78
99
|
for (const [key, info] of Object.entries(PROVIDERS)) {
|
|
79
100
|
const status = getKeyStatus(key);
|
|
101
|
+
if (key === 'chatgpt') {
|
|
102
|
+
const auth = getChatGptAuth();
|
|
103
|
+
if (auth) {
|
|
104
|
+
const plan = extractPlanType(auth);
|
|
105
|
+
const email = auth.email ?? auth.accountId ?? 'unknown';
|
|
106
|
+
const expired = auth.expires < Date.now();
|
|
107
|
+
const expiryLabel = expired
|
|
108
|
+
? pc.yellow('(token expired, will auto-refresh)')
|
|
109
|
+
: pc.dim(`(token valid)`);
|
|
110
|
+
console.log(`${pc.green('*')} ${info.label} ${pc.green('(signed in)')}`);
|
|
111
|
+
console.log(pc.dim(` account: ${email}${plan ? `, plan: ${plan}` : ''}`));
|
|
112
|
+
console.log(` ${expiryLabel}`);
|
|
113
|
+
}
|
|
114
|
+
else {
|
|
115
|
+
console.log(`${pc.dim('-')} ${info.label} ${pc.dim('(not signed in)')}`);
|
|
116
|
+
console.log(pc.dim(` run: egaki login → select ChatGPT`));
|
|
117
|
+
}
|
|
118
|
+
continue;
|
|
119
|
+
}
|
|
80
120
|
const icon = status.available ? pc.green('*') : pc.dim('-');
|
|
81
121
|
const source = (() => {
|
|
82
122
|
if (status.source === 'env') {
|
|
@@ -100,7 +140,8 @@ export function removeLogin(provider) {
|
|
|
100
140
|
process.exit(1);
|
|
101
141
|
}
|
|
102
142
|
removeProviderKey(provider);
|
|
103
|
-
|
|
143
|
+
const label = provider === 'chatgpt' ? 'ChatGPT OAuth' : info.label;
|
|
144
|
+
console.log(pc.green(`${label} key removed`));
|
|
104
145
|
}
|
|
105
146
|
// Read API key from stdin (for piping: echo "sk-xxx" | egaki login --provider google)
|
|
106
147
|
export async function readKeyFromStdin() {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"model-catalog.d.ts","sourceRoot":"","sources":["../src/model-catalog.ts"],"names":[],"mappings":"AAUA,MAAM,MAAM,YAAY,GAAG;IACzB,IAAI,EAAE,WAAW,CAAA;IACjB,kDAAkD;IAClD,QAAQ,EAAE,MAAM,CAAA;CACjB,CAAA;AAED,MAAM,MAAM,YAAY,GAAG;IACzB,IAAI,EAAE,WAAW,CAAA;IACjB,mCAAmC;IACnC,SAAS,EAAE,MAAM,CAAA;IACjB,oCAAoC;IACpC,UAAU,EAAE,MAAM,CAAA;CACnB,CAAA;AAED,MAAM,MAAM,SAAS,GAAG,YAAY,GAAG,YAAY,CAAA;AAEnD,MAAM,MAAM,aAAa,GAAG;IAC1B,wCAAwC;IACxC,OAAO,EAAE,OAAO,CAAA;IAChB,mCAAmC;IACnC,UAAU,EAAE,OAAO,CAAA;IACnB,8BAA8B;IAC9B,YAAY,EAAE,MAAM,EAAE,CAAA;IACtB,mDAAmD;IACnD,KAAK,CAAC,EAAE,MAAM,EAAE,CAAA;IAChB,kCAAkC;IAClC,IAAI,EAAE,OAAO,CAAA;IACb,uCAAuC;IACvC,cAAc,EAAE,OAAO,CAAA;CACxB,CAAA;AAED,MAAM,MAAM,UAAU,GAAG;IACvB,EAAE,EAAE,MAAM,CAAA;IACV,IAAI,EAAE,MAAM,CAAA;IACZ,iEAAiE;IACjE,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,QAAQ,EAAE,MAAM,CAAA;IAChB,QAAQ,EAAE,OAAO,GAAG,MAAM,CAAA;IAC1B,mDAAmD;IACnD,QAAQ,EAAE,MAAM,CAAA;IAChB,IAAI,EAAE,SAAS,CAAA;IACf,QAAQ,EAAE,aAAa,CAAA;CACxB,CAAA;AA+ED,eAAO,MAAM,OAAO,EAAE,UAAU,
|
|
1
|
+
{"version":3,"file":"model-catalog.d.ts","sourceRoot":"","sources":["../src/model-catalog.ts"],"names":[],"mappings":"AAUA,MAAM,MAAM,YAAY,GAAG;IACzB,IAAI,EAAE,WAAW,CAAA;IACjB,kDAAkD;IAClD,QAAQ,EAAE,MAAM,CAAA;CACjB,CAAA;AAED,MAAM,MAAM,YAAY,GAAG;IACzB,IAAI,EAAE,WAAW,CAAA;IACjB,mCAAmC;IACnC,SAAS,EAAE,MAAM,CAAA;IACjB,oCAAoC;IACpC,UAAU,EAAE,MAAM,CAAA;CACnB,CAAA;AAED,MAAM,MAAM,SAAS,GAAG,YAAY,GAAG,YAAY,CAAA;AAEnD,MAAM,MAAM,aAAa,GAAG;IAC1B,wCAAwC;IACxC,OAAO,EAAE,OAAO,CAAA;IAChB,mCAAmC;IACnC,UAAU,EAAE,OAAO,CAAA;IACnB,8BAA8B;IAC9B,YAAY,EAAE,MAAM,EAAE,CAAA;IACtB,mDAAmD;IACnD,KAAK,CAAC,EAAE,MAAM,EAAE,CAAA;IAChB,kCAAkC;IAClC,IAAI,EAAE,OAAO,CAAA;IACb,uCAAuC;IACvC,cAAc,EAAE,OAAO,CAAA;CACxB,CAAA;AAED,MAAM,MAAM,UAAU,GAAG;IACvB,EAAE,EAAE,MAAM,CAAA;IACV,IAAI,EAAE,MAAM,CAAA;IACZ,iEAAiE;IACjE,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,QAAQ,EAAE,MAAM,CAAA;IAChB,QAAQ,EAAE,OAAO,GAAG,MAAM,CAAA;IAC1B,mDAAmD;IACnD,QAAQ,EAAE,MAAM,CAAA;IAChB,IAAI,EAAE,SAAS,CAAA;IACf,QAAQ,EAAE,aAAa,CAAA;CACxB,CAAA;AA+ED,eAAO,MAAM,OAAO,EAAE,UAAU,EAy6B/B,CAAA;AAMD,wBAAgB,SAAS,CAAC,EAAE,EAAE,MAAM,GAAG,UAAU,GAAG,SAAS,CAE5D"}
|
package/dist/model-catalog.js
CHANGED
|
@@ -437,9 +437,42 @@ export const CATALOG = [
|
|
|
437
437
|
multipleImages: true,
|
|
438
438
|
},
|
|
439
439
|
},
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
440
|
+
{
|
|
441
|
+
id: 'gpt-image-2',
|
|
442
|
+
name: 'GPT Image 2',
|
|
443
|
+
description: 'State-of-the-art image generation model with token-based pricing. ' +
|
|
444
|
+
'Cost varies by quality and size; $0.053 is the medium-quality 1024×1024 estimate.',
|
|
445
|
+
released: '2026-04-21',
|
|
446
|
+
...openaiImage,
|
|
447
|
+
// Token-based pricing: $30/1M output image tokens. Medium quality 1024×1024 ≈ $0.053.
|
|
448
|
+
cost: { type: 'per-image', perImage: 0.053 },
|
|
449
|
+
features: {
|
|
450
|
+
editing: true,
|
|
451
|
+
inpainting: true,
|
|
452
|
+
aspectRatios: [],
|
|
453
|
+
sizes: ['1024x1024', '1536x1024', '1024x1536'],
|
|
454
|
+
seed: false,
|
|
455
|
+
multipleImages: true,
|
|
456
|
+
},
|
|
457
|
+
},
|
|
458
|
+
{
|
|
459
|
+
id: 'chatgpt-image-latest',
|
|
460
|
+
name: 'ChatGPT Image',
|
|
461
|
+
description: 'Rolling-latest alias that tracks the newest ChatGPT image model. Currently points ' +
|
|
462
|
+
'to gpt-image-2. Pricing may shift when the alias retargets to a newer model.',
|
|
463
|
+
released: '2026-01',
|
|
464
|
+
...openaiImage,
|
|
465
|
+
// Matches gpt-image-2 medium quality 1024×1024 estimate.
|
|
466
|
+
cost: { type: 'per-image', perImage: 0.053 },
|
|
467
|
+
features: {
|
|
468
|
+
editing: true,
|
|
469
|
+
inpainting: true,
|
|
470
|
+
aspectRatios: [],
|
|
471
|
+
sizes: ['1024x1024', '1536x1024', '1024x1536'],
|
|
472
|
+
seed: false,
|
|
473
|
+
multipleImages: true,
|
|
474
|
+
},
|
|
475
|
+
},
|
|
443
476
|
// ── Replicate ──────────────────────────────────────────────────────────
|
|
444
477
|
{
|
|
445
478
|
id: 'black-forest-labs/flux-1.1-pro',
|
package/dist/models.d.ts
CHANGED
|
@@ -9,6 +9,11 @@ export declare const DEFAULT_MODEL = "nano-banana-pro-preview";
|
|
|
9
9
|
export declare const DEFAULT_VIDEO_MODEL = "veo-3.1-fast-generate-001";
|
|
10
10
|
export declare function getModelConfig(modelId: string): AnyModelEntry;
|
|
11
11
|
export declare function ensureProviderKey(providerName: string): void;
|
|
12
|
+
/**
|
|
13
|
+
* ChatGPT OAuth image generation goes through the Codex backend instead of the
|
|
14
|
+
* OpenAI Image API, so OpenAI image models need the custom responses path.
|
|
15
|
+
*/
|
|
16
|
+
export declare function shouldUseResponsesApi(modelId: string): boolean;
|
|
12
17
|
export declare function createImageModel(modelId: string): Promise<ImageModel>;
|
|
13
18
|
export declare function createTextModel(modelId: string): Promise<LanguageModel>;
|
|
14
19
|
export declare function createVideoModel(modelId: string): Promise<any>;
|
package/dist/models.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"models.d.ts","sourceRoot":"","sources":["../src/models.ts"],"names":[],"mappings":"AAiBA,OAAO,KAAK,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,IAAI,CAAA;AAInD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAA;AAEpD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAA;AAE/D,MAAM,MAAM,aAAa,GAAG,UAAU,GAAG,eAAe,CAAA;AACxD,YAAY,EAAE,UAAU,EAAE,eAAe,EAAE,CAAA;AAE3C,eAAO,MAAM,YAAY,EAA+B,CAAC,MAAM,EAAE,GAAG,MAAM,EAAE,CAAC,CAAA;AAC7E,eAAO,MAAM,YAAY,EAAqC,CAAC,MAAM,EAAE,GAAG,MAAM,EAAE,CAAC,CAAA;AAYnF,eAAO,MAAM,aAAa,4BAA4B,CAAA;AACtD,eAAO,MAAM,mBAAmB,8BAA8B,CAAA;AAE9D,wBAAgB,cAAc,CAAC,OAAO,EAAE,MAAM,GAAG,aAAa,CAO7D;AAuBD,wBAAgB,iBAAiB,CAAC,YAAY,EAAE,MAAM,GAAG,IAAI,CAiD5D;
|
|
1
|
+
{"version":3,"file":"models.d.ts","sourceRoot":"","sources":["../src/models.ts"],"names":[],"mappings":"AAiBA,OAAO,KAAK,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,IAAI,CAAA;AAInD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAA;AAEpD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAA;AAE/D,MAAM,MAAM,aAAa,GAAG,UAAU,GAAG,eAAe,CAAA;AACxD,YAAY,EAAE,UAAU,EAAE,eAAe,EAAE,CAAA;AAE3C,eAAO,MAAM,YAAY,EAA+B,CAAC,MAAM,EAAE,GAAG,MAAM,EAAE,CAAC,CAAA;AAC7E,eAAO,MAAM,YAAY,EAAqC,CAAC,MAAM,EAAE,GAAG,MAAM,EAAE,CAAC,CAAA;AAYnF,eAAO,MAAM,aAAa,4BAA4B,CAAA;AACtD,eAAO,MAAM,mBAAmB,8BAA8B,CAAA;AAE9D,wBAAgB,cAAc,CAAC,OAAO,EAAE,MAAM,GAAG,aAAa,CAO7D;AAuBD,wBAAgB,iBAAiB,CAAC,YAAY,EAAE,MAAM,GAAG,IAAI,CAiD5D;AAgDD;;;GAGG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAI9D;AAOD,wBAAsB,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC,CAsC3E;AAED,wBAAsB,eAAe,CACnC,OAAO,EAAE,MAAM,GACd,OAAO,CAAC,aAAa,CAAC,CAqCxB;AAED,wBAAsB,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,CAyCpE"}
|
package/dist/models.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import pc from 'picocolors';
|
|
2
|
-
import { PROVIDERS, EGAKI_GATEWAY_URL } from './credentials.js';
|
|
2
|
+
import { PROVIDERS, EGAKI_GATEWAY_URL, shouldUseChatGptBackend } from './credentials.js';
|
|
3
3
|
import { CATALOG, findModel } from './model-catalog.js';
|
|
4
4
|
import { VIDEO_CATALOG, findVideoModel } from './video-model-catalog.js';
|
|
5
5
|
export const IMAGE_MODELS = CATALOG.map((m) => m.id);
|
|
@@ -128,6 +128,16 @@ async function createGatewayVideoModel(modelId, provider) {
|
|
|
128
128
|
const gatewayModelId = `${provider}/${bareId}`;
|
|
129
129
|
return gateway.video(gatewayModelId);
|
|
130
130
|
}
|
|
131
|
+
/**
|
|
132
|
+
* ChatGPT OAuth image generation goes through the Codex backend instead of the
|
|
133
|
+
* OpenAI Image API, so OpenAI image models need the custom responses path.
|
|
134
|
+
*/
|
|
135
|
+
export function shouldUseResponsesApi(modelId) {
|
|
136
|
+
const config = findModel(modelId);
|
|
137
|
+
if (!config)
|
|
138
|
+
return false;
|
|
139
|
+
return config.provider === 'openai' && config.strategy === 'image' && shouldUseChatGptBackend();
|
|
140
|
+
}
|
|
131
141
|
// Lazily import the provider and create the right model instance.
|
|
132
142
|
// This avoids loading all provider SDKs upfront — only the one needed
|
|
133
143
|
// for the selected model gets imported.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "egaki",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.1",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "./dist/cli.js",
|
|
6
6
|
"types": "./dist/cli.d.ts",
|
|
@@ -54,7 +54,8 @@
|
|
|
54
54
|
"@ai-sdk/replicate": "2.0.20",
|
|
55
55
|
"@clack/prompts": "^1.0.1",
|
|
56
56
|
"ai": "6.0.103",
|
|
57
|
-
"
|
|
57
|
+
"eventsource-parser": "^3.0.6",
|
|
58
|
+
"goke": "^6.6.1",
|
|
58
59
|
"js-yaml": "^4.1.1",
|
|
59
60
|
"picocolors": "^1.1.1",
|
|
60
61
|
"string-dedent": "^3.0.2",
|