ima2-gen 1.1.8 → 1.1.9
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 +56 -27
- package/bin/commands/annotate.js +137 -0
- package/bin/commands/annotate.ts +118 -0
- package/bin/commands/cancel.js +37 -33
- package/bin/commands/cancel.ts +45 -0
- package/bin/commands/canvas-versions.js +91 -0
- package/bin/commands/canvas-versions.ts +80 -0
- package/bin/commands/cardnews.js +293 -0
- package/bin/commands/cardnews.ts +248 -0
- package/bin/commands/comfy.js +63 -0
- package/bin/commands/comfy.ts +54 -0
- package/bin/commands/config.js +270 -0
- package/bin/commands/config.ts +265 -0
- package/bin/commands/edit.js +97 -72
- package/bin/commands/edit.ts +116 -0
- package/bin/commands/gen.js +140 -118
- package/bin/commands/gen.ts +176 -0
- package/bin/commands/history.js +164 -0
- package/bin/commands/history.ts +145 -0
- package/bin/commands/ls.js +60 -42
- package/bin/commands/ls.ts +60 -0
- package/bin/commands/metadata.js +45 -0
- package/bin/commands/metadata.ts +36 -0
- package/bin/commands/multimode.js +159 -0
- package/bin/commands/multimode.ts +146 -0
- package/bin/commands/node.js +176 -0
- package/bin/commands/node.ts +157 -0
- package/bin/commands/observability.js +201 -0
- package/bin/commands/observability.ts +176 -0
- package/bin/commands/ping.js +26 -20
- package/bin/commands/ping.ts +29 -0
- package/bin/commands/prompt.js +506 -0
- package/bin/commands/prompt.ts +421 -0
- package/bin/commands/ps.js +78 -71
- package/bin/commands/ps.ts +78 -0
- package/bin/commands/session.js +308 -0
- package/bin/commands/session.ts +265 -0
- package/bin/commands/show.js +75 -40
- package/bin/commands/show.ts +69 -0
- package/bin/ima2.js +324 -310
- package/bin/ima2.ts +444 -0
- package/bin/lib/args.js +75 -66
- package/bin/lib/args.ts +73 -0
- package/bin/lib/browser-id.js +15 -0
- package/bin/lib/browser-id.ts +16 -0
- package/bin/lib/client.js +91 -83
- package/bin/lib/client.ts +109 -0
- package/bin/lib/error-hints.js +14 -17
- package/bin/lib/error-hints.ts +23 -0
- package/bin/lib/files.js +26 -28
- package/bin/lib/files.ts +39 -0
- package/bin/lib/output.js +44 -42
- package/bin/lib/output.ts +58 -0
- package/bin/lib/platform.js +60 -56
- package/bin/lib/platform.ts +97 -0
- package/bin/lib/sse.js +73 -0
- package/bin/lib/sse.ts +73 -0
- package/bin/lib/star-prompt.js +69 -76
- package/bin/lib/star-prompt.ts +97 -0
- package/bin/lib/storage-doctor.js +34 -35
- package/bin/lib/storage-doctor.ts +38 -0
- package/config.js +147 -243
- package/config.ts +331 -0
- package/docs/API.md +48 -8
- package/docs/CLI.md +190 -0
- package/docs/FAQ.ko.md +5 -5
- package/docs/FAQ.md +5 -5
- package/docs/README.ja.md +71 -25
- package/docs/README.ko.md +61 -24
- package/docs/README.zh-CN.md +73 -27
- package/lib/assetLifecycle.js +130 -130
- package/lib/assetLifecycle.ts +142 -0
- package/lib/canvasVersionStore.js +135 -153
- package/lib/canvasVersionStore.ts +181 -0
- package/lib/cardNewsGenerator.js +127 -142
- package/lib/cardNewsGenerator.ts +162 -0
- package/lib/cardNewsJobStore.js +78 -84
- package/lib/cardNewsJobStore.ts +107 -0
- package/lib/cardNewsManifestStore.js +88 -93
- package/lib/cardNewsManifestStore.ts +112 -0
- package/lib/cardNewsPlanner.js +157 -152
- package/lib/cardNewsPlanner.ts +180 -0
- package/lib/cardNewsPlannerClient.js +101 -98
- package/lib/cardNewsPlannerClient.ts +114 -0
- package/lib/cardNewsPlannerPrompt.js +56 -56
- package/lib/cardNewsPlannerPrompt.ts +60 -0
- package/lib/cardNewsPlannerSchema.js +231 -223
- package/lib/cardNewsPlannerSchema.ts +259 -0
- package/lib/cardNewsRoleTemplateStore.js +39 -41
- package/lib/cardNewsRoleTemplateStore.ts +47 -0
- package/lib/cardNewsTemplateStore.js +171 -175
- package/lib/cardNewsTemplateStore.ts +210 -0
- package/lib/codexDetect.js +44 -47
- package/lib/codexDetect.ts +69 -0
- package/lib/comfyBridge.js +164 -184
- package/lib/comfyBridge.ts +214 -0
- package/lib/db.js +41 -51
- package/lib/db.ts +166 -0
- package/lib/errorClassify.js +62 -78
- package/lib/errorClassify.ts +100 -0
- package/lib/generationErrors.js +140 -103
- package/lib/generationErrors.ts +125 -0
- package/lib/historyList.js +149 -147
- package/lib/historyList.ts +164 -0
- package/lib/imageMetadata.js +86 -89
- package/lib/imageMetadata.ts +111 -0
- package/lib/imageMetadataStore.js +46 -51
- package/lib/imageMetadataStore.ts +67 -0
- package/lib/imageModels.js +38 -45
- package/lib/imageModels.ts +52 -0
- package/lib/inflight.js +131 -150
- package/lib/inflight.ts +204 -0
- package/lib/localImportStore.js +87 -93
- package/lib/localImportStore.ts +111 -0
- package/lib/logger.js +105 -112
- package/lib/logger.ts +150 -0
- package/lib/nodeStore.js +65 -64
- package/lib/nodeStore.ts +81 -0
- package/lib/oauthLauncher.js +61 -59
- package/lib/oauthLauncher.ts +64 -0
- package/lib/oauthNormalize.js +15 -19
- package/lib/oauthNormalize.ts +30 -0
- package/lib/oauthProxy.js +834 -832
- package/lib/oauthProxy.ts +995 -0
- package/lib/openDirectory.js +41 -40
- package/lib/openDirectory.ts +45 -0
- package/lib/pngInfo.js +18 -20
- package/lib/pngInfo.ts +26 -0
- package/lib/promptImport/curatedSources.js +125 -129
- package/lib/promptImport/curatedSources.ts +139 -0
- package/lib/promptImport/discoveryRegistry.js +185 -203
- package/lib/promptImport/discoveryRegistry.ts +236 -0
- package/lib/promptImport/errors.js +10 -10
- package/lib/promptImport/errors.ts +18 -0
- package/lib/promptImport/githubDiscovery.js +209 -219
- package/lib/promptImport/githubDiscovery.ts +248 -0
- package/lib/promptImport/githubFolder.js +253 -259
- package/lib/promptImport/githubFolder.ts +308 -0
- package/lib/promptImport/githubSource.js +189 -200
- package/lib/promptImport/githubSource.ts +239 -0
- package/lib/promptImport/gptImageHints.js +49 -56
- package/lib/promptImport/gptImageHints.ts +68 -0
- package/lib/promptImport/parsePromptCandidates.js +108 -123
- package/lib/promptImport/parsePromptCandidates.ts +153 -0
- package/lib/promptImport/promptIndex.js +190 -208
- package/lib/promptImport/promptIndex.ts +248 -0
- package/lib/promptImport/rankPromptCandidates.js +46 -43
- package/lib/promptImport/rankPromptCandidates.ts +49 -0
- package/lib/providerOptions.js +31 -0
- package/lib/providerOptions.ts +41 -0
- package/lib/referenceImageCompress.js +51 -62
- package/lib/referenceImageCompress.ts +75 -0
- package/lib/refs.js +93 -81
- package/lib/refs.ts +117 -0
- package/lib/requestLogger.js +32 -38
- package/lib/requestLogger.ts +48 -0
- package/lib/responsesImageAdapter.js +351 -0
- package/lib/responsesImageAdapter.ts +352 -0
- package/lib/runtimePorts.js +71 -73
- package/lib/runtimePorts.ts +93 -0
- package/lib/sessionStore.js +179 -230
- package/lib/sessionStore.ts +272 -0
- package/lib/storageMigration.js +247 -245
- package/lib/storageMigration.ts +284 -0
- package/lib/styleSheet.js +86 -90
- package/lib/styleSheet.ts +128 -0
- package/lib/systemTrash.js +18 -0
- package/lib/systemTrash.ts +20 -0
- package/package.json +26 -10
- package/routes/annotations.js +76 -79
- package/routes/annotations.ts +95 -0
- package/routes/canvasVersions.js +50 -54
- package/routes/canvasVersions.ts +64 -0
- package/routes/cardNews.js +158 -171
- package/routes/cardNews.ts +183 -0
- package/routes/comfy.js +23 -31
- package/routes/comfy.ts +39 -0
- package/routes/edit.js +183 -214
- package/routes/edit.ts +230 -0
- package/routes/generate.js +269 -291
- package/routes/generate.ts +309 -0
- package/routes/health.js +102 -107
- package/routes/health.ts +114 -0
- package/routes/history.js +136 -144
- package/routes/history.ts +153 -0
- package/routes/imageImport.js +27 -27
- package/routes/imageImport.ts +33 -0
- package/routes/index.js +17 -17
- package/routes/index.ts +35 -0
- package/routes/metadata.js +60 -64
- package/routes/metadata.ts +71 -0
- package/routes/multimode.js +228 -263
- package/routes/multimode.ts +280 -0
- package/routes/nodes.js +378 -424
- package/routes/nodes.ts +455 -0
- package/routes/promptImport.js +284 -324
- package/routes/promptImport.ts +354 -0
- package/routes/prompts.js +333 -360
- package/routes/prompts.ts +379 -0
- package/routes/sessions.js +277 -285
- package/routes/sessions.ts +292 -0
- package/routes/storage.js +29 -31
- package/routes/storage.ts +39 -0
- package/server.js +189 -196
- package/server.ts +235 -0
- package/ui/dist/.vite/manifest.json +101 -0
- package/ui/dist/assets/CardNewsWorkspace-BJOCey7Z.js +2 -0
- package/ui/dist/assets/NodeCanvas-BZV40eAE.css +1 -0
- package/ui/dist/assets/NodeCanvas-C3dzYNsk.js +7 -0
- package/ui/dist/assets/PromptImportDialog-Dqu1VpUh.js +2 -0
- package/ui/dist/assets/PromptImportDiscoverySection-Dg8T9X0L.js +1 -0
- package/ui/dist/assets/PromptImportFolderSection-DBaqsFO4.js +1 -0
- package/ui/dist/assets/PromptLibraryPanel-p5QqR97M.js +2 -0
- package/ui/dist/assets/SettingsWorkspace-B5bSAZ6u.js +1 -0
- package/ui/dist/assets/index-C9cXwiWE.js +25 -0
- package/ui/dist/assets/index-CGMIkZXn.css +1 -0
- package/ui/dist/assets/index-Cvld7dUZ.js +1 -0
- package/ui/dist/index.html +2 -2
- package/assets/phase-a-bg-cleanup-test.png +0 -0
- package/assets/screenshot.png +0 -0
- package/assets/screenshots/classic-generate-light.png +0 -0
- package/assets/screenshots/node-graph-branching.png +0 -0
- package/assets/screenshots/settings-oauth-generation.png +0 -0
- package/assets/screenshots/settings-workspace.png +0 -0
- package/assets/screenshots/style-sheet-editor.png +0 -0
- package/integrations/comfyui/ima2_gen_bridge/__pycache__/__init__.cpython-313.pyc +0 -0
- package/integrations/comfyui/ima2_gen_bridge/__pycache__/nodes.cpython-313.pyc +0 -0
- package/ui/dist/assets/index-BDffwmLs.css +0 -1
- package/ui/dist/assets/index-D0fdHLkJ.js +0 -31
- package/ui/dist/assets/index-D0fdHLkJ.js.map +0 -1
package/config.ts
ADDED
|
@@ -0,0 +1,331 @@
|
|
|
1
|
+
// config.js — centralized runtime configuration (0.09.12).
|
|
2
|
+
//
|
|
3
|
+
// Single source of truth for ports, limits, paths, and tunables. All server,
|
|
4
|
+
// lib, and script code should import `config` (or named legacy constants) from
|
|
5
|
+
// here rather than reading `process.env` directly.
|
|
6
|
+
//
|
|
7
|
+
// Priority: env var > ${IMA2_CONFIG_DIR}/config.json > built-in default.
|
|
8
|
+
// `config.json` is loaded once at module import. Mutating the file at runtime
|
|
9
|
+
// requires a server restart (same as env vars).
|
|
10
|
+
//
|
|
11
|
+
// Keep this module dependency-free aside from node:* built-ins to avoid
|
|
12
|
+
// circular imports with lib/*.
|
|
13
|
+
|
|
14
|
+
import { homedir } from "node:os";
|
|
15
|
+
import { join, dirname } from "node:path";
|
|
16
|
+
import { fileURLToPath } from "node:url";
|
|
17
|
+
import { readFileSync, existsSync } from "node:fs";
|
|
18
|
+
|
|
19
|
+
const env = process.env;
|
|
20
|
+
const packageRoot = dirname(fileURLToPath(import.meta.url));
|
|
21
|
+
const configDir = env.IMA2_CONFIG_DIR || join(homedir(), ".ima2");
|
|
22
|
+
|
|
23
|
+
// ── Optional config.json layer ─────────────────────────────────────────
|
|
24
|
+
// Users can drop `${configDir}/config.json` to override defaults without
|
|
25
|
+
// setting env vars. Shape: same as the `config` object below (partial).
|
|
26
|
+
function loadConfigJson() {
|
|
27
|
+
const candidates = [
|
|
28
|
+
join(configDir, "config.json"),
|
|
29
|
+
join(packageRoot, ".ima2", "config.json"),
|
|
30
|
+
];
|
|
31
|
+
for (const p of candidates) {
|
|
32
|
+
if (!existsSync(p)) continue;
|
|
33
|
+
try {
|
|
34
|
+
const raw = readFileSync(p, "utf-8");
|
|
35
|
+
return JSON.parse(raw);
|
|
36
|
+
} catch {
|
|
37
|
+
// ignore malformed config.json; env+defaults still apply
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
return {};
|
|
41
|
+
}
|
|
42
|
+
const fileCfg = loadConfigJson();
|
|
43
|
+
|
|
44
|
+
function firstDefined(...vals) {
|
|
45
|
+
return vals.find((v) => v !== undefined && v !== "");
|
|
46
|
+
}
|
|
47
|
+
function pickInt(envVal, fileVal, fallback) {
|
|
48
|
+
const candidate = firstDefined(envVal, fileVal);
|
|
49
|
+
if (candidate === undefined) return fallback;
|
|
50
|
+
const n = Number(candidate);
|
|
51
|
+
return Number.isFinite(n) ? n : fallback;
|
|
52
|
+
}
|
|
53
|
+
function pickPositiveInt(envVal, fileVal, fallback) {
|
|
54
|
+
const n = pickInt(envVal, fileVal, fallback);
|
|
55
|
+
return Number.isFinite(n) && n > 0 ? n : fallback;
|
|
56
|
+
}
|
|
57
|
+
function pickStr(envVal, fileVal, fallback) {
|
|
58
|
+
return firstDefined(envVal, fileVal) ?? fallback;
|
|
59
|
+
}
|
|
60
|
+
function pickBool(envVal, fileVal, fallback) {
|
|
61
|
+
const v = firstDefined(envVal, fileVal);
|
|
62
|
+
if (v === undefined) return fallback;
|
|
63
|
+
if (typeof v === "boolean") return v;
|
|
64
|
+
const s = String(v).toLowerCase();
|
|
65
|
+
return s === "1" || s === "true" || s === "yes";
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
export function defaultLogLevelForEnv(runtimeEnv = env) {
|
|
69
|
+
return runtimeEnv.IMA2_DEV === "1" ? "debug" : "info";
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
export const config = {
|
|
73
|
+
server: {
|
|
74
|
+
// Accept both IMA2_PORT and legacy PORT.
|
|
75
|
+
port: pickInt(firstDefined(env.IMA2_PORT, env.PORT), fileCfg.server?.port, 3333),
|
|
76
|
+
host: pickStr(env.IMA2_HOST, fileCfg.server?.host, "127.0.0.1"),
|
|
77
|
+
bodyLimit: pickStr(env.IMA2_BODY_LIMIT, fileCfg.server?.bodyLimit, "50mb"),
|
|
78
|
+
},
|
|
79
|
+
limits: {
|
|
80
|
+
maxRefB64Bytes: pickInt(env.IMA2_MAX_REF_B64_BYTES, fileCfg.limits?.maxRefB64Bytes, 7 * 1024 * 1024),
|
|
81
|
+
maxMetadataReadB64Bytes: pickInt(
|
|
82
|
+
env.IMA2_MAX_METADATA_READ_B64_BYTES,
|
|
83
|
+
fileCfg.limits?.maxMetadataReadB64Bytes,
|
|
84
|
+
12 * 1024 * 1024,
|
|
85
|
+
),
|
|
86
|
+
maxRefCount: pickInt(env.IMA2_MAX_REF_COUNT, fileCfg.limits?.maxRefCount, 5),
|
|
87
|
+
maxParallel: pickInt(env.IMA2_MAX_PARALLEL, fileCfg.limits?.maxParallel, 8),
|
|
88
|
+
graphMaxNodes: pickInt(env.IMA2_GRAPH_MAX_NODES, fileCfg.limits?.graphMaxNodes, 500),
|
|
89
|
+
graphMaxEdges: pickInt(env.IMA2_GRAPH_MAX_EDGES, fileCfg.limits?.graphMaxEdges, 1000),
|
|
90
|
+
promptImportMaxFileBytes: pickInt(
|
|
91
|
+
env.IMA2_PROMPT_IMPORT_MAX_FILE_BYTES,
|
|
92
|
+
fileCfg.limits?.promptImportMaxFileBytes,
|
|
93
|
+
512 * 1024,
|
|
94
|
+
),
|
|
95
|
+
promptImportMaxCandidatesPerFile: pickInt(
|
|
96
|
+
env.IMA2_PROMPT_IMPORT_MAX_CANDIDATES_PER_FILE,
|
|
97
|
+
fileCfg.limits?.promptImportMaxCandidatesPerFile,
|
|
98
|
+
100,
|
|
99
|
+
),
|
|
100
|
+
promptImportMaxCandidatesPerImport: pickInt(
|
|
101
|
+
env.IMA2_PROMPT_IMPORT_MAX_CANDIDATES_PER_IMPORT,
|
|
102
|
+
fileCfg.limits?.promptImportMaxCandidatesPerImport,
|
|
103
|
+
100,
|
|
104
|
+
),
|
|
105
|
+
promptImportFetchTimeoutMs: pickInt(
|
|
106
|
+
env.IMA2_PROMPT_IMPORT_FETCH_TIMEOUT_MS,
|
|
107
|
+
fileCfg.limits?.promptImportFetchTimeoutMs,
|
|
108
|
+
8000,
|
|
109
|
+
),
|
|
110
|
+
promptImportMaxCandidateChars: pickInt(
|
|
111
|
+
env.IMA2_PROMPT_IMPORT_MAX_CANDIDATE_CHARS,
|
|
112
|
+
fileCfg.limits?.promptImportMaxCandidateChars,
|
|
113
|
+
12000,
|
|
114
|
+
),
|
|
115
|
+
promptImportMinCandidateChars: pickInt(
|
|
116
|
+
env.IMA2_PROMPT_IMPORT_MIN_CANDIDATE_CHARS,
|
|
117
|
+
fileCfg.limits?.promptImportMinCandidateChars,
|
|
118
|
+
40,
|
|
119
|
+
),
|
|
120
|
+
promptImportMaxSourceCharsScanned: pickInt(
|
|
121
|
+
env.IMA2_PROMPT_IMPORT_MAX_SOURCE_CHARS_SCANNED,
|
|
122
|
+
fileCfg.limits?.promptImportMaxSourceCharsScanned,
|
|
123
|
+
512 * 1024,
|
|
124
|
+
),
|
|
125
|
+
promptImportMaxRepoIndexFiles: pickInt(
|
|
126
|
+
env.IMA2_PROMPT_IMPORT_MAX_REPO_INDEX_FILES,
|
|
127
|
+
fileCfg.limits?.promptImportMaxRepoIndexFiles,
|
|
128
|
+
500,
|
|
129
|
+
),
|
|
130
|
+
promptImportCuratedSearchLimit: pickInt(
|
|
131
|
+
env.IMA2_PROMPT_IMPORT_CURATED_SEARCH_LIMIT,
|
|
132
|
+
fileCfg.limits?.promptImportCuratedSearchLimit,
|
|
133
|
+
50,
|
|
134
|
+
),
|
|
135
|
+
promptImportIndexCacheTtlMs: pickInt(
|
|
136
|
+
env.IMA2_PROMPT_IMPORT_INDEX_CACHE_TTL_MS,
|
|
137
|
+
fileCfg.limits?.promptImportIndexCacheTtlMs,
|
|
138
|
+
24 * 60 * 60 * 1000,
|
|
139
|
+
),
|
|
140
|
+
promptImportMaxFolderFiles: pickInt(
|
|
141
|
+
env.IMA2_PROMPT_IMPORT_MAX_FOLDER_FILES,
|
|
142
|
+
fileCfg.limits?.promptImportMaxFolderFiles,
|
|
143
|
+
100,
|
|
144
|
+
),
|
|
145
|
+
promptImportMaxFolderPreviewFiles: pickInt(
|
|
146
|
+
env.IMA2_PROMPT_IMPORT_MAX_FOLDER_PREVIEW_FILES,
|
|
147
|
+
fileCfg.limits?.promptImportMaxFolderPreviewFiles,
|
|
148
|
+
20,
|
|
149
|
+
),
|
|
150
|
+
promptImportDiscoverySearchLimit: pickInt(
|
|
151
|
+
env.IMA2_PROMPT_IMPORT_DISCOVERY_SEARCH_LIMIT,
|
|
152
|
+
fileCfg.limits?.promptImportDiscoverySearchLimit,
|
|
153
|
+
20,
|
|
154
|
+
),
|
|
155
|
+
promptImportDiscoveryCacheTtlMs: pickInt(
|
|
156
|
+
env.IMA2_PROMPT_IMPORT_DISCOVERY_CACHE_TTL_MS,
|
|
157
|
+
fileCfg.limits?.promptImportDiscoveryCacheTtlMs,
|
|
158
|
+
60 * 60 * 1000,
|
|
159
|
+
),
|
|
160
|
+
promptImportDiscoveryMaxQueries: pickInt(
|
|
161
|
+
env.IMA2_PROMPT_IMPORT_DISCOVERY_MAX_QUERIES,
|
|
162
|
+
fileCfg.limits?.promptImportDiscoveryMaxQueries,
|
|
163
|
+
5,
|
|
164
|
+
),
|
|
165
|
+
},
|
|
166
|
+
history: {
|
|
167
|
+
defaultPageSize: pickInt(
|
|
168
|
+
env.IMA2_HISTORY_PAGE_SIZE,
|
|
169
|
+
fileCfg.history?.defaultPageSize ?? fileCfg.limits?.historyDefaultPageSize,
|
|
170
|
+
50,
|
|
171
|
+
),
|
|
172
|
+
maxPageCap: pickInt(
|
|
173
|
+
env.IMA2_HISTORY_MAX_PAGE,
|
|
174
|
+
fileCfg.history?.maxPageCap ?? fileCfg.limits?.historyMaxPageCap,
|
|
175
|
+
500,
|
|
176
|
+
),
|
|
177
|
+
},
|
|
178
|
+
oauth: {
|
|
179
|
+
// Accept both IMA2_OAUTH_PROXY_PORT and legacy OAUTH_PORT.
|
|
180
|
+
proxyPort: pickInt(firstDefined(env.IMA2_OAUTH_PROXY_PORT, env.OAUTH_PORT), fileCfg.oauth?.proxyPort, 10531),
|
|
181
|
+
// IMA2_NO_OAUTH_PROXY=1 disables auto-start; default is auto-start enabled.
|
|
182
|
+
autoStart: !pickBool(env.IMA2_NO_OAUTH_PROXY, fileCfg.oauth?.disableAutoStart, false),
|
|
183
|
+
statusTimeoutMs: pickInt(env.IMA2_OAUTH_STATUS_TIMEOUT_MS, fileCfg.oauth?.statusTimeoutMs, 3000),
|
|
184
|
+
generationTimeoutMs: pickInt(
|
|
185
|
+
env.IMA2_OAUTH_GENERATION_TIMEOUT_MS,
|
|
186
|
+
fileCfg.oauth?.generationTimeoutMs,
|
|
187
|
+
400 * 1000,
|
|
188
|
+
),
|
|
189
|
+
restartDelayMs: pickInt(env.IMA2_OAUTH_RESTART_DELAY_MS, fileCfg.oauth?.restartDelayMs, 5000),
|
|
190
|
+
// Provider-backed masked edit is off until upstream STEP-0 verification is recorded.
|
|
191
|
+
maskedEditEnabled: pickBool(
|
|
192
|
+
env.IMA2_OAUTH_MASKED_EDIT_ENABLED,
|
|
193
|
+
fileCfg.oauth?.maskedEditEnabled,
|
|
194
|
+
false,
|
|
195
|
+
),
|
|
196
|
+
researchSuffix: pickStr(
|
|
197
|
+
env.IMA2_RESEARCH_SUFFIX,
|
|
198
|
+
fileCfg.oauth?.researchSuffix,
|
|
199
|
+
"\n\nIf factual visual accuracy is required and the user's prompt or attached visual context is not already sufficient, use at least one concise web_search call for references before generating. If the user's prompt is already visually sufficient, do not search, rewrite, translate, summarize, or add clarifiers; pass the user's prompt through as the image_generation prompt argument.",
|
|
200
|
+
),
|
|
201
|
+
validModeration: new Set(
|
|
202
|
+
Array.isArray(fileCfg.oauth?.validModeration) && fileCfg.oauth.validModeration.length
|
|
203
|
+
? fileCfg.oauth.validModeration
|
|
204
|
+
: ["auto", "low"],
|
|
205
|
+
),
|
|
206
|
+
},
|
|
207
|
+
github: {
|
|
208
|
+
token: pickStr(env.IMA2_GITHUB_TOKEN, fileCfg.github?.token, ""),
|
|
209
|
+
},
|
|
210
|
+
storage: {
|
|
211
|
+
configDir,
|
|
212
|
+
packageRoot,
|
|
213
|
+
generatedDir: pickStr(env.IMA2_GENERATED_DIR, fileCfg.storage?.generatedDir, join(configDir, "generated")),
|
|
214
|
+
trashDir: pickStr(env.IMA2_TRASH_DIR, fileCfg.storage?.trashDir, join(configDir, "generated", ".trash")),
|
|
215
|
+
generatedDirName: pickStr(env.IMA2_GENERATED_DIRNAME, fileCfg.storage?.generatedDirName, "generated"),
|
|
216
|
+
trashDirName: pickStr(env.IMA2_TRASH_DIRNAME, fileCfg.storage?.trashDirName, ".trash"),
|
|
217
|
+
dbPath: pickStr(env.IMA2_DB_PATH, fileCfg.storage?.dbPath, join(configDir, "sessions.db")),
|
|
218
|
+
promptImportIndexCacheFile: pickStr(
|
|
219
|
+
env.IMA2_PROMPT_IMPORT_INDEX_CACHE_FILE,
|
|
220
|
+
fileCfg.storage?.promptImportIndexCacheFile,
|
|
221
|
+
join(configDir, "prompt-import-index.json"),
|
|
222
|
+
),
|
|
223
|
+
promptImportDiscoveryRegistryFile: pickStr(
|
|
224
|
+
env.IMA2_PROMPT_IMPORT_DISCOVERY_REGISTRY_FILE,
|
|
225
|
+
fileCfg.storage?.promptImportDiscoveryRegistryFile,
|
|
226
|
+
join(configDir, "prompt-import-discovery.json"),
|
|
227
|
+
),
|
|
228
|
+
configFile: join(configDir, "config.json"),
|
|
229
|
+
advertiseFile: pickStr(env.IMA2_ADVERTISE_FILE, fileCfg.storage?.advertiseFile, join(configDir, "server.json")),
|
|
230
|
+
staticMaxAge: pickStr(env.IMA2_STATIC_MAX_AGE, fileCfg.storage?.staticMaxAge, "1y"),
|
|
231
|
+
},
|
|
232
|
+
ids: {
|
|
233
|
+
generatedHexBytes: pickInt(env.IMA2_GENERATED_HEX_BYTES, fileCfg.ids?.generatedHexBytes, 4),
|
|
234
|
+
nodeHexBytes: pickInt(env.IMA2_NODE_HEX_BYTES, fileCfg.ids?.nodeHexBytes, 5),
|
|
235
|
+
},
|
|
236
|
+
inflight: {
|
|
237
|
+
ttlMs: pickInt(env.IMA2_INFLIGHT_TTL_MS, fileCfg.inflight?.ttlMs, 10 * 60 * 1000),
|
|
238
|
+
reapMs: pickInt(env.IMA2_INFLIGHT_REAP_MS, fileCfg.inflight?.reapMs, 60 * 1000),
|
|
239
|
+
terminalTtlMs: pickInt(env.IMA2_INFLIGHT_TERMINAL_TTL_MS, fileCfg.inflight?.terminalTtlMs, 5 * 60 * 1000),
|
|
240
|
+
},
|
|
241
|
+
trash: {
|
|
242
|
+
ttlMs: pickInt(env.IMA2_TRASH_TTL_MS, fileCfg.trash?.ttlMs, 10_000),
|
|
243
|
+
},
|
|
244
|
+
styleSheet: {
|
|
245
|
+
maxPrefix: pickInt(env.IMA2_STYLE_SHEET_MAX_PREFIX, fileCfg.styleSheet?.maxPrefix, 4000),
|
|
246
|
+
model: pickStr(env.IMA2_STYLE_MODEL, fileCfg.styleSheet?.model, "gpt-5.4-mini"),
|
|
247
|
+
},
|
|
248
|
+
imageModels: {
|
|
249
|
+
default: pickStr(env.IMA2_IMAGE_MODEL_DEFAULT, fileCfg.imageModels?.default, "gpt-5.4-mini"),
|
|
250
|
+
valid: new Set(["gpt-5.5", "gpt-5.4", "gpt-5.4-mini"]),
|
|
251
|
+
unsupported: new Set(["gpt-5.3-codex-spark"]),
|
|
252
|
+
reasoningEffort: pickStr(
|
|
253
|
+
env.IMA2_REASONING_EFFORT,
|
|
254
|
+
fileCfg.imageModels?.reasoningEffort,
|
|
255
|
+
"medium",
|
|
256
|
+
),
|
|
257
|
+
validReasoningEfforts: new Set(["none", "low", "medium", "high", "xhigh"]),
|
|
258
|
+
},
|
|
259
|
+
apiProvider: {
|
|
260
|
+
defaultImageModel: pickStr(
|
|
261
|
+
env.IMA2_API_IMAGE_MODEL_DEFAULT,
|
|
262
|
+
fileCfg.apiProvider?.defaultImageModel,
|
|
263
|
+
"gpt-5.4-mini",
|
|
264
|
+
),
|
|
265
|
+
defaultReasoningEffort: pickStr(
|
|
266
|
+
env.IMA2_API_REASONING_EFFORT,
|
|
267
|
+
fileCfg.apiProvider?.defaultReasoningEffort,
|
|
268
|
+
"low",
|
|
269
|
+
),
|
|
270
|
+
defaultSize: pickStr(env.IMA2_API_IMAGE_SIZE, fileCfg.apiProvider?.defaultSize, "1024x1024"),
|
|
271
|
+
allowWebSearch: pickBool(env.IMA2_API_ALLOW_WEB_SEARCH, fileCfg.apiProvider?.allowWebSearch, true),
|
|
272
|
+
},
|
|
273
|
+
log: {
|
|
274
|
+
level: pickStr(env.IMA2_LOG_LEVEL, fileCfg.log?.level, defaultLogLevelForEnv(env)),
|
|
275
|
+
pretty: env.NODE_ENV !== "production",
|
|
276
|
+
},
|
|
277
|
+
features: {
|
|
278
|
+
cardNews: pickBool(env.IMA2_CARD_NEWS, fileCfg.features?.cardNews, env.IMA2_DEV === "1"),
|
|
279
|
+
},
|
|
280
|
+
cardNewsPlanner: {
|
|
281
|
+
enabled: pickBool(env.IMA2_CARD_NEWS_PLANNER, fileCfg.cardNewsPlanner?.enabled, true),
|
|
282
|
+
model: pickStr(env.IMA2_CARD_NEWS_PLANNER_MODEL, fileCfg.cardNewsPlanner?.model, "gpt-5.4-mini"),
|
|
283
|
+
timeoutMs: pickInt(env.IMA2_CARD_NEWS_PLANNER_TIMEOUT_MS, fileCfg.cardNewsPlanner?.timeoutMs, 60_000),
|
|
284
|
+
deterministicFallback: pickBool(
|
|
285
|
+
env.IMA2_CARD_NEWS_PLANNER_FALLBACK,
|
|
286
|
+
fileCfg.cardNewsPlanner?.deterministicFallback,
|
|
287
|
+
false,
|
|
288
|
+
),
|
|
289
|
+
},
|
|
290
|
+
comfy: {
|
|
291
|
+
defaultUrl: pickStr(env.IMA2_COMFY_URL, fileCfg.comfy?.defaultUrl, "http://127.0.0.1:8188"),
|
|
292
|
+
uploadTimeoutMs: pickPositiveInt(
|
|
293
|
+
env.IMA2_COMFY_UPLOAD_TIMEOUT_MS,
|
|
294
|
+
fileCfg.comfy?.uploadTimeoutMs,
|
|
295
|
+
30_000,
|
|
296
|
+
),
|
|
297
|
+
maxUploadBytes: pickPositiveInt(
|
|
298
|
+
env.IMA2_COMFY_MAX_UPLOAD_BYTES,
|
|
299
|
+
fileCfg.comfy?.maxUploadBytes,
|
|
300
|
+
50 * 1024 * 1024,
|
|
301
|
+
),
|
|
302
|
+
},
|
|
303
|
+
dev: {
|
|
304
|
+
viteDevMode: pickBool(env.VITE_IMA2_DEV, fileCfg.dev?.viteDevMode, false),
|
|
305
|
+
},
|
|
306
|
+
};
|
|
307
|
+
|
|
308
|
+
export default config;
|
|
309
|
+
|
|
310
|
+
// ── Backward-compatible flat re-exports (used by lib/inflight.js & earlier
|
|
311
|
+
// call sites). Prefer `import { config } from "./config.js"` going forward.
|
|
312
|
+
export const PORT = config.server.port;
|
|
313
|
+
export const OAUTH_PORT = config.oauth.proxyPort;
|
|
314
|
+
export const OAUTH_URL = `http://127.0.0.1:${config.oauth.proxyPort}`;
|
|
315
|
+
export const CONFIG_DIR = config.storage.configDir;
|
|
316
|
+
export const CONFIG_FILE = config.storage.configFile;
|
|
317
|
+
export const ADVERTISE_FILE = config.storage.advertiseFile;
|
|
318
|
+
export const DB_FILE = config.storage.dbPath;
|
|
319
|
+
export const GENERATED_DIR = config.storage.generatedDir;
|
|
320
|
+
export const BODY_LIMIT = config.server.bodyLimit;
|
|
321
|
+
export const MAX_REF_B64_BYTES = config.limits.maxRefB64Bytes;
|
|
322
|
+
export const MAX_REFS = config.limits.maxRefCount;
|
|
323
|
+
export const MAX_N = config.limits.maxParallel;
|
|
324
|
+
export const INFLIGHT_TTL_MS = config.inflight.ttlMs;
|
|
325
|
+
export const INFLIGHT_REAP_MS = config.inflight.reapMs;
|
|
326
|
+
export const INFLIGHT_TERMINAL_TTL_MS = config.inflight.terminalTtlMs;
|
|
327
|
+
export const STYLE_SHEET_MAX_PREFIX = config.styleSheet.maxPrefix;
|
|
328
|
+
export const LOG_LEVEL = config.log.level;
|
|
329
|
+
export const NO_OAUTH_PROXY = !config.oauth.autoStart;
|
|
330
|
+
export const DEV_MODE = config.dev.viteDevMode;
|
|
331
|
+
export const CARD_NEWS_ENABLED = config.features.cardNews;
|
package/docs/API.md
CHANGED
|
@@ -10,18 +10,20 @@ http://localhost:3333
|
|
|
10
10
|
|
|
11
11
|
## Provider Policy
|
|
12
12
|
|
|
13
|
-
Image generation
|
|
13
|
+
Image generation supports both OAuth and API-key providers.
|
|
14
14
|
|
|
15
|
-
- `provider: "oauth"`
|
|
16
|
-
- `provider: "api"`
|
|
17
|
-
- API
|
|
15
|
+
- `provider: "oauth"` uses the local Codex OAuth proxy.
|
|
16
|
+
- `provider: "api"` uses the OpenAI Responses API with the hosted `image_generation` tool.
|
|
17
|
+
- API-key generation covers classic generate, edit, mask-guided edit, multimode, and node generation.
|
|
18
|
+
- If `provider: "api"` is requested without an API key, routes fail before upstream with `401` and `API_KEY_REQUIRED`.
|
|
19
|
+
- Mask edits are mask/selection guided edits, not pixel-perfect inpaint guarantees.
|
|
18
20
|
|
|
19
21
|
## Health And Status
|
|
20
22
|
|
|
21
23
|
| Method | Path | Notes |
|
|
22
24
|
|---|---|---|
|
|
23
25
|
| `GET` | `/api/health` | Server health, version, paths, provider policy |
|
|
24
|
-
| `GET` | `/api/providers` | Provider availability
|
|
26
|
+
| `GET` | `/api/providers` | Provider availability and runtime ports |
|
|
25
27
|
| `GET` | `/api/oauth/status` | OAuth proxy status and visible models |
|
|
26
28
|
| `GET` | `/api/billing` | Billing/status probe, including API key source when configured |
|
|
27
29
|
|
|
@@ -106,7 +108,7 @@ Recommended model: `gpt-5.4`. Current app default: `gpt-5.4-mini`. `gpt-5.5` is
|
|
|
106
108
|
|
|
107
109
|
Image edit / image-to-image generation.
|
|
108
110
|
|
|
109
|
-
The request includes a prompt and image payload.
|
|
111
|
+
The request includes a prompt and image payload. `provider: "api"` sends the prompt and image through the shared Responses image adapter. Optional masks are forwarded as mask guidance, not a pixel-perfect edit guarantee.
|
|
110
112
|
|
|
111
113
|
### `POST /api/node/generate`
|
|
112
114
|
|
|
@@ -198,13 +200,14 @@ X-Ima2-Tab-Id
|
|
|
198
200
|
| `PATCH` | `/api/sessions/:id/style-sheet/enabled` | Toggle style sheet usage |
|
|
199
201
|
| `POST` | `/api/sessions/:id/style-sheet/extract` | Extract style fields from prompt/reference |
|
|
200
202
|
|
|
201
|
-
Style-sheet extraction can require an API key/openai client.
|
|
203
|
+
Style-sheet extraction can require an API key/openai client. Image generation also supports `provider: "api"` through the shared Responses API image adapter when an API key is configured.
|
|
202
204
|
|
|
203
205
|
## Common Error Codes
|
|
204
206
|
|
|
205
207
|
| Code | Meaning |
|
|
206
208
|
|---|---|
|
|
207
|
-
| `
|
|
209
|
+
| `API_KEY_REQUIRED` | `provider: "api"` was requested without a configured API key |
|
|
210
|
+
| `APIKEY_DISABLED` | Legacy/deprecated hard-block code from older builds |
|
|
208
211
|
| `INVALID_IMAGE_MODEL` | Model name is unknown or unsupported |
|
|
209
212
|
| `IMAGE_MODEL_UNSUPPORTED` | Model exists but cannot use image generation |
|
|
210
213
|
| `INVALID_REQUEST` | Upstream request parameters are invalid; raw provider details may be included as `upstreamCode`, `upstreamType`, and `upstreamParam` |
|
|
@@ -221,6 +224,43 @@ Style-sheet extraction can require an API key/openai client. This does not reope
|
|
|
221
224
|
| `GRAPH_TOO_LARGE` | Graph exceeds node/edge limits |
|
|
222
225
|
| `NODE_NOT_FOUND` | Node metadata was not found |
|
|
223
226
|
|
|
227
|
+
## Endpoint → CLI Mapping
|
|
228
|
+
|
|
229
|
+
As of 0.09.x, every server route under `/api/*` has a CLI wrapper. Use this table to find the command that calls a given endpoint. (See README.md "Client" section for full flag lists.)
|
|
230
|
+
|
|
231
|
+
| Endpoint | CLI |
|
|
232
|
+
|---|---|
|
|
233
|
+
| `POST /api/generate` | `ima2 gen` |
|
|
234
|
+
| `POST /api/edit` | `ima2 edit` |
|
|
235
|
+
| `POST /api/generate/multi` (SSE) | `ima2 multimode` |
|
|
236
|
+
| `POST /api/node/generate` (SSE) / `GET /api/node/:id` | `ima2 node generate` / `ima2 node show` |
|
|
237
|
+
| `GET /api/history` | `ima2 ls` |
|
|
238
|
+
| `DELETE /api/history/:name` / `…/permanent` | `ima2 history rm [--permanent]` |
|
|
239
|
+
| `POST /api/history/restore` | `ima2 history restore --trash-id` |
|
|
240
|
+
| `POST /api/history/favorite` | `ima2 history favorite` |
|
|
241
|
+
| `POST /api/history/import-local` | `ima2 history import` |
|
|
242
|
+
| `POST /api/metadata/read` | `ima2 metadata` / `ima2 show --metadata` |
|
|
243
|
+
| `GET/POST/PUT/DELETE /api/sessions[/…]` | `ima2 session ls/show/create/rm/rename` |
|
|
244
|
+
| `GET/PUT /api/sessions/:id/graph` | `ima2 session graph load/save` |
|
|
245
|
+
| `GET/PUT /api/sessions/:id/style-sheet[/…]` | `ima2 session style-sheet …` |
|
|
246
|
+
| `GET/PUT/DELETE /api/annotations/:name` | `ima2 annotate get/set/rm` |
|
|
247
|
+
| `POST /api/canvas-versions` / `PUT /api/canvas-versions/:name` | `ima2 canvas-versions save/update` |
|
|
248
|
+
| `GET/POST/PUT/DELETE /api/prompts[/…]` | `ima2 prompt …` |
|
|
249
|
+
| `GET/POST/PUT/DELETE /api/prompt-folders[/…]` | `ima2 prompt folder …` |
|
|
250
|
+
| `…/api/prompt-import/…` | `ima2 prompt import sources/refresh/curated/discovery/folder` |
|
|
251
|
+
| `…/api/cardnews/…` (gated on `features.cardNews`) | `ima2 cardnews …` |
|
|
252
|
+
| `POST /api/comfy/export-image` | `ima2 comfy export` |
|
|
253
|
+
| `GET /api/inflight` / `DELETE /api/inflight/:id` | `ima2 inflight ls` (alias `ps`) / `ima2 inflight rm` (alias `cancel`) |
|
|
254
|
+
| `GET /api/storage/status` / `POST /api/storage/open-generated-dir` | `ima2 storage status` / `ima2 storage open` |
|
|
255
|
+
| `GET /api/billing` / `GET /api/providers` / `GET /api/oauth/status` | `ima2 billing` / `ima2 providers` / `ima2 oauth status` |
|
|
256
|
+
| `GET /api/health` | `ima2 ping` |
|
|
257
|
+
|
|
258
|
+
Notes:
|
|
259
|
+
- `ima2 history favorite` and `ima2 annotate …` send `X-Ima2-Browser-Id: cli-<sha1prefix>` derived from the config dir, so CLI activity does not collide with browser sessions.
|
|
260
|
+
- `ima2 session graph save` performs a GET-then-PUT with `If-Match: "<version>"` to guard against `GRAPH_VERSION_CONFLICT`.
|
|
261
|
+
- `ima2 history import` and `ima2 canvas-versions save/update` send raw bytes with `Content-Type: image/<png|jpeg|webp>`; the SSE endpoints (`multimode`, `node generate`) use `Accept: text/event-stream`.
|
|
262
|
+
- `ima2 cardnews …` checks `runtimeConfig.features.cardNews` before calling the gated endpoints; when disabled the CLI exits 2 with a clear message instead of producing a 404.
|
|
263
|
+
|
|
224
264
|
## CLI Discovery
|
|
225
265
|
|
|
226
266
|
The server writes an advertisement file at:
|
package/docs/CLI.md
ADDED
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
# CLI Reference
|
|
2
|
+
|
|
3
|
+
Every server route under `/api/*` has a CLI wrapper. The CLI is a thin shell over the local server, so most commands require a running `ima2 serve` (the few exceptions — `serve`, `setup`, `doctor`, `status`, `open`, `reset`, `config` — work without a live server).
|
|
4
|
+
|
|
5
|
+
For a quick start, see the [main README](../README.md). For endpoint mapping, see [API.md](API.md).
|
|
6
|
+
|
|
7
|
+
## Server commands
|
|
8
|
+
|
|
9
|
+
| Command | Description |
|
|
10
|
+
|---|---|
|
|
11
|
+
| `ima2 serve [--dev]` | Start the local web server; `--dev` enables verbose server diagnostics |
|
|
12
|
+
| `ima2 setup` / `ima2 login` | Reconfigure saved auth (interactive) |
|
|
13
|
+
| `ima2 status` | Show config and OAuth status |
|
|
14
|
+
| `ima2 doctor` | Diagnose Node, package, config, and auth |
|
|
15
|
+
| `ima2 open` | Open the web UI in a browser |
|
|
16
|
+
| `ima2 reset` | Remove saved config |
|
|
17
|
+
|
|
18
|
+
## Common flags
|
|
19
|
+
|
|
20
|
+
These work on most client commands:
|
|
21
|
+
|
|
22
|
+
| Flag | Meaning |
|
|
23
|
+
|---|---|
|
|
24
|
+
| `--server <url>` | Override server discovery (default uses `~/.ima2/server.json`, falls back to `IMA2_SERVER` env) |
|
|
25
|
+
| `--json` | Emit machine-readable JSON instead of human-formatted output |
|
|
26
|
+
| `-h`, `--help` | Show subcommand help |
|
|
27
|
+
|
|
28
|
+
## Generation
|
|
29
|
+
|
|
30
|
+
| Command | Description |
|
|
31
|
+
|---|---|
|
|
32
|
+
| `ima2 gen <prompt>` | Generate from the CLI |
|
|
33
|
+
| `ima2 edit <file> --prompt <text>` | Edit an existing image |
|
|
34
|
+
| `ima2 multimode <prompt>` | Multi-image SSE generation (streams `phase` / `partial` / `image` events) |
|
|
35
|
+
| `ima2 node generate` | Node-mode generate (SSE; supports `--no-stream`) |
|
|
36
|
+
| `ima2 node show <nodeId>` | Read node metadata |
|
|
37
|
+
|
|
38
|
+
Generation flags include `--reasoning-effort {none\|low\|medium\|high\|xhigh}`, `--web-search` / `--no-web-search`, `--model`, `--mode`, `--moderation`, `--ref <file>` (repeatable, up to 5), `-q low|medium|high`, `-n <count>`, `-o <file>`.
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
ima2 gen "a poster of a samurai cat" --model gpt-5.4 --reasoning-effort high
|
|
42
|
+
ima2 edit input.png --prompt "make it rainy" --web-search
|
|
43
|
+
ima2 multimode "two cats playing" -n 2
|
|
44
|
+
ima2 node generate --node n_abc --prompt "add neon lights" --no-stream
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
## History and metadata
|
|
48
|
+
|
|
49
|
+
| Command | Description |
|
|
50
|
+
|---|---|
|
|
51
|
+
| `ima2 ls [--session <id>] [--favorites]` | List recent history |
|
|
52
|
+
| `ima2 show <name> [--metadata]` | Reveal a generated asset; optional embedded-metadata read |
|
|
53
|
+
| `ima2 history rm <name> [--permanent]` | Soft-delete (default) or permanently delete |
|
|
54
|
+
| `ima2 history restore --trash-id <id>` | Restore from trash |
|
|
55
|
+
| `ima2 history favorite <name>` | Toggle favorite (sends `X-Ima2-Browser-Id`) |
|
|
56
|
+
| `ima2 history import <file>` | Import a local image (raw PNG/JPEG/WEBP) into history |
|
|
57
|
+
| `ima2 metadata <file>` | Read embedded metadata from any local image (no server roundtrip needed for the read itself, but the route lives on the server) |
|
|
58
|
+
|
|
59
|
+
## Sessions and graphs
|
|
60
|
+
|
|
61
|
+
| Command | Description |
|
|
62
|
+
|---|---|
|
|
63
|
+
| `ima2 session ls / show <id> / create <title> / rm <id> / rename <id> <title>` | Session CRUD |
|
|
64
|
+
| `ima2 session graph save <id> --file <graph.json>` | Save a graph (uses GET-then-PUT with `If-Match` to guard against `GRAPH_VERSION_CONFLICT`) |
|
|
65
|
+
| `ima2 session graph load <id>` | Read the latest graph snapshot |
|
|
66
|
+
| `ima2 session style-sheet get <id> / put <id> --file <style.json> / enable <id> / disable <id> / extract <id>` | Style-sheet ops (advanced; UI no longer surfaces this — kept for API-level workflows) |
|
|
67
|
+
|
|
68
|
+
## Annotations and canvas
|
|
69
|
+
|
|
70
|
+
| Command | Description |
|
|
71
|
+
|---|---|
|
|
72
|
+
| `ima2 annotate get <name>` | Read annotation for an image |
|
|
73
|
+
| `ima2 annotate set <name> --body <json\|@file\|->` | Write annotation (sends `X-Ima2-Browser-Id`) |
|
|
74
|
+
| `ima2 annotate rm <name>` | Remove annotation |
|
|
75
|
+
| `ima2 canvas-versions save <imagefile> [--source <name>] [--prompt <text>]` | Save a raw PNG canvas version |
|
|
76
|
+
| `ima2 canvas-versions update <name> <imagefile>` | Update an existing canvas version |
|
|
77
|
+
|
|
78
|
+
## Prompt library
|
|
79
|
+
|
|
80
|
+
| Command | Description |
|
|
81
|
+
|---|---|
|
|
82
|
+
| `ima2 prompt ls [-q <search>] [--folder <id>] [--favorites]` | List prompts |
|
|
83
|
+
| `ima2 prompt show <id>` | Read one prompt |
|
|
84
|
+
| `ima2 prompt create --name <n> --text <t> [--folder <id>] [--tags <a,b>]` | Create |
|
|
85
|
+
| `ima2 prompt edit <id> [--name] [--text] [--folder] [--tags]` | Edit |
|
|
86
|
+
| `ima2 prompt rm <id>` | Delete |
|
|
87
|
+
| `ima2 prompt favorite <id>` | Toggle favorite |
|
|
88
|
+
| `ima2 prompt export <id> [-o <file>]` | Export one prompt to JSON |
|
|
89
|
+
| `ima2 prompt folder ls / create <name> / rename <id> <name> / rm <id> [--strategy moveToRoot\|deleteItems]` | Folder CRUD |
|
|
90
|
+
| `ima2 prompt import sources` | List configured import sources |
|
|
91
|
+
| `ima2 prompt import refresh --source <id>` | Re-index a source |
|
|
92
|
+
| `ima2 prompt import curated --source <id> --q <query>` | Curated import (commits prompts) |
|
|
93
|
+
| `ima2 prompt import discovery --q <query> --seeds <a,b,c>` | Discovery import (curator-only on some servers) |
|
|
94
|
+
| `ima2 prompt import folder <localpath>` | Import a local folder of prompts |
|
|
95
|
+
|
|
96
|
+
## Card News (gated)
|
|
97
|
+
|
|
98
|
+
Card News requires the server to be started with `IMA2_CARD_NEWS=1` (or `features.cardNews: true` in `~/.ima2/config.json`). When disabled, the CLI exits 2 with a clear message instead of producing a 404.
|
|
99
|
+
|
|
100
|
+
| Command | Description |
|
|
101
|
+
|---|---|
|
|
102
|
+
| `ima2 cardnews templates` | List image-templates and role-templates |
|
|
103
|
+
| `ima2 cardnews template preview <id>` | Preview an image template |
|
|
104
|
+
| `ima2 cardnews sets` | List card sets |
|
|
105
|
+
| `ima2 cardnews set show <id>` / `set manifest <id>` | Show a set or its manifest |
|
|
106
|
+
| `ima2 cardnews draft / generate / export [--data <json>]` | Pass-through bodies (server forwards `req.body`) |
|
|
107
|
+
| `ima2 cardnews job create [--data <json>]` | Create + start a job |
|
|
108
|
+
| `ima2 cardnews job show <jobId>` | Show one job |
|
|
109
|
+
| `ima2 cardnews job retry <jobId> [--cards <id,id>]` | Retry a job (optionally specific cards) |
|
|
110
|
+
| `ima2 cardnews card regenerate <cardId> [--data <json>]` | Regenerate a single card |
|
|
111
|
+
|
|
112
|
+
## Observability and jobs
|
|
113
|
+
|
|
114
|
+
| Command | Description |
|
|
115
|
+
|---|---|
|
|
116
|
+
| `ima2 ps` | Alias for `inflight ls` (kept for backward compatibility) |
|
|
117
|
+
| `ima2 cancel <id>` | Alias for `inflight rm` |
|
|
118
|
+
| `ima2 inflight ls [--kind classic\|node] [--session <id>] [--terminal]` | List active (and optionally terminal) jobs with phase / model / prompt |
|
|
119
|
+
| `ima2 inflight rm <requestId>` | Force-remove a stuck job |
|
|
120
|
+
| `ima2 storage status` | Storage inspection (richer than `doctor`) |
|
|
121
|
+
| `ima2 storage open` | Open the generated dir in the OS file manager (POST) |
|
|
122
|
+
| `ima2 billing` | API usage / quota |
|
|
123
|
+
| `ima2 providers` | Configured providers |
|
|
124
|
+
| `ima2 oauth status` | OAuth proxy state |
|
|
125
|
+
| `ima2 ping` | Health-check the running server |
|
|
126
|
+
|
|
127
|
+
## Config
|
|
128
|
+
|
|
129
|
+
`config` reads/writes `~/.ima2/config.json` (the file layer). Effective values follow `env > file > defaults`.
|
|
130
|
+
|
|
131
|
+
| Command | Description |
|
|
132
|
+
|---|---|
|
|
133
|
+
| `ima2 config path` | Print the config file path |
|
|
134
|
+
| `ima2 config ls [--effective]` | Print the file layer (default), or merged effective config with `--effective` |
|
|
135
|
+
| `ima2 config get <key>` | Read a dotted key from the effective config; secrets matching `/token\|secret\|apikey\|password/i` are redacted |
|
|
136
|
+
| `ima2 config set <key> <value>` | Write to the file layer; rejects unknown keys, refuses auth keys (`provider`, `apiKey`), warns when an env var is overriding the same key, prints a restart-required note |
|
|
137
|
+
| `ima2 config rm <key>` | Remove a key from the file layer |
|
|
138
|
+
|
|
139
|
+
Allowed keys (whitelist):
|
|
140
|
+
|
|
141
|
+
```
|
|
142
|
+
imageModels.default imageModels.reasoningEffort
|
|
143
|
+
log.level features.cardNews
|
|
144
|
+
cardNewsPlanner.{enabled,model,timeoutMs,deterministicFallback}
|
|
145
|
+
comfy.{defaultUrl,uploadTimeoutMs,maxUploadBytes}
|
|
146
|
+
storage.{generatedDir,generatedDirName}
|
|
147
|
+
server.{port,host,bodyLimit}
|
|
148
|
+
oauth.{proxyPort,statusTimeoutMs,restartDelayMs}
|
|
149
|
+
limits.{maxRefCount,maxParallel}
|
|
150
|
+
history.{defaultPageSize,maxPageCap}
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
To change `provider` / `apiKey`, run `ima2 setup` or `ima2 login` instead.
|
|
154
|
+
|
|
155
|
+
## Other
|
|
156
|
+
|
|
157
|
+
| Command | Description |
|
|
158
|
+
|---|---|
|
|
159
|
+
| `ima2 comfy export <filename>` | Export a ComfyUI workflow (`POST /api/comfy/export-image`) |
|
|
160
|
+
|
|
161
|
+
## Discovery
|
|
162
|
+
|
|
163
|
+
The server writes `~/.ima2/server.json` on start. CLI commands read this file to find the actual port (the backend can fall back from `3333` to `3334+`). Override discovery with `--server <url>` or `IMA2_SERVER=http://localhost:3333`.
|
|
164
|
+
|
|
165
|
+
## Examples
|
|
166
|
+
|
|
167
|
+
```bash
|
|
168
|
+
# Generation with reasoning effort and web search
|
|
169
|
+
ima2 gen "poster" --model gpt-5.4 --moderation low --reasoning-effort high
|
|
170
|
+
ima2 edit input.png --prompt "make it rainy" --web-search
|
|
171
|
+
ima2 multimode "two cats playing" -n 2 -o cat_{i}.png
|
|
172
|
+
|
|
173
|
+
# History and metadata
|
|
174
|
+
ima2 ls --session sess_abc --favorites
|
|
175
|
+
ima2 show img_xyz.png --metadata
|
|
176
|
+
ima2 history import ./local.png
|
|
177
|
+
|
|
178
|
+
# Prompts
|
|
179
|
+
ima2 prompt ls -q sunset
|
|
180
|
+
ima2 prompt import refresh --source curated
|
|
181
|
+
|
|
182
|
+
# Observability
|
|
183
|
+
ima2 inflight ls --terminal
|
|
184
|
+
ima2 storage status --json
|
|
185
|
+
|
|
186
|
+
# Config
|
|
187
|
+
ima2 config set imageModels.reasoningEffort high
|
|
188
|
+
ima2 config get log.level
|
|
189
|
+
ima2 config ls --effective --json
|
|
190
|
+
```
|
package/docs/FAQ.ko.md
CHANGED
|
@@ -12,7 +12,7 @@ English version: [FAQ.md](FAQ.md)
|
|
|
12
12
|
|---|---|
|
|
13
13
|
| 서버에 연결되지 않음 | `ima2 serve`를 켠 뒤 `ima2 ping`을 실행합니다. |
|
|
14
14
|
| OAuth 로그인이 안 됨 | `npx @openai/codex login`을 실행하고 `ima2 serve`를 다시 시작합니다. |
|
|
15
|
-
| API key
|
|
15
|
+
| API key provider가 `API_KEY_REQUIRED`를 반환함 | API 키를 설정하거나 OAuth 공급자로 다시 전환합니다. |
|
|
16
16
|
| 업데이트 후 예전 이미지가 안 보임 | `ima2 doctor`를 실행한 뒤 [예전 이미지 복구 안내](RECOVER_OLD_IMAGES.md)를 확인합니다. |
|
|
17
17
|
| `gpt-5.5`만 실패함 | Codex CLI를 업데이트하고, 안정 대안으로 `gpt-5.4`를 사용합니다. |
|
|
18
18
|
| 레퍼런스 업로드 실패 | JPEG/PNG로 변환하고 해상도를 낮춰 보세요. 레퍼런스는 최대 5장입니다. |
|
|
@@ -70,13 +70,13 @@ npm install -g ima2-gen@latest
|
|
|
70
70
|
|
|
71
71
|
### OpenAI API 키가 필요한가요?
|
|
72
72
|
|
|
73
|
-
|
|
73
|
+
기본 생성 경로에는 필요하지 않습니다. 기본 경로는 로컬 Codex/ChatGPT OAuth 세션을 사용합니다.
|
|
74
74
|
|
|
75
|
-
|
|
75
|
+
API 키를 설정하면 이미지 생성 엔드포인트도 `provider: "api"`로 Responses API `image_generation` 도구를 사용할 수 있습니다.
|
|
76
76
|
|
|
77
|
-
### 설정 화면의 "
|
|
77
|
+
### 설정 화면의 "API key provider available"은 무슨 뜻인가요?
|
|
78
78
|
|
|
79
|
-
|
|
79
|
+
`ima2-gen`이 유효한 API 키를 찾았다는 뜻입니다. API-Key 모드는 생성, 편집, 멀티모드, 노드 출력을 지원합니다. 키가 없으면 `provider: "api"` 요청은 upstream 호출 전에 `API_KEY_REQUIRED`로 실패합니다.
|
|
80
80
|
|
|
81
81
|
### Codex CLI에 이미 로그인되어 있으면 자동으로 잡히나요?
|
|
82
82
|
|