ima2-gen 1.1.20 → 1.1.21

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 (93) hide show
  1. package/README.md +15 -25
  2. package/bin/commands/capabilities.js +2 -2
  3. package/bin/commands/capabilities.ts +2 -2
  4. package/bin/commands/defaults.js +2 -2
  5. package/bin/commands/defaults.ts +2 -2
  6. package/bin/commands/doctor.js +3 -3
  7. package/bin/commands/doctor.ts +3 -3
  8. package/bin/commands/edit.js +1 -1
  9. package/bin/commands/edit.ts +1 -1
  10. package/bin/commands/gen.js +1 -1
  11. package/bin/commands/gen.ts +1 -1
  12. package/bin/commands/grok.js +16 -11
  13. package/bin/commands/grok.ts +16 -11
  14. package/bin/commands/multimode.js +1 -1
  15. package/bin/commands/multimode.ts +1 -1
  16. package/bin/commands/observability.js +2 -2
  17. package/bin/commands/observability.ts +2 -2
  18. package/bin/commands/video.js +335 -13
  19. package/bin/commands/video.ts +249 -12
  20. package/bin/ima2.js +9 -9
  21. package/bin/ima2.ts +9 -9
  22. package/bin/lib/error-hints.js +2 -2
  23. package/bin/lib/error-hints.ts +2 -2
  24. package/docs/API.md +112 -3
  25. package/docs/CLI.md +61 -7
  26. package/docs/FAQ.ko.md +15 -20
  27. package/docs/FAQ.md +14 -19
  28. package/docs/NPX_QUICKSTART.md +40 -0
  29. package/docs/PROMPT_STUDIO.ko.md +1 -1
  30. package/docs/PROMPT_STUDIO.md +1 -1
  31. package/docs/README.ja.md +6 -16
  32. package/docs/README.ko.md +10 -20
  33. package/docs/README.zh-CN.md +7 -17
  34. package/docs/migration/runtime-test-inventory.md +8 -1
  35. package/lib/agentRuntime.js +19 -5
  36. package/lib/agentRuntime.ts +17 -5
  37. package/lib/capabilities.js +1 -1
  38. package/lib/capabilities.ts +1 -1
  39. package/lib/generationErrors.js +1 -1
  40. package/lib/generationErrors.ts +1 -1
  41. package/lib/grokProxyLauncher.js +26 -3
  42. package/lib/grokProxyLauncher.ts +27 -3
  43. package/lib/grokVideoAdapter.js +18 -89
  44. package/lib/grokVideoAdapter.ts +27 -88
  45. package/lib/grokVideoCanvas.js +25 -0
  46. package/lib/grokVideoCanvas.ts +26 -0
  47. package/lib/grokVideoDownload.js +58 -0
  48. package/lib/grokVideoDownload.ts +59 -0
  49. package/lib/grokVideoPlannerPrompt.js +64 -0
  50. package/lib/grokVideoPlannerPrompt.ts +67 -0
  51. package/lib/historyList.js +7 -1
  52. package/lib/historyList.ts +5 -1
  53. package/lib/oauthLauncher.js +21 -6
  54. package/lib/oauthLauncher.ts +22 -6
  55. package/lib/videoContinuity.js +149 -0
  56. package/lib/videoContinuity.ts +180 -0
  57. package/lib/videoFrameExtract.js +80 -0
  58. package/lib/videoFrameExtract.ts +78 -0
  59. package/node_modules/progrok/dist/index.js +187 -88
  60. package/node_modules/progrok/dist/index.js.map +1 -1
  61. package/node_modules/progrok/package.json +1 -1
  62. package/node_modules/progrok/skills/progrok/SKILL.md +33 -4
  63. package/package.json +2 -2
  64. package/routes/index.js +4 -0
  65. package/routes/index.ts +4 -0
  66. package/routes/quota.js +66 -0
  67. package/routes/quota.ts +89 -0
  68. package/routes/video.js +77 -15
  69. package/routes/video.ts +82 -14
  70. package/routes/videoExtended.js +293 -0
  71. package/routes/videoExtended.ts +284 -0
  72. package/server.js +6 -2
  73. package/server.ts +5 -2
  74. package/skills/ima2/SKILL.md +320 -7
  75. package/ui/dist/.vite/manifest.json +12 -12
  76. package/ui/dist/assets/{AgentWorkspace-DS8uvoLI.js → AgentWorkspace-B_hq9CLg.js} +2 -2
  77. package/ui/dist/assets/{CardNewsWorkspace-CYxMsE67.js → CardNewsWorkspace-wD12J7qk.js} +1 -1
  78. package/ui/dist/assets/{NodeCanvas-DccIc347.js → NodeCanvas-CI_wuPMf.js} +1 -1
  79. package/ui/dist/assets/{PromptBuilderPanel-BvxxwSJp.js → PromptBuilderPanel-CUTujJUV.js} +1 -1
  80. package/ui/dist/assets/{PromptImportDialog-u1_BFDRd.js → PromptImportDialog-CUi66jPK.js} +2 -2
  81. package/ui/dist/assets/{PromptImportDiscoverySection-C5uvkVSz.js → PromptImportDiscoverySection-Cm3vrjY4.js} +1 -1
  82. package/ui/dist/assets/{PromptImportFolderSection-D3E_O1SD.js → PromptImportFolderSection-DOtWTD9n.js} +1 -1
  83. package/ui/dist/assets/{PromptLibraryPanel-4gyf9CB9.js → PromptLibraryPanel-BMjQegRa.js} +2 -2
  84. package/ui/dist/assets/SettingsWorkspace-PiaVnsdA.js +1 -0
  85. package/ui/dist/assets/{index-DoKtXbod.js → index-31uVIdt4.js} +1 -1
  86. package/ui/dist/assets/index-CjgnNtgt.css +1 -0
  87. package/ui/dist/assets/index-Da2s4_-5.js +36 -0
  88. package/ui/dist/index.html +2 -2
  89. package/vendor/progrok-0.2.0.tgz +0 -0
  90. package/ui/dist/assets/SettingsWorkspace-F3eNu3mJ.js +0 -1
  91. package/ui/dist/assets/index-B6tcw_UF.css +0 -1
  92. package/ui/dist/assets/index-DYOh6gQD.js +0 -32
  93. package/vendor/progrok-0.1.1.tgz +0 -0
package/README.md CHANGED
@@ -16,25 +16,20 @@
16
16
 
17
17
  `ima2-gen` is a local image generation studio for people who want the ChatGPT/Codex image workflow in a small desktop-like web app.
18
18
 
19
- Run it with `npx`, sign in with ChatGPT OAuth or Grok OAuth, and start generating images and videos. Iterate with history, references, node branches, multimode batches, Canvas Mode cleanup, and Grok Video generation. No API key required — free ChatGPT OAuth and SuperGrok subscription cover everything.
19
+ Install globally, sign in with ChatGPT OAuth or Grok OAuth, and start generating images and videos. Iterate with history, references, node branches, multimode batches, Canvas Mode cleanup, and Grok Video generation. No API key required — free ChatGPT OAuth and SuperGrok subscription cover everything.
20
20
 
21
21
  ![ima2-gen video playback with gallery sidebar showing generated images and videos.](assets/screenshots/classic-generate-light.png)
22
22
 
23
23
  ## Quick Start
24
24
 
25
25
  ```bash
26
- npx ima2-gen serve
26
+ npm install -g ima2-gen
27
+ ima2 setup
28
+ ima2 serve
27
29
  ```
28
30
 
29
31
  Then open `http://localhost:3333`.
30
32
 
31
- If Codex is not logged in yet:
32
-
33
- ```bash
34
- npx @openai/codex login
35
- npx ima2-gen serve
36
- ```
37
-
38
33
  To generate a video from the CLI:
39
34
 
40
35
  ```bash
@@ -44,12 +39,7 @@ ima2 video "animate this scene" --ref photo.png --duration 10
44
39
 
45
40
  If `3333` is already occupied, `ima2-gen` binds the next available port and writes the actual URL to `~/.ima2/server.json`. Use `ima2 open` or the URL printed in the terminal instead of assuming the port.
46
41
 
47
- You can also install it globally:
48
-
49
- ```bash
50
- npm install -g ima2-gen
51
- ima2 serve
52
- ```
42
+ > **Using npx?** See [docs/NPX_QUICKSTART.md](docs/NPX_QUICKSTART.md) for the `npx ima2-gen serve` workflow.
53
43
 
54
44
  ### Setup
55
45
 
@@ -60,7 +50,7 @@ ima2 serve
60
50
  3. **Both** — GPT OAuth + Grok OAuth (full feature access)
61
51
  4. **API Key** — paste your OpenAI API key (paid)
62
52
 
63
- Video generation requires Grok OAuth (option 2 or 3). Run `ima2 grok login` separately if you already have GPT OAuth configured and want to add video support.
53
+ Video generation requires Grok OAuth (option 2 or 3). Run `ima2 grok login` separately if you already have GPT OAuth configured and want to add video support; it defaults to the manual-paste flow.
64
54
 
65
55
  Before updating a global install on Windows, stop any running `ima2 serve`
66
56
  process. If npm reports `EBUSY` or `resource busy or locked`, close ima2
@@ -90,11 +80,11 @@ Image generation can run through the local Codex/ChatGPT OAuth path, a configure
90
80
  - API-key generation supports classic generate, edit, mask-guided edit, multimode, and node generation.
91
81
  - Grok generation supports Classic, Node, and Agent flows. If a Classic reference, Node parent image, or Agent current image is present, ima2 switches the final Grok call to xAI image edit so image-to-image context is preserved.
92
82
 
93
- If no provider is specified, the app keeps the current OAuth/default behavior. API-key generation defaults to `gpt-5.4-mini`, `low` reasoning, and `1024x1024` unless the request passes validated model, reasoning, size, or web-search options. Grok defaults to `grok-imagine-image`; `quality: "high"` promotes the final image call to `grok-imagine-image-quality`.
83
+ If no provider is specified, the app keeps the current GPT OAuth/default behavior. API-key generation defaults to `gpt-5.4-mini`, `low` reasoning, and `1024x1024` unless the request passes validated model, reasoning, size, or web-search options. Grok defaults to `grok-imagine-image`; `quality: "high"` promotes the final image call to `grok-imagine-image-quality`.
94
84
 
95
- Grok video generation uses `grok-imagine-video` (default) or `grok-imagine-video-1.5-preview`. Three modes are auto-detected from reference count: text-to-video (0 refs), image-to-video (1 ref), and reference-to-video (2–7 refs, max 10s duration). Video controls include duration (1–15s), resolution (480p, 720p), and aspect ratio (1:1, 16:9, 9:16, 4:3, 3:4, 3:2, 2:3, auto).
85
+ Grok video generation uses `grok-imagine-video` (default) or `grok-imagine-video-1.5-preview`. Three modes are auto-detected from reference count: text-to-video (0 refs), image-to-video (1 ref), and reference-to-video (2–7 refs, max 10s duration). `grok-imagine-video-1.5-preview` supports image-to-video but not `reference_images` Ref2V, so 2+ refs use `grok-imagine-video` as the effective model. Video edit and extension are also base-model only. Video controls include duration (1–15s), resolution (480p, 720p), and aspect ratio (1:1, 16:9, 9:16, 4:3, 3:4, 3:2, 2:3, auto).
96
86
 
97
- ![Settings workspace showing OAuth active and API key provider available.](assets/screenshots/settings-oauth-generation.png)
87
+ ![Settings workspace showing GPT OAuth active and API key provider available.](assets/screenshots/settings-oauth-generation.png)
98
88
 
99
89
  ## Model Guidance
100
90
 
@@ -225,7 +215,7 @@ environment variables > ~/.ima2/config.json > built-in defaults
225
215
  | `IMA2_ADVERTISE_FILE` | `~/.ima2/server.json` | Runtime discovery file |
226
216
  | `IMA2_GENERATED_DIR` | `~/.ima2/generated` | Generated image directory |
227
217
  | `IMA2_IMAGE_MODEL_DEFAULT` | `gpt-5.4-mini` | Server fallback image model |
228
- | `IMA2_REASONING_EFFORT` | `medium` | Default reasoning effort for the default (OAuth) path; one of `none`, `low`, `medium`, `high`, `xhigh` |
218
+ | `IMA2_REASONING_EFFORT` | `medium` | Default reasoning effort for the default (GPT OAuth) path; one of `none`, `low`, `medium`, `high`, `xhigh` |
229
219
  | `IMA2_NO_OAUTH_PROXY` | — | Set `1` to disable the auto-started OAuth proxy |
230
220
  | `IMA2_LOG_LEVEL` | `info` | Normal serve defaults to `info`; dev mode defaults to `debug`; supports `debug`, `info`, `warn`, `error`, or `silent` |
231
221
  | `IMA2_INFLIGHT_TERMINAL_TTL_MS` | `300000` | Recent terminal job retention for debug views |
@@ -270,17 +260,17 @@ Useful references:
270
260
  **`ima2 ping` says the server is unreachable**
271
261
  Start `ima2 serve`, then check `~/.ima2/server.json`. You can also run `ima2 ping --server http://localhost:3333`.
272
262
 
273
- **OAuth login does not work**
274
- Run `npx @openai/codex login`, confirm `ima2 status`, then restart `ima2 serve`.
263
+ **GPT OAuth login does not work**
264
+ Re-run `ima2 setup` (option 1), confirm `ima2 status`, then restart `ima2 serve`.
275
265
 
276
266
  **`fetch failed` repeats on a proxy/VPN network**
277
- Check that the local OAuth proxy is reachable. On networks that require a proxy, enable your proxy client's TUN/TURN-style mode, then retry `npx openai-oauth --port 10531`. If it still fails, set `HTTP_PROXY` and `HTTPS_PROXY` in the same terminal that runs `ima2 serve` or `openai-oauth`. On Windows, also check for auto-start network interception tools, including DNS/fragmentation bypass tools such as SecretDNS, because they can break OAuth or streaming image responses even when the browser appears connected.
267
+ Check that the local OAuth proxy is reachable. On networks that require a proxy, enable your proxy client's TUN/TURN-style mode, then retry `openai-oauth --port 10531`. If it still fails, set `HTTP_PROXY` and `HTTPS_PROXY` in the same terminal that runs `ima2 serve` or `openai-oauth`. On Windows, also check for auto-start network interception tools, including DNS/fragmentation bypass tools such as SecretDNS, because they can break OAuth or streaming image responses even when the browser appears connected.
278
268
 
279
269
  **Images fail with `API_KEY_REQUIRED`**
280
- Set `OPENAI_API_KEY` or configure an API key before using `provider: "api"`. The default OAuth path still works without an API key.
270
+ Set `OPENAI_API_KEY` or configure an API key before using `provider: "api"`. The default GPT OAuth path still works without an API key.
281
271
 
282
272
  **Image generation returns `EMPTY_RESPONSE` or no image data**
283
- Run `ima2 doctor image-probe --json > ima2-image-probe.json` and attach the safe JSON when opening an issue. For OAuth cases, also capture `ima2 gen "고양이" --no-web-search --json` and `ima2 gen "고양이" --json` while `ima2 serve` is running. Do not share ChatGPT cookies, OAuth token files, API keys, raw upstream responses, prompt history, or generated base64. See the [FAQ support bundle](docs/FAQ.md#what-should-i-share-when-oauth-image-generation-returns-no-image).
273
+ Run `ima2 doctor image-probe --json > ima2-image-probe.json` and attach the safe JSON when opening an issue. For GPT OAuth cases, also capture `ima2 gen "고양이" --no-web-search --json` and `ima2 gen "고양이" --json` while `ima2 serve` is running. Do not share ChatGPT cookies, OAuth token files, API keys, raw upstream responses, prompt history, or generated base64. See the [FAQ support bundle](docs/FAQ.md#what-should-i-share-when-oauth-image-generation-returns-no-image).
284
274
 
285
275
  **A large reference image fails**
286
276
  The app compresses large JPEG/PNG references before upload. If a file still fails, convert it to JPEG or PNG at a lower resolution and try again. HEIC/HEIF files are not supported by the browser path.
@@ -58,8 +58,8 @@ function printText(capabilities) {
58
58
  out(`server: ${capabilities.server || "none"}`);
59
59
  out("");
60
60
  out("defaults:");
61
- out(` oauth model: ${capabilities.defaults?.oauth?.model}`);
62
- out(` oauth reasoning: ${capabilities.defaults?.oauth?.reasoningEffort}`);
61
+ out(` gpt-oauth model: ${capabilities.defaults?.oauth?.model}`);
62
+ out(` gpt-oauth reasoning: ${capabilities.defaults?.oauth?.reasoningEffort}`);
63
63
  out(` api model: ${capabilities.defaults?.api?.model}`);
64
64
  out(` api reasoning: ${capabilities.defaults?.api?.reasoningEffort}`);
65
65
  out(` grok model: ${capabilities.defaults?.grok?.model}`);
@@ -62,8 +62,8 @@ function printText(capabilities: any): void {
62
62
  out(`server: ${capabilities.server || "none"}`);
63
63
  out("");
64
64
  out("defaults:");
65
- out(` oauth model: ${capabilities.defaults?.oauth?.model}`);
66
- out(` oauth reasoning: ${capabilities.defaults?.oauth?.reasoningEffort}`);
65
+ out(` gpt-oauth model: ${capabilities.defaults?.oauth?.model}`);
66
+ out(` gpt-oauth reasoning: ${capabilities.defaults?.oauth?.reasoningEffort}`);
67
67
  out(` api model: ${capabilities.defaults?.api?.model}`);
68
68
  out(` api reasoning: ${capabilities.defaults?.api?.reasoningEffort}`);
69
69
  out(` grok model: ${capabilities.defaults?.grok?.model}`);
@@ -12,8 +12,8 @@ const HELP = `
12
12
 
13
13
  Subcommands:
14
14
  ls Show effective defaults
15
- set model <model> Persist default model for OAuth and API paths
16
- set reasoning <effort> Persist default reasoning effort for OAuth and API paths
15
+ set model <model> Persist default model for GPT OAuth and API paths
16
+ set reasoning <effort> Persist default reasoning effort for GPT OAuth and API paths
17
17
  reset model Remove persisted model defaults
18
18
  reset reasoning Remove persisted reasoning defaults
19
19
 
@@ -25,8 +25,8 @@ const HELP = `
25
25
 
26
26
  Subcommands:
27
27
  ls Show effective defaults
28
- set model <model> Persist default model for OAuth and API paths
29
- set reasoning <effort> Persist default reasoning effort for OAuth and API paths
28
+ set model <model> Persist default model for GPT OAuth and API paths
29
+ set reasoning <effort> Persist default reasoning effort for GPT OAuth and API paths
30
30
  reset model Remove persisted model defaults
31
31
  reset reasoning Remove persisted reasoning defaults
32
32
 
@@ -63,7 +63,7 @@ function showImageProbeHelp() {
63
63
  --quality <quality> Default: low
64
64
  --moderation <value> Default: low
65
65
  --prompt <text> Override built-in cat prompt
66
- --oauth-url <url> Override OAuth proxy URL
66
+ --oauth-url <url> Override GPT OAuth proxy URL
67
67
  --timeout-ms <ms> Per-probe timeout
68
68
  `);
69
69
  }
@@ -155,7 +155,7 @@ async function standardDoctor() {
155
155
  if (adv?.backend || adv?.port) {
156
156
  console.log(` ℹ Backend actual URL: ${adv?.backend?.url || adv?.url || `http://localhost:${adv.port}`}`);
157
157
  if (adv?.oauth)
158
- console.log(` ℹ OAuth actual URL: ${adv.oauth.url} (${adv.oauth.status || "unknown"})`);
158
+ console.log(` ℹ GPT OAuth actual URL: ${adv.oauth.url} (${adv.oauth.status || "unknown"})`);
159
159
  }
160
160
  const hardeningLines = await buildHardeningDoctorLines({
161
161
  root: ROOT,
@@ -182,7 +182,7 @@ async function standardDoctor() {
182
182
  console.log(line);
183
183
  const auth = detectCodexAuth();
184
184
  if (auth.platform === "win32")
185
- console.log(" ℹ Windows OAuth note: use WSL2 for Codex login.");
185
+ console.log(" ℹ Windows GPT OAuth note: use WSL2 for Codex login.");
186
186
  console.log(`\n ${ok} passed, ${fail} failed\n`);
187
187
  process.exit(fail > 0 ? 1 : 0);
188
188
  }
@@ -63,7 +63,7 @@ function showImageProbeHelp() {
63
63
  --quality <quality> Default: low
64
64
  --moderation <value> Default: low
65
65
  --prompt <text> Override built-in cat prompt
66
- --oauth-url <url> Override OAuth proxy URL
66
+ --oauth-url <url> Override GPT OAuth proxy URL
67
67
  --timeout-ms <ms> Per-probe timeout
68
68
  `);
69
69
  }
@@ -160,7 +160,7 @@ async function standardDoctor() {
160
160
  console.log(` ℹ Preferred backend port: ${runtimeConfig.server.port}`);
161
161
  if (adv?.backend || adv?.port) {
162
162
  console.log(` ℹ Backend actual URL: ${adv?.backend?.url || adv?.url || `http://localhost:${adv.port}`}`);
163
- if (adv?.oauth) console.log(` ℹ OAuth actual URL: ${adv.oauth.url} (${adv.oauth.status || "unknown"})`);
163
+ if (adv?.oauth) console.log(` ℹ GPT OAuth actual URL: ${adv.oauth.url} (${adv.oauth.status || "unknown"})`);
164
164
  }
165
165
 
166
166
  const hardeningLines = await buildHardeningDoctorLines({
@@ -187,7 +187,7 @@ async function standardDoctor() {
187
187
  for (const line of storageLines) console.log(line);
188
188
 
189
189
  const auth = detectCodexAuth();
190
- if (auth.platform === "win32") console.log(" ℹ Windows OAuth note: use WSL2 for Codex login.");
190
+ if (auth.platform === "win32") console.log(" ℹ Windows GPT OAuth note: use WSL2 for Codex login.");
191
191
 
192
192
  console.log(`\n ${ok} passed, ${fail} failed\n`);
193
193
  process.exit(fail > 0 ? 1 : 0);
@@ -41,7 +41,7 @@ const HELP = `
41
41
  -o, --out <file>
42
42
  --json
43
43
  --model <gpt-5.5|gpt-5.4|gpt-5.4-mini|grok-imagine-image|grok-imagine-image-quality>
44
- --provider <auto|oauth|api|grok> Provider for this request; grok uses progrok proxy
44
+ --provider <auto|oauth|api|grok> Provider (oauth = GPT OAuth; grok = xAI Grok)
45
45
  --mode <auto|direct> Prompt handling mode. Default: auto
46
46
  --moderation <auto|low> Default: low
47
47
  --session <id> Apply session style sheet if enabled
@@ -44,7 +44,7 @@ const HELP = `
44
44
  -o, --out <file>
45
45
  --json
46
46
  --model <gpt-5.5|gpt-5.4|gpt-5.4-mini|grok-imagine-image|grok-imagine-image-quality>
47
- --provider <auto|oauth|api|grok> Provider for this request; grok uses progrok proxy
47
+ --provider <auto|oauth|api|grok> Provider (oauth = GPT OAuth; grok = xAI Grok)
48
48
  --mode <auto|direct> Prompt handling mode. Default: auto
49
49
  --moderation <auto|low> Default: low
50
50
  --session <id> Apply session style sheet if enabled
@@ -52,7 +52,7 @@ const HELP = `
52
52
  --timeout <sec> Default: 180
53
53
  --server <url> Override server URL
54
54
  --model <gpt-5.5|gpt-5.4|gpt-5.4-mini|grok-imagine-image|grok-imagine-image-quality>
55
- --provider <auto|oauth|api|grok> Provider for this request; grok uses progrok proxy
55
+ --provider <auto|oauth|api|grok> Provider (oauth = GPT OAuth; grok = xAI Grok)
56
56
  --mode <auto|direct> Prompt handling mode. Default: auto
57
57
  --moderation <auto|low> Default: low
58
58
  --session <id> Apply session style sheet if enabled
@@ -55,7 +55,7 @@ const HELP = `
55
55
  --timeout <sec> Default: 180
56
56
  --server <url> Override server URL
57
57
  --model <gpt-5.5|gpt-5.4|gpt-5.4-mini|grok-imagine-image|grok-imagine-image-quality>
58
- --provider <auto|oauth|api|grok> Provider for this request; grok uses progrok proxy
58
+ --provider <auto|oauth|api|grok> Provider (oauth = GPT OAuth; grok = xAI Grok)
59
59
  --mode <auto|direct> Prompt handling mode. Default: auto
60
60
  --moderation <auto|low> Default: low
61
61
  --session <id> Apply session style sheet if enabled
@@ -20,8 +20,11 @@ const HELP = `
20
20
 
21
21
  Notes:
22
22
  ima2 serve auto-starts the bundled proxy on 127.0.0.1:18645 by default.
23
+ ima2 grok login defaults to --manual-paste for reliable copy/paste auth.
23
24
  Use IMA2_NO_GROK_PROXY=1 to disable automatic proxy startup.
24
25
  `;
26
+ const MANUAL_PASTE_FLAG = "--manual-paste";
27
+ const NON_MANUAL_LOGIN_FLOW_FLAGS = new Set(["--device-code", "--browser"]);
25
28
  function localBinPath() {
26
29
  return join(ROOT, "node_modules", ".bin");
27
30
  }
@@ -39,6 +42,15 @@ function spawnProgrok(argv, env) {
39
42
  child.on("close", resolve);
40
43
  });
41
44
  }
45
+ export function normalizeGrokLoginArgs(argv) {
46
+ const sub = argv[0];
47
+ if (sub !== "login")
48
+ return argv;
49
+ const normalized = argv.filter((arg) => !NON_MANUAL_LOGIN_FLOW_FLAGS.has(arg));
50
+ if (normalized.includes(MANUAL_PASTE_FLAG))
51
+ return normalized;
52
+ return [...normalized, MANUAL_PASTE_FLAG];
53
+ }
42
54
  export default async function grokCmd(argv) {
43
55
  const sub = argv[0];
44
56
  if (!sub || sub === "--help" || sub === "-h") {
@@ -50,20 +62,13 @@ export default async function grokCmd(argv) {
50
62
  PATH: `${localBinPath()}${delimiter}${process.env.PATH || ""}`,
51
63
  };
52
64
  try {
53
- // Default to --manual-paste for login (most reliable across platforms).
54
- // Users can still pass --device-code or --browser explicitly.
55
- if (sub === "login" && !argv.includes("--device-code") && !argv.includes("--browser") && !argv.includes("--manual-paste")) {
56
- argv = [...argv, "--manual-paste"];
57
- }
65
+ argv = normalizeGrokLoginArgs(argv);
58
66
  const code = await spawnProgrok(argv, env);
59
67
  if (code && code !== 0) {
60
- // progrok 0.1.1+ defaults to device-code flow already.
61
- // Do NOT auto-retry with --device-code — it issues a NEW code that
62
- // invalidates the one the user may already be looking at in their browser.
63
- if (sub === "login" && !argv.includes("--device-code")) {
68
+ if (sub === "login") {
64
69
  out(color.yellow("⚠ ") + "Login failed. Try again with:\n");
65
- out(" ima2 grok login --device-code\n");
66
- die(code, "bundled progrok login failed");
70
+ out(" ima2 grok login\n");
71
+ die(code, "bundled Grok OAuth login failed");
67
72
  }
68
73
  else {
69
74
  die(code, `bundled progrok exited with code ${code}`);
@@ -21,9 +21,13 @@ const HELP = `
21
21
 
22
22
  Notes:
23
23
  ima2 serve auto-starts the bundled proxy on 127.0.0.1:18645 by default.
24
+ ima2 grok login defaults to --manual-paste for reliable copy/paste auth.
24
25
  Use IMA2_NO_GROK_PROXY=1 to disable automatic proxy startup.
25
26
  `;
26
27
 
28
+ const MANUAL_PASTE_FLAG = "--manual-paste";
29
+ const NON_MANUAL_LOGIN_FLOW_FLAGS = new Set(["--device-code", "--browser"]);
30
+
27
31
  function localBinPath() {
28
32
  return join(ROOT, "node_modules", ".bin");
29
33
  }
@@ -43,6 +47,14 @@ function spawnProgrok(argv: string[], env: NodeJS.ProcessEnv): Promise<number |
43
47
  });
44
48
  }
45
49
 
50
+ export function normalizeGrokLoginArgs(argv: string[]): string[] {
51
+ const sub = argv[0];
52
+ if (sub !== "login") return argv;
53
+ const normalized = argv.filter((arg) => !NON_MANUAL_LOGIN_FLOW_FLAGS.has(arg));
54
+ if (normalized.includes(MANUAL_PASTE_FLAG)) return normalized;
55
+ return [...normalized, MANUAL_PASTE_FLAG];
56
+ }
57
+
46
58
  export default async function grokCmd(argv: string[]) {
47
59
  const sub = argv[0];
48
60
  if (!sub || sub === "--help" || sub === "-h") {
@@ -56,21 +68,14 @@ export default async function grokCmd(argv: string[]) {
56
68
  };
57
69
 
58
70
  try {
59
- // Default to --manual-paste for login (most reliable across platforms).
60
- // Users can still pass --device-code or --browser explicitly.
61
- if (sub === "login" && !argv.includes("--device-code") && !argv.includes("--browser") && !argv.includes("--manual-paste")) {
62
- argv = [...argv, "--manual-paste"];
63
- }
71
+ argv = normalizeGrokLoginArgs(argv);
64
72
 
65
73
  const code = await spawnProgrok(argv, env);
66
74
  if (code && code !== 0) {
67
- // progrok 0.1.1+ defaults to device-code flow already.
68
- // Do NOT auto-retry with --device-code — it issues a NEW code that
69
- // invalidates the one the user may already be looking at in their browser.
70
- if (sub === "login" && !argv.includes("--device-code")) {
75
+ if (sub === "login") {
71
76
  out(color.yellow("⚠ ") + "Login failed. Try again with:\n");
72
- out(" ima2 grok login --device-code\n");
73
- die(code, "bundled progrok login failed");
77
+ out(" ima2 grok login\n");
78
+ die(code, "bundled Grok OAuth login failed");
74
79
  } else {
75
80
  die(code, `bundled progrok exited with code ${code}`);
76
81
  }
@@ -41,7 +41,7 @@ const HELP = `
41
41
  -d, --out-dir <dir> Output dir for multiple images
42
42
  --json
43
43
  --model <gpt-5.5|gpt-5.4|gpt-5.4-mini>
44
- --provider <auto|oauth|api|grok> Provider for this request; grok uses progrok proxy
44
+ --provider <auto|oauth|api|grok> Provider (oauth = GPT OAuth; grok = xAI Grok)
45
45
  --mode <auto|direct> Prompt handling mode. Default: auto
46
46
  --ref <file> Attach reference image (repeatable, max 5)
47
47
  --reasoning-effort <none|low|medium|high|xhigh>
@@ -43,7 +43,7 @@ const HELP = `
43
43
  -d, --out-dir <dir> Output dir for multiple images
44
44
  --json
45
45
  --model <gpt-5.5|gpt-5.4|gpt-5.4-mini>
46
- --provider <auto|oauth|api|grok> Provider for this request; grok uses progrok proxy
46
+ --provider <auto|oauth|api|grok> Provider (oauth = GPT OAuth; grok = xAI Grok)
47
47
  --mode <auto|direct> Prompt handling mode. Default: auto
48
48
  --ref <file> Attach reference image (repeatable, max 5)
49
49
  --reasoning-effort <none|low|medium|high|xhigh>
@@ -8,10 +8,10 @@ const HELP = `
8
8
  storage status [--json] Storage inspection
9
9
  storage open Open generated-dir in OS file manager
10
10
 
11
- Billing / Providers / OAuth:
11
+ Billing / Providers / GPT OAuth:
12
12
  billing [--json] API usage / quota
13
13
  providers [--json] Configured providers
14
- oauth status [--json] OAuth proxy state
14
+ oauth status [--json] GPT OAuth proxy state
15
15
 
16
16
  Inflight jobs:
17
17
  inflight ls [--kind classic|node|multimode] [--session <id>] [--terminal] [--json]
@@ -9,10 +9,10 @@ const HELP = `
9
9
  storage status [--json] Storage inspection
10
10
  storage open Open generated-dir in OS file manager
11
11
 
12
- Billing / Providers / OAuth:
12
+ Billing / Providers / GPT OAuth:
13
13
  billing [--json] API usage / quota
14
14
  providers [--json] Configured providers
15
- oauth status [--json] OAuth proxy state
15
+ oauth status [--json] GPT OAuth proxy state
16
16
 
17
17
  Inflight jobs:
18
18
  inflight ls [--kind classic|node|multimode] [--session <id>] [--terminal] [--json]