ima2-gen 1.0.10 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -6,203 +6,123 @@
6
6
 
7
7
  > **Read in other languages**: [한국어](docs/README.ko.md) · [日本語](docs/README.ja.md) · [简体中文](docs/README.zh-CN.md)
8
8
 
9
- `ima2-gen` is a local CLI + web studio for OpenAI image generation through the ChatGPT/Codex OAuth route. It includes a React UI, headless CLI commands, persistent history, reference uploads, production node-mode branching, and safe request observability.
9
+ `ima2-gen` is a local image generation studio for people who want the ChatGPT/Codex image workflow in a small desktop-like web app.
10
10
 
11
- Generation is currently **OAuth-only**. API keys can still be configured for auxiliary developer paths such as billing/status checks and style-sheet extraction, but image generation endpoints reject `provider: "api"` with `APIKEY_DISABLED` unless the provider policy is intentionally changed in code.
11
+ Run it with `npx`, sign in with Codex OAuth, type a prompt, and keep iterating with history, references, style sheets, and node branches. No OpenAI API key is required for image generation in the default path.
12
12
 
13
- ![ima2-gen screenshot](assets/screenshot.png)
14
-
15
- ---
13
+ ![ima2-gen classic generation screen with prompt composer, generated image, compact model label, and result metadata.](assets/screenshots/classic-generate-light.png)
16
14
 
17
15
  ## Quick Start
18
16
 
19
17
  ```bash
20
- # Run instantly with npx
21
18
  npx ima2-gen serve
22
-
23
- # Or install globally
24
- npm install -g ima2-gen
25
- ima2 serve
26
19
  ```
27
20
 
28
- The first run opens setup:
21
+ Then open `http://localhost:3333`.
29
22
 
30
- ```text
31
- 1) API Key — save an OpenAI API key for supported auxiliary paths
32
- 2) OAuth — log in with a ChatGPT/Codex account for image generation
33
- ```
34
-
35
- For the current release, choose OAuth for generation. If Codex is not logged in yet, run:
23
+ If Codex is not logged in yet:
36
24
 
37
25
  ```bash
38
26
  npx @openai/codex login
39
- ima2 serve
27
+ npx ima2-gen serve
40
28
  ```
41
29
 
42
- The web UI opens at `http://localhost:3333` by default.
30
+ You can also install it globally:
43
31
 
44
- ---
45
-
46
- ## What Works Now
47
-
48
- ### OAuth Generation
49
-
50
- - Text-to-image through `/api/generate`
51
- - Image edit / image-to-image through `/api/edit`
52
- - Up to 5 reference images per root generation
53
- - Quality controls: `low`, `medium`, `high`
54
- - Moderation controls: `low`, `auto`
55
- - PNG/JPEG/WebP output
56
- - Parallel count: 1, 2, or 4 from the UI; CLI/server cap is 8
57
- - Size presets aligned to `gpt-image-2` constraints
58
-
59
- ### UI Workflow
60
-
61
- - Prompt composer with drag/drop and Cmd/Ctrl+V image paste
62
- - Current-image reuse from the canvas
63
- - Gallery strip and full gallery modal
64
- - Delete/restore for generated assets
65
- - Settings workspace opened from the header gear
66
- - Theme and account/status settings moved out of the crowded sidebar
67
- - Right sidebar now contains only generation details
68
- - In-flight jobs survive refresh and reconcile back into the UI
69
-
70
- ### Node Mode
32
+ ```bash
33
+ npm install -g ima2-gen
34
+ ima2 serve
35
+ ```
71
36
 
72
- Node mode is available in the packaged web UI and can be opened from the mode switch next to the composer.
37
+ ## What It Does
73
38
 
74
- - SQLite-backed graph sessions
75
- - Branching child generations
76
- - Duplicate branch / new-from-here flows
77
- - Node-local reference attachments for root nodes with drag/drop, paste, and file picker support
78
- - Reference count metadata in node sidecars and history responses
79
- - Session style sheets that can prepend a house style to node/classic prompts
80
- - Gallery grouping by session title instead of raw server IDs
39
+ - **Classic mode**: generate, edit, reuse the current image, paste references, and continue from history.
40
+ - **Node mode**: branch a good image into multiple directions without losing the original.
41
+ - **Local gallery**: keep generated assets on your machine with session-aware history.
42
+ - **Reference images**: drag, drop, paste, and attach up to 5 references; large images are compressed before upload.
43
+ - **Style sheets**: extract and reuse a visual direction across classic and node prompts.
44
+ - **Observable jobs**: active and recent jobs are tracked with safe logs and request IDs.
81
45
 
82
- ### Observability
46
+ ## OAuth Only For Image Generation
83
47
 
84
- - Safe structured logs for generation, edit, node, OAuth, session, history, and in-flight lifecycle
85
- - Correlation by `requestId`
86
- - Active-only `/api/inflight` by default
87
- - Optional recent terminal jobs via `/api/inflight?includeTerminal=1`
88
- - Logs avoid raw prompts, effective prompts, revised prompts, tokens, auth headers, cookies, request bodies, reference data URLs, generated base64, and raw upstream response bodies
48
+ Image generation currently runs through the local Codex/ChatGPT OAuth path.
89
49
 
90
- ---
50
+ API keys may still be detected for auxiliary developer features such as billing checks or style-sheet extraction, but generation routes reject `provider: "api"` with `APIKEY_DISABLED`.
91
51
 
92
- ## CLI Commands
52
+ If the settings page says **Configured but disabled**, that means an API key exists in env/config but image generation still uses OAuth.
93
53
 
94
- ### Server Commands
54
+ ![Settings workspace showing OAuth active and API key configured but disabled.](assets/screenshots/settings-oauth-generation.png)
95
55
 
96
- | Command | Alias | Description |
97
- |---|---|---|
98
- | `ima2 serve` | — | Start the local web server |
99
- | `ima2 setup` | `login` | Reconfigure saved auth |
100
- | `ima2 status` | — | Show config and OAuth session status |
101
- | `ima2 doctor` | — | Diagnose Node, package, config, and auth state |
102
- | `ima2 open` | — | Open the web UI |
103
- | `ima2 reset` | — | Remove saved config |
104
- | `ima2 --version` | `-v` | Print package version |
105
- | `ima2 --help` | `-h` | Print help |
56
+ ## Model Guidance
106
57
 
107
- ### Client Commands
58
+ Start with **`gpt-5.4`** when you want the safest balanced image workflow.
108
59
 
109
- These require a running `ima2 serve`.
60
+ - `gpt-5.4` recommended balanced choice.
61
+ - `gpt-5.4-mini` — current app default and faster draft model.
62
+ - `gpt-5.5` — strongest quality option when your Codex CLI/OAuth backend supports it. It may use more quota, expose different tool capabilities, or require updating Codex CLI before it works reliably.
110
63
 
111
- | Command | Description |
112
- |---|---|
113
- | `ima2 gen <prompt>` | Generate image(s) from the CLI |
114
- | `ima2 edit <file> --prompt <text>` | Edit an existing image |
115
- | `ima2 ls` | List history, table or `--json` |
116
- | `ima2 show <name>` | Show/reveal a generated asset |
117
- | `ima2 ps` | List active in-flight jobs |
118
- | `ima2 ping` | Health-check the running server |
64
+ The app also exposes quality (`low`, `medium`, `high`) and moderation (`auto`, `low`) controls.
119
65
 
120
- The server advertises its port at `~/.ima2/server.json`. Client commands auto-discover it. Override with `--server <url>` or `IMA2_SERVER=http://localhost:3333`.
66
+ ## Workflows
121
67
 
122
- ### Exit Codes
68
+ ### Classic Mode
123
69
 
124
- `0` OK · `2` bad arguments · `3` server unreachable · `4` `APIKEY_DISABLED` · `5` 4xx · `6` 5xx · `7` safety refusal · `8` timeout.
70
+ Use Classic when you want one strong result quickly.
125
71
 
126
- ---
72
+ 1. Write a prompt.
73
+ 2. Attach or paste references if needed.
74
+ 3. Pick model, quality, size, format, and moderation.
75
+ 4. Generate, copy, download, or continue from the result.
127
76
 
128
- ## API Endpoints
77
+ ### Node Mode
129
78
 
130
- ```text
131
- GET /api/health
132
- GET /api/providers
133
- GET /api/oauth/status
134
- GET /api/billing
135
- GET /api/inflight
136
- GET /api/inflight?includeTerminal=1
137
- POST /api/generate
138
- POST /api/edit
139
- GET /api/history
140
- GET /api/history?groupBy=session
141
- DELETE /api/history/:filename
142
- POST /api/history/:filename/restore
143
- GET /api/sessions
144
- POST /api/sessions
145
- GET /api/sessions/:id
146
- PATCH /api/sessions/:id
147
- DELETE /api/sessions/:id
148
- PUT /api/sessions/:id/graph
149
- GET /api/node/:nodeId
150
- POST /api/node/generate
151
- ```
79
+ Use Node mode when you want to explore branches.
152
80
 
153
- ### OAuth Generation Request
81
+ ![Node mode with connected generated cards and compact per-node metadata.](assets/screenshots/node-graph-branching.png)
154
82
 
155
- ```bash
156
- curl -X POST http://localhost:3333/api/generate \
157
- -H 'Content-Type: application/json' \
158
- -d '{
159
- "prompt": "a shiba in space",
160
- "quality": "medium",
161
- "size": "1024x1024",
162
- "moderation": "low",
163
- "provider": "oauth"
164
- }'
165
- ```
83
+ Each node keeps its own prompt and result. Root nodes can attach local references; child nodes use the parent image as their source. Completed jobs are matched back to nodes by request ID, so reloads and graph version conflicts can recover finished results.
166
84
 
167
- ### API-Key Configuration And Activation Notes
85
+ ### Settings And Style Sheets
168
86
 
169
- Current behavior:
87
+ The settings workspace keeps account, model, appearance, and language controls away from the generation sidebar.
170
88
 
171
- - `provider: "oauth"` is the supported generation path.
172
- - `provider: "api"` returns `403` / `APIKEY_DISABLED` in `routes/generate.js`, `routes/edit.js`, and `routes/nodes.js`.
173
- - `OPENAI_API_KEY` or `~/.ima2/config.json` can still be used for non-generation helpers such as billing probes and style-sheet extraction.
89
+ ![Settings workspace with account navigation and generation model controls.](assets/screenshots/settings-workspace.png)
174
90
 
175
- Configure an API key for those auxiliary paths:
91
+ Style sheets let you capture a reusable visual direction.
176
92
 
177
- ```bash
178
- export OPENAI_API_KEY="sk-..."
179
- ima2 serve
180
- ```
93
+ ![Style sheet editor with medium, composition, mood, subject, palette, and negative fields.](assets/screenshots/style-sheet-editor.png)
181
94
 
182
- or:
95
+ ## CLI Commands
183
96
 
184
- ```json
185
- {
186
- "provider": "api",
187
- "apiKey": "sk-..."
188
- }
189
- ```
97
+ ### Server
190
98
 
191
- saved at `~/.ima2/config.json`.
99
+ | Command | Description |
100
+ |---|---|
101
+ | `ima2 serve` | Start the local web server |
102
+ | `ima2 setup` | Reconfigure saved auth |
103
+ | `ima2 status` | Show config and OAuth status |
104
+ | `ima2 doctor` | Diagnose Node, package, config, and auth |
105
+ | `ima2 open` | Open the web UI |
106
+ | `ima2 reset` | Remove saved config |
192
107
 
193
- To intentionally reopen API-key image generation as a developer, audit and change the explicit `provider === "api"` guards in:
108
+ ### Client
194
109
 
195
- - `routes/generate.js`
196
- - `routes/edit.js`
197
- - `routes/nodes.js`
110
+ These require a running `ima2 serve`.
198
111
 
199
- Then wire the OpenAI SDK generation/edit implementation, update tests for both OAuth and API-key paths, and update this README. Do not simply remove the guards without adding the API implementation and billing/error tests.
112
+ | Command | Description |
113
+ |---|---|
114
+ | `ima2 gen <prompt>` | Generate from the CLI |
115
+ | `ima2 edit <file> --prompt <text>` | Edit an existing image |
116
+ | `ima2 ls` | List local history |
117
+ | `ima2 show <name>` | Reveal a generated asset |
118
+ | `ima2 ps` | List active jobs |
119
+ | `ima2 ping` | Health-check the running server |
200
120
 
201
- ---
121
+ The server advertises its port at `~/.ima2/server.json`. Override discovery with `--server <url>` or `IMA2_SERVER=http://localhost:3333`.
202
122
 
203
123
  ## Configuration
204
124
 
205
- Config priority is:
125
+ Config priority:
206
126
 
207
127
  ```text
208
128
  environment variables > ~/.ima2/config.json > built-in defaults
@@ -215,79 +135,56 @@ environment variables > ~/.ima2/config.json > built-in defaults
215
135
  | `IMA2_SERVER` | — | CLI target override |
216
136
  | `IMA2_CONFIG_DIR` | `~/.ima2` | Config and SQLite location |
217
137
  | `IMA2_GENERATED_DIR` | `~/.ima2/generated` | Generated image directory |
218
- | `IMA2_NO_OAUTH_PROXY` | — | Set `1` to disable auto-starting the OAuth proxy |
219
- | `IMA2_INFLIGHT_TERMINAL_TTL_MS` | `30000` | Retention for opt-in terminal in-flight debug jobs |
220
- | `VITE_IMA2_NODE_MODE` | enabled | Set `0` at UI build time to hide node mode |
221
- | `OPENAI_API_KEY` | — | API key for supported auxiliary paths |
222
-
223
- ---
224
-
225
- ## Architecture
138
+ | `IMA2_NO_OAUTH_PROXY` | — | Set `1` to disable the auto-started OAuth proxy |
139
+ | `IMA2_INFLIGHT_TERMINAL_TTL_MS` | `30000` | Recent terminal job retention for debug views |
140
+ | `OPENAI_API_KEY` | | API key for supported auxiliary paths, not image generation |
226
141
 
227
- ```text
228
- ima2 serve
229
- ├── Express server (:3333)
230
- │ ├── route modules in routes/
231
- │ ├── OAuth image calls via lib/oauthProxy.js
232
- │ ├── generated/ image + sidecar JSON storage
233
- │ ├── SQLite sessions via better-sqlite3
234
- │ └── ui/dist React app
235
- ├── openai-oauth proxy (:10531)
236
- └── ~/.ima2/server.json for CLI discovery
237
- ```
238
-
239
- The server uses ES modules, centralized config in `config.js`, and route helpers under `lib/`.
240
-
241
- ---
242
-
243
- ## Development
244
-
245
- ```bash
246
- git clone https://github.com/lidge-jun/ima2-gen.git
247
- cd ima2-gen
248
- npm install
249
- npm run dev
250
- npm test
251
- npm run build
252
- ```
142
+ ## API Reference
253
143
 
254
- `npm run dev` builds the UI and starts `server.js` with `--watch`. Node mode is now a normal product surface in both dev and packaged builds. Set `VITE_IMA2_NODE_MODE=0` only when you intentionally need a classic-only bundle.
144
+ The endpoint list moved to [docs/API.md](docs/API.md) so this README can stay focused on first-run use.
255
145
 
256
- Test coverage currently includes CLI behavior, config loading, history pagination/delete/restore, reference validation, OAuth parameter normalization, prompt fidelity, in-flight tracking, safe logging, and route health checks.
146
+ Useful references:
257
147
 
258
- ---
148
+ - [API Reference](docs/API.md)
149
+ - [Korean README](docs/README.ko.md)
150
+ - [Japanese README](docs/README.ja.md)
151
+ - [Chinese README](docs/README.zh-CN.md)
259
152
 
260
153
  ## Troubleshooting
261
154
 
262
155
  **`ima2 ping` says the server is unreachable**
263
- Start `ima2 serve`, then check `~/.ima2/server.json`. You can override discovery with `ima2 ping --server http://localhost:3333`.
156
+ Start `ima2 serve`, then check `~/.ima2/server.json`. You can also run `ima2 ping --server http://localhost:3333`.
264
157
 
265
158
  **OAuth login does not work**
266
159
  Run `npx @openai/codex login`, confirm `ima2 status`, then restart `ima2 serve`.
267
160
 
268
161
  **Images fail with `APIKEY_DISABLED`**
269
- You are trying to generate with `provider: "api"`. Use OAuth for generation in the current release.
162
+ Use OAuth for generation. API-key image generation is intentionally disabled in this build.
163
+
164
+ **A large reference image fails**
165
+ 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.
166
+
167
+ **Old gallery images are missing after updating**
168
+ Recent versions moved generated images from the installed package folder to `~/.ima2/generated`. Run `ima2 doctor` and see [Recover old images](docs/RECOVER_OLD_IMAGES.md).
270
169
 
271
- **An API key is configured but generation still uses OAuth**
272
- That is expected. API keys are currently recognized for auxiliary status/extraction paths, not for image generation.
170
+ **`gpt-5.5` fails but other models work**
171
+ Update Codex CLI first, then retry. If it still fails, your account or backend route may not expose the same image capability or quota for `gpt-5.5` yet; use `gpt-5.4` as the stable fallback.
273
172
 
274
- **Port is unexpectedly `3457`**
173
+ **The port is unexpectedly `3457`**
275
174
  Your shell may have inherited `PORT=3457` from another local tool. Run `unset PORT` or start with `IMA2_PORT=3333 ima2 serve`.
276
175
 
277
- ---
176
+ ## Development
278
177
 
279
- ## Recent Changelog Highlights
178
+ ```bash
179
+ git clone https://github.com/lidge-jun/ima2-gen.git
180
+ cd ima2-gen
181
+ npm install
182
+ npm run dev
183
+ npm test
184
+ npm run build
185
+ ```
280
186
 
281
- - Node mode enabled in packaged builds
282
- - Node-local references and branch duplication for node mode
283
- - `refsCount` metadata for node reference usage
284
- - npm package includes modular `routes/` server files
285
- - Settings workspace with account/theme controls
286
- - Prompt fidelity and revised prompt capture
287
- - OAuth quality handling for `low`, `medium`, `high`
288
- - Safer structured request logs and terminal in-flight debug snapshots
289
- - Session-title gallery grouping
290
- - Cross-platform CLI fixes for Windows process spawning
187
+ `npm run dev` builds the UI and starts `server.js` with `--watch`. Node mode is part of the packaged UI by default.
291
188
 
292
189
  ## License
293
190
 
Binary file
package/bin/ima2.js CHANGED
@@ -7,6 +7,7 @@ import { spawn, execSync } from "child_process";
7
7
  import { networkInterfaces, homedir } from "os";
8
8
  import { openUrl, resolveBin } from "./lib/platform.js";
9
9
  import { maybePromptGithubStar } from "./lib/star-prompt.js";
10
+ import { buildStorageDoctorLines } from "./lib/storage-doctor.js";
10
11
  import { detectCodexAuth } from "../lib/codexDetect.js";
11
12
  import { config as runtimeConfig } from "../config.js";
12
13
 
@@ -198,11 +199,11 @@ async function doctor() {
198
199
  // Node version
199
200
  const nodeVersion = process.version;
200
201
  const nodeMajor = parseInt(nodeVersion.slice(1).split(".")[0]);
201
- if (nodeMajor >= 18) {
202
- console.log(` ✓ Node.js ${nodeVersion} (>= 18)`);
202
+ if (nodeMajor >= 20) {
203
+ console.log(` ✓ Node.js ${nodeVersion} (>= 20)`);
203
204
  ok++;
204
205
  } else {
205
- console.log(` ✗ Node.js ${nodeVersion} (requires >= 18)`);
206
+ console.log(` ✗ Node.js ${nodeVersion} (requires >= 20)`);
206
207
  fail++;
207
208
  }
208
209
 
@@ -245,6 +246,13 @@ async function doctor() {
245
246
  const port = runtimeConfig.server.port;
246
247
  console.log(` ℹ Default port: ${port}`);
247
248
 
249
+ const storageLines = await buildStorageDoctorLines({
250
+ rootDir: ROOT,
251
+ config: runtimeConfig,
252
+ });
253
+ console.log("");
254
+ for (const line of storageLines) console.log(line);
255
+
248
256
  console.log(`\n ${ok} passed, ${fail} failed\n`);
249
257
  process.exit(fail > 0 ? 1 : 0);
250
258
  }
@@ -322,7 +330,7 @@ switch (command) {
322
330
  showStatus();
323
331
  break;
324
332
  case "doctor":
325
- doctor();
333
+ await doctor();
326
334
  break;
327
335
  case "open":
328
336
  openBrowser();
@@ -0,0 +1,38 @@
1
+ import { inspectGeneratedStorage } from "../../lib/storageMigration.js";
2
+
3
+ export async function buildStorageDoctorLines(ctx) {
4
+ const status = await inspectGeneratedStorage(ctx);
5
+ const lines = [
6
+ " Storage",
7
+ ` Current gallery: ${status.generatedDirLabel}`,
8
+ ` Source: ${status.overrides.generatedDir ? "IMA2_GENERATED_DIR" : "default"}`,
9
+ ` Images in current gallery: ${status.targetFileCount}`,
10
+ ` Legacy folders scanned: ${status.legacyCandidatesScanned}`,
11
+ ` Legacy folders found: ${status.legacySourcesFound}`,
12
+ ];
13
+
14
+ for (const source of status.legacySources.slice(0, 5)) {
15
+ lines.push(` - ${source.path} (${source.fileCount} files)`);
16
+ }
17
+ if (status.legacySources.length > 5) {
18
+ lines.push(` ...and ${status.legacySources.length - 5} more`);
19
+ }
20
+
21
+ lines.push("");
22
+ lines.push(" Next step");
23
+ if (status.state === "recoverable") {
24
+ lines.push(" Old images may still be recoverable. Restart ima2 or copy them manually.");
25
+ } else if (status.state === "not_found") {
26
+ lines.push(" No previous generated folder was found on this machine.");
27
+ lines.push(" If the old global install folder was replaced during update, backups may be required.");
28
+ } else if (status.state === "unknown") {
29
+ lines.push(" Storage status could not be fully checked.");
30
+ } else {
31
+ lines.push(" Current gallery storage looks available.");
32
+ }
33
+ lines.push(` See: ${status.recoveryDocsPath}`);
34
+ lines.push(" macOS/Linux: cp -n \"/old/ima2-gen/generated/\"* ~/.ima2/generated/");
35
+ lines.push(" Windows: Copy old generated files into %USERPROFILE%\\.ima2\\generated");
36
+
37
+ return lines;
38
+ }
package/config.js CHANGED
@@ -133,6 +133,11 @@ export const config = {
133
133
  maxPrefix: pickInt(env.IMA2_STYLE_SHEET_MAX_PREFIX, fileCfg.styleSheet?.maxPrefix, 4000),
134
134
  model: pickStr(env.IMA2_STYLE_MODEL, fileCfg.styleSheet?.model, "gpt-5.4-mini"),
135
135
  },
136
+ imageModels: {
137
+ default: pickStr(env.IMA2_IMAGE_MODEL_DEFAULT, fileCfg.imageModels?.default, "gpt-5.4-mini"),
138
+ valid: new Set(["gpt-5.5", "gpt-5.4", "gpt-5.4-mini"]),
139
+ unsupported: new Set(["gpt-5.3-codex-spark"]),
140
+ },
136
141
  log: {
137
142
  level: pickStr(env.IMA2_LOG_LEVEL, fileCfg.log?.level, "info"),
138
143
  pretty: env.NODE_ENV !== "production",