egaki 0.9.0 → 0.11.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.
Files changed (50) hide show
  1. package/CHANGELOG.md +72 -0
  2. package/dist/cli/chatgpt-auth.d.ts +30 -5
  3. package/dist/cli/chatgpt-auth.d.ts.map +1 -1
  4. package/dist/cli/chatgpt-auth.js +257 -79
  5. package/dist/cli/cli.d.ts.map +1 -1
  6. package/dist/cli/cli.js +132 -28
  7. package/dist/cli/dev-server.d.ts +30 -0
  8. package/dist/cli/dev-server.d.ts.map +1 -0
  9. package/dist/cli/dev-server.js +266 -0
  10. package/dist/cli/dev-server.test.d.ts +2 -0
  11. package/dist/cli/dev-server.test.d.ts.map +1 -0
  12. package/dist/cli/dev-server.test.js +95 -0
  13. package/dist/cli/generate.d.ts +8 -0
  14. package/dist/cli/generate.d.ts.map +1 -1
  15. package/dist/cli/generate.js +170 -58
  16. package/dist/cli/generate.test.js +50 -1
  17. package/dist/cli/login.d.ts +38 -3
  18. package/dist/cli/login.d.ts.map +1 -1
  19. package/dist/cli/login.js +44 -17
  20. package/dist/cli/login.test.d.ts +2 -0
  21. package/dist/cli/login.test.d.ts.map +1 -0
  22. package/dist/cli/login.test.js +158 -0
  23. package/dist/cli/open-browser.d.ts +3 -1
  24. package/dist/cli/open-browser.d.ts.map +1 -1
  25. package/dist/cli/open-browser.js +2 -2
  26. package/dist/cli/xai-auth.d.ts +3 -1
  27. package/dist/cli/xai-auth.d.ts.map +1 -1
  28. package/dist/cli/xai-auth.js +13 -3
  29. package/dist/vite/angled-screen-shader.d.ts +5 -0
  30. package/dist/vite/angled-screen-shader.d.ts.map +1 -1
  31. package/dist/vite/angled-screen-shader.js +77 -34
  32. package/dist/vite/generated-media-client.d.ts.map +1 -1
  33. package/dist/vite/generated-media-client.js +2 -2
  34. package/dist/vite/vite-plugin.d.ts.map +1 -1
  35. package/dist/vite/vite-plugin.js +128 -10
  36. package/package.json +6 -10
  37. package/skills/egaki/SKILL.md +14 -0
  38. package/src/cli/chatgpt-auth.ts +379 -89
  39. package/src/cli/cli.ts +161 -27
  40. package/src/cli/dev-server.test.ts +109 -0
  41. package/src/cli/dev-server.ts +303 -0
  42. package/src/cli/generate.test.ts +57 -0
  43. package/src/cli/generate.ts +191 -61
  44. package/src/cli/login.test.ts +185 -0
  45. package/src/cli/login.ts +68 -16
  46. package/src/cli/open-browser.ts +7 -6
  47. package/src/cli/xai-auth.ts +15 -3
  48. package/src/vite/angled-screen-shader.tsx +81 -34
  49. package/src/vite/generated-media-client.tsx +6 -1
  50. package/src/vite/vite-plugin.ts +137 -10
@@ -1 +1 @@
1
- {"version":3,"file":"generate.d.ts","sourceRoot":"","sources":["../../src/cli/generate.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"generate.d.ts","sourceRoot":"","sources":["../../src/cli/generate.ts"],"names":[],"mappings":"AAgCA,OAAO,EAQL,eAAe,EAChB,MAAM,aAAa,CAAA;AAEpB,OAAO,EAAE,eAAe,EAAE,CAAA;AAa1B,uEAAuE;AACvE,MAAM,MAAM,YAAY,GACpB,yBAAyB,GAAG,+BAA+B,GAAG,8BAA8B,GAC5F,uCAAuC,GAAG,wBAAwB,GAAG,4BAA4B,GAAG,gCAAgC,GACpI,gCAAgC,GAAG,sCAAsC,GAAG,qCAAqC,GACjH,+BAA+B,GAAG,mCAAmC,GAAG,uCAAuC,GAC/G,kBAAkB,GAAG,kBAAkB,GAAG,mBAAmB,GAAG,cAAc,GAAG,oBAAoB,GACrG,YAAY,GAAG,YAAY,GAAG,aAAa,GAAG,iBAAiB,GAAG,iBAAiB,GACnF,YAAY,GAAG,YAAY,GAAG,YAAY,GAAG,gBAAgB,GAAG,cAAc,GAAG,kBAAkB,GAAG,sBAAsB,GAAG,0BAA0B,GACzJ,mBAAmB,GAAG,cAAc,GAAG,cAAc,GACrD,oBAAoB,GAAG,4BAA4B,GACnD,UAAU,GAAG,UAAU,GAAG,aAAa,GAAG,kBAAkB,GAAG,eAAe,GAAG,aAAa,GAAG,sBAAsB,GACvH,CAAC,MAAM,GAAG,EAAE,CAAC,CAAA;AAEjB,uEAAuE;AACvE,MAAM,MAAM,YAAY,GACpB,sBAAsB,GAAG,2BAA2B,GAAG,sBAAsB,GAAG,2BAA2B,GAC3G,6BAA6B,GAAG,kCAAkC,GAClE,oBAAoB,GAAG,wBAAwB,GAC/C,gBAAgB,GAAG,gBAAgB,GAAG,2BAA2B,GAAG,gBAAgB,GAAG,gBAAgB,GAAG,2BAA2B,GACrI,sBAAsB,GAAG,sBAAsB,GAC/C,cAAc,GAAG,cAAc,GAAG,oBAAoB,GAAG,cAAc,GAAG,oBAAoB,GAAG,sBAAsB,GACvH,cAAc,GAAG,mBAAmB,GAAG,mBAAmB,GAAG,mBAAmB,GAAG,wBAAwB,GAAG,wBAAwB,GAAG,wBAAwB,GACjK,YAAY,GAAG,eAAe,GAAG,eAAe,GAChD,CAAC,MAAM,GAAG,EAAE,CAAC,CAAA;AAEjB,6CAA6C;AAC7C,MAAM,MAAM,WAAW,GACnB,KAAK,GAAG,KAAK,GAAG,KAAK,GAAG,MAAM,GAAG,MAAM,GAAG,KAAK,GAAG,KAAK,GAAG,KAAK,GAAG,KAAK,GAAG,MAAM,GAAG,MAAM,GACzF,CAAC,MAAM,GAAG,EAAE,CAAC,CAAA;AAEjB,kDAAkD;AAClD,MAAM,MAAM,YAAY,GAAG,MAAM,GAAG,KAAK,GAAG,QAAQ,GAAG,MAAM,GAAG,UAAU,GAAG,CAAC,MAAM,GAAG,EAAE,CAAC,CAAA;AAE1F,4BAA4B;AAC5B,MAAM,MAAM,iBAAiB,GAAG,KAAK,GAAG,MAAM,GAAG,MAAM,GAAG,CAAC,MAAM,GAAG,EAAE,CAAC,CAAA;AAIvE,MAAM,MAAM,aAAa,GAAG;IAC1B,UAAU,EAAE,UAAU,CAAA;IACtB,SAAS,EAAE,MAAM,CAAA;CAClB,CAAA;AAED,MAAM,WAAW,oBAAoB;IACnC,MAAM,EAAE,MAAM,CAAA;IACd,sDAAsD;IACtD,KAAK,CAAC,EAAE,YAAY,CAAA;IACpB,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,WAAW,CAAC,EAAE,WAAW,CAAA;IACzB,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,WAAW,CAAC,EAAE,UAAU,EAAE,CAAA;IAC1B,SAAS,CAAC,EAAE,UAAU,CAAA;IACtB,WAAW,CAAC,EAAE,OAAO,CAAA;IACrB,OAAO,CAAC,EAAE,YAAY,CAAA;IACtB,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,YAAY,CAAC,EAAE,iBAAiB,CAAA;IAChC,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,qDAAqD;IACrD,SAAS,CAAC,EAAE,IAAI,GAAG,IAAI,GAAG,IAAI,CAAA;CAC/B;AAED,MAAM,WAAW,mBAAmB;IAClC,MAAM,EAAE,aAAa,EAAE,CAAA;IACvB,KAAK,EAAE,MAAM,CAAA;IACb,IAAI,EAAE,MAAM,GAAG,IAAI,CAAA;IACnB,KAAK,CAAC,EAAE;QAAE,WAAW,CAAC,EAAE,MAAM,CAAC;QAAC,YAAY,CAAC,EAAE,MAAM,CAAA;KAAE,CAAA;IACvD,QAAQ,CAAC,EAAE,OAAO,EAAE,CAAA;IACpB,mDAAmD;IACnD,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,sDAAsD;IACtD,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;CAC9B;AAED,MAAM,WAAW,oBAAoB;IACnC,MAAM,EAAE,MAAM,CAAA;IACd,4DAA4D;IAC5D,KAAK,CAAC,EAAE,YAAY,CAAA;IACpB,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,WAAW,CAAC,EAAE,WAAW,CAAA;IACzB,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,UAAU,CAAC,EAAE,UAAU,CAAA;IACvB,IAAI,CAAC,EAAE,YAAY,GAAG,cAAc,GAAG,oBAAoB,CAAA;IAC3D,+EAA+E;IAC/E,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,+EAA+E;IAC/E,eAAe,CAAC,EAAE,MAAM,EAAE,CAAA;IAC1B,cAAc,CAAC,EAAE,MAAM,CAAA;CACxB;AAED,MAAM,WAAW,mBAAmB;IAClC,MAAM,EAAE,aAAa,EAAE,CAAA;IACvB,KAAK,EAAE,MAAM,CAAA;IACb,IAAI,EAAE,MAAM,GAAG,IAAI,CAAA;IACnB,QAAQ,CAAC,EAAE,OAAO,EAAE,CAAA;IACpB,yDAAyD;IACzD,SAAS,CAAC,EAAE,OAAO,EAAE,CAAA;CACtB;AAeD,KAAK,qBAAqB,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,MAAM,EAAE,GAAG,IAAI,GAAG,SAAS,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,IAAI,GAAG,SAAS,CAAC,CAAC,CAAC,CAAA;AAEnL,wBAAgB,yBAAyB,CACvC,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE;IACJ,WAAW,CAAC,EAAE,GAAG,MAAM,IAAI,MAAM,EAAE,CAAA;IACnC,WAAW,EAAE,OAAO,CAAA;IACpB,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,cAAc,CAAC,EAAE,MAAM,CAAA;CACxB,GACA,qBAAqB,CAyCvB;AAED,wBAAgB,yBAAyB,CACvC,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE;IACJ,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,eAAe,CAAC,EAAE,MAAM,EAAE,CAAA;IAC1B,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,KAAK,EAAE,MAAM,CAAA;CACd,GACA,qBAAqB,GAAG,SAAS,CAuDnC;AAID,wBAAgB,aAAa,CAC3B,IAAI,EAAE;IACJ,IAAI,EAAE,WAAW,CAAA;IACjB,QAAQ,EAAE,MAAM,CAAA;CACjB,GAAG;IACF,IAAI,EAAE,WAAW,CAAA;IACjB,SAAS,EAAE,MAAM,CAAA;IACjB,UAAU,EAAE,MAAM,CAAA;CACnB,GAAG;IACF,IAAI,EAAE,kBAAkB,CAAA;IACxB,kBAAkB,EAAE,MAAM,CAAA;IAC1B,KAAK,EAAE,KAAK,CAAC;QAAE,UAAU,CAAC,EAAE,MAAM,CAAC;QAAC,aAAa,EAAE,MAAM,CAAC;QAAC,aAAa,CAAC,EAAE,OAAO,CAAA;KAAE,CAAC,CAAA;CACtF,GAAG;IACF,IAAI,EAAE,SAAS,CAAA;CAChB,EACD,KAAK,EAAE;IACL,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,eAAe,CAAC,EAAE,MAAM,CAAA;IACxB,eAAe,CAAC,EAAE,MAAM,CAAA;IACxB,eAAe,CAAC,EAAE,MAAM,CAAA;IACxB,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,aAAa,CAAC,EAAE,OAAO,CAAA;CACxB,EACD,KAAK,GAAE,MAAU,GAChB,MAAM,GAAG,IAAI,CA0Bf;AA+FD;;;GAGG;AACH,wBAAgB,mBAAmB,CACjC,MAAM,EAAE,MAAM,EACd,WAAW,EAAE,GAAG,MAAM,IAAI,MAAM,EAAE,GAAG,SAAS,EAC9C,KAAK,EAAE,SAAS,MAAM,EAAE,GACvB;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,GAAG,MAAM,IAAI,MAAM,EAAE,CAAA;CAAE,CAQlD;AAUD;;;;GAIG;AACH,wBAAsB,qBAAqB,CAAC,IAAI,EAAE,oBAAoB,GAAG,OAAO,CAAC,KAAK,GAAG,mBAAmB,CAAC,CAqD5G;AAID;;;GAGG;AACH,wBAAsB,qBAAqB,CAAC,IAAI,EAAE,oBAAoB,GAAG,OAAO,CAAC,KAAK,GAAG,mBAAmB,CAAC,CA8E5G;AAsWD,MAAM,WAAW,oBAAoB;IACnC,oEAAoE;IACpE,GAAG,EAAE,MAAM,CAAA;CACZ;AAOD,eAAO,MAAM,aAAa;WAAkD,MAAM;wBAehF,CAAA;AAIF,eAAO,MAAM,aAAa;WAAkD,MAAM;wBAehF,CAAA;AAIF,OAAO,EACL,cAAc,EACd,sBAAsB,EACtB,mBAAmB,EACnB,KAAK,qBAAqB,EAC1B,KAAK,oBAAoB,EACzB,KAAK,kBAAkB,EACvB,KAAK,cAAc,EACnB,KAAK,qBAAqB,EAC1B,KAAK,oBAAoB,GAC1B,MAAM,sBAAsB,CAAA;AAI7B,OAAO,EACL,eAAe,EACf,uBAAuB,EACvB,0BAA0B,EAC1B,wBAAwB,EACxB,wBAAwB,EACxB,KAAK,iBAAiB,EACtB,KAAK,gBAAgB,EACrB,KAAK,aAAa,EAClB,KAAK,oBAAoB,GAC1B,MAAM,6BAA6B,CAAA"}
@@ -19,7 +19,7 @@ import { createParser } from 'eventsource-parser';
19
19
  import { injectCredentialsToEnv, getChatGptAuth, saveChatGptAuth, } from './credentials.js';
20
20
  import { getModelConfig, createImageModel, createTextModel, createVideoModel, shouldUseResponsesApi, DEFAULT_MODEL, DEFAULT_VIDEO_MODEL, ValidationError, } from './models.js';
21
21
  export { ValidationError };
22
- import { getValidChatGptAuth } from './chatgpt-auth.js';
22
+ import { chatGptReLoginMessage, getValidChatGptAuth, isRevokedChatGptAccessToken, refreshChatGptToken, resolveChatGptResponsesModel, } from './chatgpt-auth.js';
23
23
  export function buildImageProviderOptions(provider, opts) {
24
24
  switch (provider) {
25
25
  case 'google': {
@@ -181,21 +181,70 @@ function imageBytesToDataUrl(image) {
181
181
  const mediaType = inferImageMediaType(image);
182
182
  return `data:${mediaType};base64,${Buffer.from(image).toString('base64')}`;
183
183
  }
184
- function chatGptImageSizeFromAspectRatio(aspectRatio) {
185
- switch (aspectRatio) {
186
- case '1:1':
187
- return '1024x1024';
188
- case '3:2':
189
- return '1536x1024';
190
- case '2:3':
191
- return '1024x1536';
192
- default:
193
- return undefined;
194
- }
195
- }
196
184
  function isAspectRatio(input) {
197
185
  return /^\d+:\d+$/.test(input);
198
186
  }
187
+ // ─── aspect ratio fallback for models without native support ─────────────────
188
+ //
189
+ // OpenAI image models (gpt-image-*, dall-e-*) reject `aspectRatio`: the AI SDK
190
+ // pushes an "unsupported: aspectRatio" warning and the request falls back to a
191
+ // square image. They accept a fixed `size` list instead, and they also honour a
192
+ // plain-language ratio statement in the prompt text when picking the framing.
193
+ // So for these models we do both: snap to the closest supported size AND state
194
+ // the ratio in the prompt. The prompt hint matters because the supported sizes
195
+ // are coarse (only 3:2 / 1:1 / 2:3), so a request like 16:9 has no exact match
196
+ // and the composition has to come from the prompt.
197
+ //
198
+ // Models with a non-empty `features.aspectRatios` keep the native flag.
199
+ const OPENAI_SIZES = ['1024x1024', '1536x1024', '1024x1536'];
200
+ function ratioValue(aspectRatio) {
201
+ const [w, h] = aspectRatio.split(':').map(Number);
202
+ if (!w || !h)
203
+ return undefined;
204
+ return w / h;
205
+ }
206
+ function orientationLabel(ratio) {
207
+ if (ratio > 1.02)
208
+ return 'landscape';
209
+ if (ratio < 0.98)
210
+ return 'portrait';
211
+ return 'square';
212
+ }
213
+ /** Pick the supported WIDTHxHEIGHT whose ratio is closest to the requested one. */
214
+ function closestSize(aspectRatio, sizes) {
215
+ const target = ratioValue(aspectRatio);
216
+ if (target === undefined || sizes.length === 0)
217
+ return undefined;
218
+ let best;
219
+ let bestDistance = Infinity;
220
+ for (const size of sizes) {
221
+ const [w, h] = size.split('x').map(Number);
222
+ if (!w || !h)
223
+ continue;
224
+ // Compare in log space so 2x-too-wide and 2x-too-tall are equally far off.
225
+ const distance = Math.abs(Math.log(w / h) - Math.log(target));
226
+ if (distance < bestDistance) {
227
+ bestDistance = distance;
228
+ best = size;
229
+ }
230
+ }
231
+ return best;
232
+ }
233
+ /**
234
+ * Translate an aspect ratio request into a prompt prefix + concrete `size` for
235
+ * models that have no native aspect ratio parameter.
236
+ */
237
+ export function aspectRatioFallback(prompt, aspectRatio, sizes) {
238
+ if (!aspectRatio)
239
+ return { prompt };
240
+ const ratio = ratioValue(aspectRatio);
241
+ if (ratio === undefined)
242
+ return { prompt };
243
+ return {
244
+ prompt: `Image aspect ratio: ${aspectRatio}, ${orientationLabel(ratio)} orientation. ${prompt}`,
245
+ size: closestSize(aspectRatio, sizes),
246
+ };
247
+ }
199
248
  /** Convert any thrown value into an Error instance. */
200
249
  function toError(err) {
201
250
  if (err instanceof Error)
@@ -336,12 +385,19 @@ export async function generateVideoUncached(opts) {
336
385
  }
337
386
  // ─── internal generation paths ───────────────────────────────────────────────
338
387
  async function generateWithImageModel(opts) {
339
- const imagePrompt = opts.inputImages.length > 0
340
- ? { text: opts.prompt, images: opts.inputImages, ...(opts.maskImage ? { mask: opts.maskImage } : {}) }
341
- : opts.prompt;
342
388
  const config = getModelConfig(opts.model);
343
389
  if (config instanceof Error)
344
390
  return config;
391
+ // Models with an empty `aspectRatios` list have no native aspect ratio
392
+ // parameter, so the request is expressed through `size` + the prompt text.
393
+ const features = config.strategy === 'video' ? undefined : config.features;
394
+ const supportsNativeAspectRatio = (features?.aspectRatios?.length ?? 0) > 0;
395
+ const fallback = supportsNativeAspectRatio
396
+ ? { prompt: opts.prompt, size: undefined }
397
+ : aspectRatioFallback(opts.prompt, opts.aspectRatio, features?.sizes ?? []);
398
+ const imagePrompt = opts.inputImages.length > 0
399
+ ? { text: fallback.prompt, images: opts.inputImages, ...(opts.maskImage ? { mask: opts.maskImage } : {}) }
400
+ : fallback.prompt;
345
401
  const imageModel = await createImageModel(opts.model);
346
402
  if (imageModel instanceof Error)
347
403
  return imageModel;
@@ -359,7 +415,8 @@ async function generateWithImageModel(opts) {
359
415
  model: imageModel,
360
416
  prompt: imagePrompt,
361
417
  n: opts.count,
362
- ...(opts.aspectRatio ? { aspectRatio: opts.aspectRatio } : {}),
418
+ ...(opts.aspectRatio && supportsNativeAspectRatio ? { aspectRatio: opts.aspectRatio } : {}),
419
+ ...(fallback.size ? { size: fallback.size } : {}),
363
420
  ...(opts.seed !== undefined ? { seed: opts.seed } : {}),
364
421
  providerOptions,
365
422
  });
@@ -453,10 +510,7 @@ async function generateWithResponsesApi(opts) {
453
510
  if (opts.maskImage) {
454
511
  return new ValidationError('ChatGPT image generation does not support mask yet.');
455
512
  }
456
- const size = opts.aspectRatio ? chatGptImageSizeFromAspectRatio(opts.aspectRatio) : undefined;
457
- if (opts.aspectRatio && !size) {
458
- return new ValidationError('ChatGPT image generation only supports aspect ratios 1:1, 3:2, or 2:3.');
459
- }
513
+ const { prompt, size } = aspectRatioFallback(opts.prompt, opts.aspectRatio, OPENAI_SIZES);
460
514
  const storedAuth = getChatGptAuth();
461
515
  if (!storedAuth?.accountId) {
462
516
  return new ValidationError('Missing ChatGPT account metadata. Please run `egaki login --provider chatgpt` again.');
@@ -465,49 +519,62 @@ async function generateWithResponsesApi(opts) {
465
519
  if (auth instanceof Error)
466
520
  return auth;
467
521
  const content = [
468
- { type: 'input_text', text: opts.prompt },
522
+ { type: 'input_text', text: prompt },
469
523
  ...opts.inputImages.map((image) => ({
470
524
  type: 'input_image',
471
525
  image_url: imageBytesToDataUrl(image),
472
526
  })),
473
527
  ];
528
+ const responsesModel = await resolveChatGptResponsesModel({ auth });
529
+ if (responsesModel instanceof Error)
530
+ return responsesModel;
531
+ const requestBodyFor = (model) => JSON.stringify({
532
+ model,
533
+ instructions: 'You are Codex.',
534
+ input: [
535
+ {
536
+ type: 'message',
537
+ role: 'user',
538
+ content,
539
+ },
540
+ ],
541
+ tools: [
542
+ {
543
+ type: 'image_generation',
544
+ model: opts.model,
545
+ quality: 'auto',
546
+ output_format: 'png',
547
+ output_compression: 100,
548
+ moderation: 'auto',
549
+ size: size ?? 'auto',
550
+ },
551
+ ],
552
+ tool_choice: 'auto',
553
+ parallel_tool_calls: true,
554
+ stream: true,
555
+ store: false,
556
+ include: [],
557
+ });
558
+ const post = ({ access, accountId, body, }) => {
559
+ const headers = new Headers({
560
+ Authorization: `Bearer ${access}`,
561
+ 'Content-Type': 'application/json',
562
+ });
563
+ if (accountId)
564
+ headers.set('ChatGPT-Account-ID', accountId);
565
+ return fetch('https://chatgpt.com/backend-api/codex/responses', {
566
+ method: 'POST',
567
+ headers,
568
+ body,
569
+ });
570
+ };
571
+ let activeModel = responsesModel;
474
572
  let response;
475
573
  try {
476
- response = await fetch('https://chatgpt.com/backend-api/codex/responses', {
477
- method: 'POST',
478
- headers: {
479
- Authorization: `Bearer ${auth.access}`,
480
- ...(auth.accountId && { 'ChatGPT-Account-ID': auth.accountId }),
481
- 'Content-Type': 'application/json',
482
- },
483
- body: JSON.stringify({
484
- model: 'gpt-5.4',
485
- instructions: 'You are Codex.',
486
- input: [
487
- {
488
- type: 'message',
489
- role: 'user',
490
- content,
491
- },
492
- ],
493
- tools: [
494
- {
495
- type: 'image_generation',
496
- model: opts.model,
497
- size: 'auto',
498
- quality: 'auto',
499
- output_format: 'png',
500
- output_compression: 100,
501
- moderation: 'auto',
502
- ...(size ? { size } : {}),
503
- },
504
- ],
505
- tool_choice: 'auto',
506
- parallel_tool_calls: true,
507
- stream: true,
508
- store: false,
509
- include: [],
510
- }),
574
+ response = await post({
575
+ access: auth.access,
576
+ accountId: auth.accountId,
577
+ body: requestBodyFor(activeModel),
511
578
  });
512
579
  }
513
580
  catch (err) {
@@ -515,7 +582,52 @@ async function generateWithResponsesApi(opts) {
515
582
  }
516
583
  if (!response.ok || !response.body) {
517
584
  const body = await response.text().catch(() => '');
518
- return new Error(`ChatGPT image generation failed: ${response.status}${body ? ` ${body}` : ''}`);
585
+ if (!(response.status === 400 && body.includes('not supported'))) {
586
+ if (!isRevokedChatGptAccessToken(response.status, body)) {
587
+ return new Error(`ChatGPT image generation failed: ${response.status}${body ? ` ${body}` : ''}`);
588
+ }
589
+ const refreshed = await refreshChatGptToken(auth);
590
+ if (refreshed instanceof Error)
591
+ return refreshed;
592
+ saveChatGptAuth(refreshed);
593
+ try {
594
+ response = await post({
595
+ access: refreshed.access,
596
+ accountId: refreshed.accountId,
597
+ body: requestBodyFor(activeModel),
598
+ });
599
+ }
600
+ catch (err) {
601
+ return toError(err);
602
+ }
603
+ }
604
+ else {
605
+ const nextModel = await resolveChatGptResponsesModel({
606
+ auth,
607
+ exclude: [activeModel],
608
+ });
609
+ if (nextModel instanceof Error) {
610
+ return new Error(`ChatGPT image generation failed: ${response.status} ${body}`);
611
+ }
612
+ activeModel = nextModel;
613
+ try {
614
+ response = await post({
615
+ access: auth.access,
616
+ accountId: auth.accountId,
617
+ body: requestBodyFor(activeModel),
618
+ });
619
+ }
620
+ catch (err) {
621
+ return toError(err);
622
+ }
623
+ }
624
+ if (!response.ok || !response.body) {
625
+ const retryBody = await response.text().catch(() => '');
626
+ if (isRevokedChatGptAccessToken(response.status, retryBody)) {
627
+ return new Error(chatGptReLoginMessage({ status: response.status, body: retryBody }));
628
+ }
629
+ return new Error(`ChatGPT image generation failed: ${response.status}${retryBody ? ` ${retryBody}` : ''}`);
630
+ }
519
631
  }
520
632
  let imageBase64;
521
633
  let revisedPrompt = null;
@@ -2,7 +2,7 @@
2
2
  // Tests the error-as-value pattern and validation logic without
3
3
  // making actual API calls (no credentials needed).
4
4
  import { describe, it, expect } from 'vitest';
5
- import { generateImage, generateVideo, calculateCost, buildImageProviderOptions, buildVideoProviderOptions, ValidationError, } from './generate.js';
5
+ import { generateImage, generateVideo, calculateCost, buildImageProviderOptions, buildVideoProviderOptions, aspectRatioFallback, ValidationError, } from './generate.js';
6
6
  describe('generateImage', () => {
7
7
  it('returns ValidationError for unknown model', async () => {
8
8
  const result = await generateImage({
@@ -110,6 +110,55 @@ describe('buildImageProviderOptions', () => {
110
110
  expect(opts).toEqual({});
111
111
  });
112
112
  });
113
+ describe('aspectRatioFallback', () => {
114
+ const openaiSizes = ['1024x1024', '1536x1024', '1024x1536'];
115
+ it('leaves the prompt untouched when no aspect ratio is requested', () => {
116
+ expect(aspectRatioFallback('a sunset', undefined, openaiSizes)).toMatchInlineSnapshot(`
117
+ {
118
+ "prompt": "a sunset",
119
+ }
120
+ `);
121
+ });
122
+ it('prepends the ratio and picks the closest landscape size', () => {
123
+ expect(aspectRatioFallback('a sunset', '16:9', openaiSizes)).toMatchInlineSnapshot(`
124
+ {
125
+ "prompt": "Image aspect ratio: 16:9, landscape orientation. a sunset",
126
+ "size": "1536x1024",
127
+ }
128
+ `);
129
+ });
130
+ it('picks the closest portrait size', () => {
131
+ expect(aspectRatioFallback('a sunset', '9:16', openaiSizes)).toMatchInlineSnapshot(`
132
+ {
133
+ "prompt": "Image aspect ratio: 9:16, portrait orientation. a sunset",
134
+ "size": "1024x1536",
135
+ }
136
+ `);
137
+ });
138
+ it('picks the square size for 1:1', () => {
139
+ expect(aspectRatioFallback('a sunset', '1:1', openaiSizes)).toMatchInlineSnapshot(`
140
+ {
141
+ "prompt": "Image aspect ratio: 1:1, square orientation. a sunset",
142
+ "size": "1024x1024",
143
+ }
144
+ `);
145
+ });
146
+ it('still prepends the ratio when the model has no size list', () => {
147
+ expect(aspectRatioFallback('a sunset', '21:9', [])).toMatchInlineSnapshot(`
148
+ {
149
+ "prompt": "Image aspect ratio: 21:9, landscape orientation. a sunset",
150
+ "size": undefined,
151
+ }
152
+ `);
153
+ });
154
+ it('ignores malformed ratios', () => {
155
+ expect(aspectRatioFallback('a sunset', '0:0', openaiSizes)).toMatchInlineSnapshot(`
156
+ {
157
+ "prompt": "a sunset",
158
+ }
159
+ `);
160
+ });
161
+ });
113
162
  describe('buildVideoProviderOptions', () => {
114
163
  it('builds xai edit-video options', () => {
115
164
  const opts = buildVideoProviderOptions('xai', {
@@ -1,9 +1,44 @@
1
- export declare function loginInteractive(): Promise<void>;
2
- export declare function loginNonInteractive({ provider, key, }: {
1
+ type LoginAction = {
2
+ type: 'show';
3
+ } | {
4
+ type: 'remove';
5
+ provider: string;
6
+ } | {
7
+ type: 'oauth-daemon';
8
+ provider: string;
9
+ } | {
10
+ type: 'oauth-client';
11
+ provider: string;
12
+ } | {
13
+ type: 'api-key';
14
+ provider: string;
15
+ key: string | undefined;
16
+ } | {
17
+ type: 'interactive';
18
+ };
19
+ export declare function resolveLoginAction({ options, daemonProvider, isAgent, }: {
20
+ options: {
21
+ provider?: string;
22
+ key?: string;
23
+ show?: boolean;
24
+ remove?: string;
25
+ };
26
+ daemonProvider: string | undefined;
27
+ isAgent: boolean;
28
+ }): LoginAction | Error;
29
+ export declare function loginInteractive({ loginOAuth, }: {
30
+ loginOAuth: (provider: string) => Promise<void>;
31
+ }): Promise<void>;
32
+ export declare function loginNonInteractive({ provider, key, background, }: {
3
33
  provider: string;
4
34
  key: string;
35
+ background?: boolean;
5
36
  }): Promise<void>;
6
- export declare function showLoginStatus(): void;
37
+ export declare function describeChatGptExpiry(expires: number, now: number): string;
38
+ export declare function showLoginStatus({ loginRunning }?: {
39
+ loginRunning?: boolean | undefined;
40
+ }): void;
7
41
  export declare function removeLogin(provider: string): void;
8
42
  export declare function readKeyFromStdin(): Promise<string>;
43
+ export {};
9
44
  //# sourceMappingURL=login.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"login.d.ts","sourceRoot":"","sources":["../../src/cli/login.ts"],"names":[],"mappings":"AA4BA,wBAAsB,gBAAgB,IAAI,OAAO,CAAC,IAAI,CAAC,CAkGtD;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,CAiChB;AAED,wBAAgB,eAAe,IAAI,IAAI,CA2DtC;AAED,wBAAgB,WAAW,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAalD;AAGD,wBAAsB,gBAAgB,IAAI,OAAO,CAAC,MAAM,CAAC,CAMxD"}
1
+ {"version":3,"file":"login.d.ts","sourceRoot":"","sources":["../../src/cli/login.ts"],"names":[],"mappings":"AA4BA,KAAK,WAAW,GACZ;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,GAChB;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,GACpC;IAAE,IAAI,EAAE,cAAc,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,GAC1C;IAAE,IAAI,EAAE,cAAc,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,GAC1C;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,GAAG,SAAS,CAAA;CAAE,GAC9D;IAAE,IAAI,EAAE,aAAa,CAAA;CAAE,CAAA;AAM3B,wBAAgB,kBAAkB,CAAC,EACjC,OAAO,EACP,cAAc,EACd,OAAO,GACR,EAAE;IACD,OAAO,EAAE;QACP,QAAQ,CAAC,EAAE,MAAM,CAAA;QACjB,GAAG,CAAC,EAAE,MAAM,CAAA;QACZ,IAAI,CAAC,EAAE,OAAO,CAAA;QACd,MAAM,CAAC,EAAE,MAAM,CAAA;KAChB,CAAA;IACD,cAAc,EAAE,MAAM,GAAG,SAAS,CAAA;IAClC,OAAO,EAAE,OAAO,CAAA;CACjB,GAAG,WAAW,GAAG,KAAK,CAiBtB;AAED,wBAAsB,gBAAgB,CAAC,EACrC,UAAU,GACX,EAAE;IACD,UAAU,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;CAChD,GAAG,OAAO,CAAC,IAAI,CAAC,CA8FhB;AAED,wBAAsB,mBAAmB,CAAC,EACxC,QAAQ,EACR,GAAG,EACH,UAAkB,GACnB,EAAE;IACD,QAAQ,EAAE,MAAM,CAAA;IAChB,GAAG,EAAE,MAAM,CAAA;IACX,UAAU,CAAC,EAAE,OAAO,CAAA;CACrB,GAAG,OAAO,CAAC,IAAI,CAAC,CAiChB;AAED,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CAG1E;AAED,wBAAgB,eAAe,CAAC,EAAE,YAAoB,EAAE;;CAAK,GAAG,IAAI,CA4DnE;AAED,wBAAgB,WAAW,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAalD;AAGD,wBAAsB,gBAAgB,IAAI,OAAO,CAAC,MAAM,CAAC,CAMxD"}
package/dist/cli/login.js CHANGED
@@ -1,13 +1,37 @@
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
+ // OAuth providers run through the login command's goke daemon.
5
5
  import { intro, outro, select, password, isCancel, cancel, log, note, } from '@clack/prompts';
6
- import pc from 'picocolors';
6
+ import { colors as pc } from 'goke';
7
7
  import { PROVIDERS, saveProviderKey, removeProviderKey, getKeyStatus, getChatGptAuth, saveChatGptAuth, getXaiAuth, saveXaiAuth, } from './credentials.js';
8
8
  import { chatGptOAuthLogin, extractPlanType } from './chatgpt-auth.js';
9
9
  import { xaiOAuthLogin } from './xai-auth.js';
10
- export async function loginInteractive() {
10
+ function isOAuthProvider(provider) {
11
+ return provider === 'chatgpt' || provider === 'xai-oauth';
12
+ }
13
+ export function resolveLoginAction({ options, daemonProvider, isAgent, }) {
14
+ if (options.show)
15
+ return { type: 'show' };
16
+ if (options.remove)
17
+ return { type: 'remove', provider: options.remove };
18
+ if (daemonProvider && !isOAuthProvider(daemonProvider)) {
19
+ return new Error(`Invalid background login provider: ${daemonProvider}`);
20
+ }
21
+ if (daemonProvider)
22
+ return { type: 'oauth-daemon', provider: daemonProvider };
23
+ if (options.provider && isOAuthProvider(options.provider)) {
24
+ return { type: 'oauth-client', provider: options.provider };
25
+ }
26
+ if (options.provider) {
27
+ return { type: 'api-key', provider: options.provider, key: options.key };
28
+ }
29
+ if (isAgent) {
30
+ return new Error('Missing --provider. Run egaki login --provider <name>.');
31
+ }
32
+ return { type: 'interactive' };
33
+ }
34
+ export async function loginInteractive({ loginOAuth, }) {
11
35
  intro(pc.bold('egaki login'));
12
36
  const providerOptions = Object.entries(PROVIDERS).map(([key, info]) => {
13
37
  const status = getKeyStatus(key);
@@ -58,16 +82,12 @@ export async function loginInteractive() {
58
82
  }
59
83
  // ChatGPT uses browser OAuth instead of key paste
60
84
  if (provider === 'chatgpt') {
61
- const auth = await chatGptOAuthLogin();
62
- saveChatGptAuth(auth);
63
- outro('Done — ChatGPT OAuth saved');
85
+ await loginOAuth(provider);
64
86
  return;
65
87
  }
66
88
  // xAI Grok Build uses browser OAuth
67
89
  if (provider === 'xai-oauth') {
68
- const auth = await xaiOAuthLogin();
69
- saveXaiAuth(auth);
70
- outro('Done — xAI OAuth saved');
90
+ await loginOAuth(provider);
71
91
  return;
72
92
  }
73
93
  log.info(`${pc.dim('Env var:')} ${info.envVar} ${pc.dim('(also used by the CLI when set)')}`);
@@ -89,7 +109,7 @@ export async function loginInteractive() {
89
109
  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');
90
110
  outro('Done');
91
111
  }
92
- export async function loginNonInteractive({ provider, key, }) {
112
+ export async function loginNonInteractive({ provider, key, background = false, }) {
93
113
  const info = PROVIDERS[provider];
94
114
  if (!info) {
95
115
  const available = Object.keys(PROVIDERS).join(', ');
@@ -98,14 +118,14 @@ export async function loginNonInteractive({ provider, key, }) {
98
118
  }
99
119
  // ChatGPT uses browser OAuth — key flag is not needed
100
120
  if (provider === 'chatgpt') {
101
- const auth = await chatGptOAuthLogin();
121
+ const auth = await chatGptOAuthLogin({ openInBackground: background });
102
122
  saveChatGptAuth(auth);
103
123
  console.log(pc.green('ChatGPT OAuth saved'));
104
124
  return;
105
125
  }
106
126
  // xAI Grok Build uses browser OAuth — key flag is not needed
107
127
  if (provider === 'xai-oauth') {
108
- const auth = await xaiOAuthLogin();
128
+ const auth = await xaiOAuthLogin({ openInBackground: background });
109
129
  saveXaiAuth(auth);
110
130
  console.log(pc.green('xAI OAuth saved'));
111
131
  return;
@@ -117,7 +137,14 @@ export async function loginNonInteractive({ provider, key, }) {
117
137
  saveProviderKey(provider, key.trim());
118
138
  console.log(pc.green(`${info.label} key saved`));
119
139
  }
120
- export function showLoginStatus() {
140
+ export function describeChatGptExpiry(expires, now) {
141
+ if (expires < now)
142
+ return 'expired locally, the next request will try to refresh';
143
+ return 'not expired locally';
144
+ }
145
+ export function showLoginStatus({ loginRunning = false } = {}) {
146
+ if (loginRunning)
147
+ console.log(pc.cyan('OAuth login is running in the background.\n'));
121
148
  console.log(pc.bold('Configured providers:\n'));
122
149
  for (const [key, info] of Object.entries(PROVIDERS)) {
123
150
  const status = getKeyStatus(key);
@@ -126,10 +153,10 @@ export function showLoginStatus() {
126
153
  if (auth) {
127
154
  const plan = extractPlanType(auth);
128
155
  const email = auth.email ?? auth.accountId ?? 'unknown';
129
- const expired = auth.expires < Date.now();
130
- const expiryLabel = expired
131
- ? pc.yellow('(token expired, will auto-refresh)')
132
- : pc.dim(`(token valid)`);
156
+ const expiryText = describeChatGptExpiry(auth.expires, Date.now());
157
+ const expiryLabel = auth.expires < Date.now()
158
+ ? pc.yellow(`(${expiryText})`)
159
+ : pc.dim(`(${expiryText})`);
133
160
  console.log(`${pc.green('*')} ${info.label} ${pc.green('(signed in)')}`);
134
161
  console.log(pc.dim(` account: ${email}${plan ? `, plan: ${plan}` : ''}`));
135
162
  console.log(` ${expiryLabel}`);
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=login.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"login.test.d.ts","sourceRoot":"","sources":["../../src/cli/login.test.ts"],"names":[],"mappings":""}