ima2-gen 1.1.21 → 1.1.22

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 (208) hide show
  1. package/README.md +30 -4
  2. package/bin/ima2.js +14 -4
  3. package/bin/lib/platform.js +34 -5
  4. package/docs/README.ko.md +31 -0
  5. package/lib/agentQueueWorker.js +6 -0
  6. package/lib/agentRuntime.js +3 -2
  7. package/lib/atomicWrite.js +14 -0
  8. package/lib/grokProxyLauncher.js +5 -3
  9. package/lib/inflight.js +1 -1
  10. package/lib/oauthLauncher.js +5 -0
  11. package/lib/videoFrameExtract.js +3 -3
  12. package/package.json +5 -7
  13. package/routes/edit.js +2 -1
  14. package/routes/generate.js +4 -3
  15. package/routes/health.js +4 -3
  16. package/routes/multimode.js +2 -1
  17. package/routes/video.js +4 -2
  18. package/server.js +29 -2
  19. package/ui/dist/.vite/manifest.json +12 -12
  20. package/ui/dist/assets/{AgentWorkspace-B_hq9CLg.js → AgentWorkspace-COxQ5TjU.js} +1 -1
  21. package/ui/dist/assets/{CardNewsWorkspace-wD12J7qk.js → CardNewsWorkspace-B0OkcuVz.js} +1 -1
  22. package/ui/dist/assets/{NodeCanvas-CI_wuPMf.js → NodeCanvas-BSsclEBh.js} +1 -1
  23. package/ui/dist/assets/{PromptBuilderPanel-CUTujJUV.js → PromptBuilderPanel-DpC9A5Rz.js} +1 -1
  24. package/ui/dist/assets/{PromptImportDialog-CUi66jPK.js → PromptImportDialog-CVwT0rLd.js} +2 -2
  25. package/ui/dist/assets/{PromptImportDiscoverySection-Cm3vrjY4.js → PromptImportDiscoverySection-BDCkRCRs.js} +1 -1
  26. package/ui/dist/assets/{PromptImportFolderSection-DOtWTD9n.js → PromptImportFolderSection-QoKbZD83.js} +1 -1
  27. package/ui/dist/assets/{PromptLibraryPanel-BMjQegRa.js → PromptLibraryPanel-BhFgeKnY.js} +2 -2
  28. package/ui/dist/assets/SettingsWorkspace-CfjrlH5R.js +1 -0
  29. package/ui/dist/assets/index-C-mur7pa.css +1 -0
  30. package/ui/dist/assets/index-CCP5nUOj.js +42 -0
  31. package/ui/dist/assets/{index-31uVIdt4.js → index-Cxhzi3bs.js} +1 -1
  32. package/ui/dist/index.html +2 -2
  33. package/bin/commands/annotate.ts +0 -119
  34. package/bin/commands/cancel.ts +0 -48
  35. package/bin/commands/canvas-versions.ts +0 -80
  36. package/bin/commands/capabilities.ts +0 -110
  37. package/bin/commands/cardnews.ts +0 -249
  38. package/bin/commands/comfy.ts +0 -54
  39. package/bin/commands/config.ts +0 -186
  40. package/bin/commands/defaults.ts +0 -192
  41. package/bin/commands/doctor.ts +0 -202
  42. package/bin/commands/edit.ts +0 -150
  43. package/bin/commands/gen.ts +0 -214
  44. package/bin/commands/grok.ts +0 -90
  45. package/bin/commands/history.ts +0 -146
  46. package/bin/commands/ls.ts +0 -64
  47. package/bin/commands/metadata.ts +0 -39
  48. package/bin/commands/multimode.ts +0 -196
  49. package/bin/commands/node.ts +0 -166
  50. package/bin/commands/observability.ts +0 -176
  51. package/bin/commands/ping.ts +0 -31
  52. package/bin/commands/prompt-sub/build.ts +0 -101
  53. package/bin/commands/prompt.ts +0 -492
  54. package/bin/commands/ps.ts +0 -81
  55. package/bin/commands/session.ts +0 -266
  56. package/bin/commands/show.ts +0 -72
  57. package/bin/commands/skill.ts +0 -70
  58. package/bin/commands/video.ts +0 -442
  59. package/bin/ima2.ts +0 -430
  60. package/bin/lib/args.ts +0 -92
  61. package/bin/lib/browser-id.ts +0 -16
  62. package/bin/lib/client.ts +0 -122
  63. package/bin/lib/config-store.ts +0 -120
  64. package/bin/lib/destructive-confirm.ts +0 -19
  65. package/bin/lib/doctor-checks.ts +0 -91
  66. package/bin/lib/error-hints.ts +0 -23
  67. package/bin/lib/files.ts +0 -39
  68. package/bin/lib/output.ts +0 -73
  69. package/bin/lib/platform.ts +0 -99
  70. package/bin/lib/recover-output.ts +0 -139
  71. package/bin/lib/sse.ts +0 -73
  72. package/bin/lib/star-prompt.ts +0 -97
  73. package/bin/lib/storage-doctor.ts +0 -39
  74. package/bin/lib/ui-build.ts +0 -85
  75. package/config.ts +0 -354
  76. package/lib/agentCommandParser.ts +0 -69
  77. package/lib/agentGenerationPlanner.ts +0 -273
  78. package/lib/agentQuestionResponder.ts +0 -266
  79. package/lib/agentQueueStore.ts +0 -270
  80. package/lib/agentQueueWorker.ts +0 -89
  81. package/lib/agentRuntime.ts +0 -604
  82. package/lib/agentSettings.ts +0 -72
  83. package/lib/agentStore.ts +0 -422
  84. package/lib/agentStoreRows.ts +0 -136
  85. package/lib/agentTypes.ts +0 -154
  86. package/lib/apiCachePolicy.ts +0 -11
  87. package/lib/assetLifecycle.ts +0 -146
  88. package/lib/canvasVersionStore.ts +0 -223
  89. package/lib/capabilities.ts +0 -126
  90. package/lib/cardNewsGenerator.ts +0 -271
  91. package/lib/cardNewsJobStore.ts +0 -142
  92. package/lib/cardNewsManifestStore.ts +0 -154
  93. package/lib/cardNewsPlanner.ts +0 -236
  94. package/lib/cardNewsPlannerClient.ts +0 -155
  95. package/lib/cardNewsPlannerPrompt.ts +0 -62
  96. package/lib/cardNewsPlannerSchema.ts +0 -321
  97. package/lib/cardNewsRoleTemplateStore.ts +0 -47
  98. package/lib/cardNewsTemplateStore.ts +0 -252
  99. package/lib/codexDetect.ts +0 -71
  100. package/lib/comfyBridge.ts +0 -235
  101. package/lib/composerSnapshot.ts +0 -33
  102. package/lib/configKeys.ts +0 -62
  103. package/lib/db.ts +0 -295
  104. package/lib/errInfo.ts +0 -43
  105. package/lib/errorClassify.ts +0 -100
  106. package/lib/generationCancel.ts +0 -28
  107. package/lib/generationErrors.ts +0 -238
  108. package/lib/grokImageAdapter.ts +0 -513
  109. package/lib/grokMultimodeAdapter.ts +0 -84
  110. package/lib/grokProxyLauncher.ts +0 -153
  111. package/lib/grokRuntime.ts +0 -23
  112. package/lib/grokSizeMapper.ts +0 -71
  113. package/lib/grokVideoAdapter.ts +0 -458
  114. package/lib/grokVideoCanvas.ts +0 -26
  115. package/lib/grokVideoDownload.ts +0 -59
  116. package/lib/grokVideoPlannerPrompt.ts +0 -67
  117. package/lib/historyIndex.ts +0 -51
  118. package/lib/historyList.ts +0 -181
  119. package/lib/imageMetadata.ts +0 -113
  120. package/lib/imageMetadataStore.ts +0 -67
  121. package/lib/imageModels.ts +0 -165
  122. package/lib/inflight.ts +0 -281
  123. package/lib/localImportStore.ts +0 -114
  124. package/lib/logger.ts +0 -161
  125. package/lib/nodeStore.ts +0 -91
  126. package/lib/oauthLauncher.ts +0 -94
  127. package/lib/oauthNormalize.ts +0 -30
  128. package/lib/oauthProxy/errors.ts +0 -128
  129. package/lib/oauthProxy/generators.ts +0 -494
  130. package/lib/oauthProxy/index.ts +0 -28
  131. package/lib/oauthProxy/prompts.ts +0 -123
  132. package/lib/oauthProxy/references.ts +0 -45
  133. package/lib/oauthProxy/runtime.ts +0 -115
  134. package/lib/oauthProxy/streams.ts +0 -232
  135. package/lib/oauthProxy/types.ts +0 -9
  136. package/lib/oauthProxy.ts +0 -3
  137. package/lib/openDirectory.ts +0 -47
  138. package/lib/pngInfo.ts +0 -26
  139. package/lib/promptBuilder/attachments.ts +0 -74
  140. package/lib/promptBuilder/client.ts +0 -130
  141. package/lib/promptBuilder/constants.ts +0 -9
  142. package/lib/promptBuilder/context.ts +0 -36
  143. package/lib/promptBuilder/errors.ts +0 -12
  144. package/lib/promptBuilder/requestSchema.ts +0 -56
  145. package/lib/promptBuilder/responseParser.ts +0 -219
  146. package/lib/promptBuilder/systemPrompt.ts +0 -135
  147. package/lib/promptBuilder/transport.ts +0 -94
  148. package/lib/promptBuilder/types.ts +0 -109
  149. package/lib/promptImport/curatedSources.ts +0 -141
  150. package/lib/promptImport/discoveryRegistry.ts +0 -329
  151. package/lib/promptImport/errors.ts +0 -18
  152. package/lib/promptImport/githubDiscovery.ts +0 -309
  153. package/lib/promptImport/githubFolder.ts +0 -397
  154. package/lib/promptImport/githubSource.ts +0 -257
  155. package/lib/promptImport/gptImageHints.ts +0 -70
  156. package/lib/promptImport/parsePromptCandidates.ts +0 -179
  157. package/lib/promptImport/promptIndex.ts +0 -326
  158. package/lib/promptImport/rankPromptCandidates.ts +0 -65
  159. package/lib/promptImport/types.ts +0 -103
  160. package/lib/promptSafetyPolicy.ts +0 -5
  161. package/lib/providerOptions.ts +0 -56
  162. package/lib/referenceImageCompress.ts +0 -84
  163. package/lib/refs.ts +0 -133
  164. package/lib/requestLogger.ts +0 -49
  165. package/lib/responsesDoctor.ts +0 -456
  166. package/lib/responsesErrors.ts +0 -83
  167. package/lib/responsesFallback.ts +0 -114
  168. package/lib/responsesImageAdapter.ts +0 -466
  169. package/lib/responsesParse.ts +0 -452
  170. package/lib/responsesTools.ts +0 -28
  171. package/lib/runtimeContext.ts +0 -146
  172. package/lib/runtimePorts.ts +0 -105
  173. package/lib/sessionStore.ts +0 -308
  174. package/lib/storageMigration.ts +0 -310
  175. package/lib/styleSheet.ts +0 -139
  176. package/lib/systemTrash.ts +0 -20
  177. package/lib/videoContinuity.ts +0 -180
  178. package/lib/videoFrameExtract.ts +0 -78
  179. package/lib/videoSeriesChain.ts +0 -29
  180. package/lib/visibleTextLanguagePolicy.ts +0 -7
  181. package/routes/agent.ts +0 -308
  182. package/routes/annotations.ts +0 -118
  183. package/routes/canvasVersions.ts +0 -69
  184. package/routes/capabilities.ts +0 -18
  185. package/routes/cardNews.ts +0 -211
  186. package/routes/comfy.ts +0 -43
  187. package/routes/edit.ts +0 -352
  188. package/routes/generate.ts +0 -492
  189. package/routes/grok.ts +0 -24
  190. package/routes/health.ts +0 -123
  191. package/routes/history.ts +0 -221
  192. package/routes/imageImport.ts +0 -37
  193. package/routes/index.ts +0 -52
  194. package/routes/metadata.ts +0 -77
  195. package/routes/multimode.ts +0 -499
  196. package/routes/nodes.ts +0 -578
  197. package/routes/promptBuilder.ts +0 -37
  198. package/routes/promptImport.ts +0 -379
  199. package/routes/prompts.ts +0 -428
  200. package/routes/quota.ts +0 -89
  201. package/routes/sessions.ts +0 -317
  202. package/routes/storage.ts +0 -47
  203. package/routes/video.ts +0 -300
  204. package/routes/videoExtended.ts +0 -284
  205. package/server.ts +0 -293
  206. package/ui/dist/assets/SettingsWorkspace-PiaVnsdA.js +0 -1
  207. package/ui/dist/assets/index-CjgnNtgt.css +0 -1
  208. package/ui/dist/assets/index-Da2s4_-5.js +0 -36
@@ -1,9 +0,0 @@
1
- export const VALID_PROMPT_BUILDER_MODELS = new Set(["gpt-5.5", "gpt-5.4", "gpt-5.4-mini"]);
2
- export const DEFAULT_PROMPT_BUILDER_MODEL = "gpt-5.5";
3
- export const MAX_MESSAGES = 24;
4
- export const MAX_MESSAGE_CHARS = 16_000;
5
- export const MAX_ATTACHMENTS = 6;
6
- export const MAX_TEXT_ATTACHMENT_CHARS = 20_000;
7
- export const MAX_ATTACHMENT_NAME_CHARS = 160;
8
- export const MAX_ATTACHMENT_MIME_CHARS = 120;
9
- export const PROMPT_BUILDER_RESPONSE_MAX_OUTPUT_TOKENS = 2400;
@@ -1,36 +0,0 @@
1
- import type { PromptBuilderContext } from "./types.js";
2
-
3
- export function contextText(context: PromptBuilderContext | undefined): string {
4
- const lines: string[] = [];
5
- const currentPrompt =
6
- typeof context?.currentPrompt === "string" ? context.currentPrompt.trim() : "";
7
- if (currentPrompt) lines.push(`Current main prompt:\n${currentPrompt}`);
8
-
9
- const blocks = Array.isArray(context?.insertedPrompts) ? context.insertedPrompts : [];
10
- if (blocks.length > 0) {
11
- lines.push(
12
- `Inserted prompt blocks:\n${blocks
13
- .map((block, index) => {
14
- const name =
15
- typeof block.name === "string" && block.name.trim()
16
- ? block.name.trim()
17
- : `Block ${index + 1}`;
18
- const text = typeof block.text === "string" ? block.text.trim() : "";
19
- return `- ${name}: ${text}`;
20
- })
21
- .join("\n")}`,
22
- );
23
- }
24
-
25
- if (context?.settings && typeof context.settings === "object") {
26
- lines.push(`Generation settings:\n${JSON.stringify(context.settings)}`);
27
- }
28
-
29
- const resultPrompt =
30
- typeof context?.currentResultPrompt === "string"
31
- ? context.currentResultPrompt.trim()
32
- : "";
33
- if (resultPrompt) lines.push(`Current result prompt:\n${resultPrompt}`);
34
-
35
- return lines.join("\n\n");
36
- }
@@ -1,12 +0,0 @@
1
- import type { PromptBuilderError } from "./types.js";
2
-
3
- export function promptBuilderError(
4
- message: string,
5
- code: string,
6
- status = 400,
7
- ): PromptBuilderError {
8
- const err = new Error(message) as PromptBuilderError;
9
- err.code = code;
10
- err.status = status;
11
- return err;
12
- }
@@ -1,56 +0,0 @@
1
- import {
2
- VALID_PROMPT_BUILDER_MODELS,
3
- DEFAULT_PROMPT_BUILDER_MODEL,
4
- MAX_MESSAGES,
5
- MAX_MESSAGE_CHARS,
6
- } from "./constants.js";
7
- import { promptBuilderError } from "./errors.js";
8
- import { normalizeAttachments } from "./attachments.js";
9
- import type { PromptBuilderMessage } from "./types.js";
10
-
11
- export function normalizeModel(raw: unknown): string {
12
- if (typeof raw !== "string" || raw.trim().length === 0) return DEFAULT_PROMPT_BUILDER_MODEL;
13
- if (!VALID_PROMPT_BUILDER_MODELS.has(raw)) {
14
- throw promptBuilderError(
15
- "model must be one of: gpt-5.5, gpt-5.4, gpt-5.4-mini",
16
- "PROMPT_BUILDER_BAD_MODEL",
17
- );
18
- }
19
- return raw;
20
- }
21
-
22
- export function normalizeMessages(raw: unknown): PromptBuilderMessage[] {
23
- if (!Array.isArray(raw)) {
24
- throw promptBuilderError("messages must be an array", "PROMPT_BUILDER_BAD_MESSAGES");
25
- }
26
- const messages = raw.slice(-MAX_MESSAGES).map((message): PromptBuilderMessage => {
27
- if (!message || typeof message !== "object") {
28
- throw promptBuilderError("each message must be an object", "PROMPT_BUILDER_BAD_MESSAGES");
29
- }
30
- const item = message as { role?: unknown; content?: unknown; attachments?: unknown };
31
- const role = item.role === "assistant" ? "assistant" : item.role === "user" ? "user" : null;
32
- if (!role) {
33
- throw promptBuilderError(
34
- "message role must be user or assistant",
35
- "PROMPT_BUILDER_BAD_MESSAGES",
36
- );
37
- }
38
- const content = typeof item.content === "string" ? item.content.trim() : "";
39
- if (!content && role === "user") {
40
- throw promptBuilderError("message content is required", "PROMPT_BUILDER_EMPTY_MESSAGE");
41
- }
42
- return {
43
- role,
44
- content: content.slice(0, MAX_MESSAGE_CHARS),
45
- attachments: normalizeAttachments(item.attachments),
46
- };
47
- });
48
- const last = messages.at(-1);
49
- if (!last || last.role !== "user" || !last.content.trim()) {
50
- throw promptBuilderError(
51
- "last message must be a non-empty user message",
52
- "PROMPT_BUILDER_EMPTY_MESSAGE",
53
- );
54
- }
55
- return messages;
56
- }
@@ -1,219 +0,0 @@
1
- import { promptBuilderError } from "./errors.js";
2
- import type {
3
- PromptBuilderError,
4
- ResponseShapeSummary,
5
- ChatCompletionBody,
6
- ResponsesBody,
7
- ResponsesReadResult,
8
- } from "./types.js";
9
-
10
- function safeUpstreamString(value: unknown): string | undefined {
11
- return typeof value === "string" && value.trim()
12
- ? value.trim().slice(0, 160)
13
- : undefined;
14
- }
15
-
16
- export function parseUpstreamError(text: string): Pick<
17
- PromptBuilderError,
18
- "upstreamCode" | "upstreamType" | "upstreamParam"
19
- > {
20
- try {
21
- const body = JSON.parse(text) as { error?: Record<string, unknown> };
22
- const error =
23
- body && typeof body.error === "object" ? body.error : undefined;
24
- return {
25
- upstreamCode: safeUpstreamString(error?.code),
26
- upstreamType: safeUpstreamString(error?.type),
27
- upstreamParam: safeUpstreamString(error?.param),
28
- };
29
- } catch {
30
- return {};
31
- }
32
- }
33
-
34
- export function responseSummary(body: unknown): ResponseShapeSummary {
35
- if (!body || typeof body !== "object") {
36
- return {
37
- responseBodyKeys: "",
38
- responseStatus: undefined,
39
- responseErrorCode: undefined,
40
- responseErrorType: undefined,
41
- responseErrorParam: undefined,
42
- responseIncompleteReason: undefined,
43
- responseOutputTypes: "",
44
- responseContentTypes: "",
45
- responseOutputCount: 0,
46
- responseContentCount: 0,
47
- };
48
- }
49
- const record = body as Record<string, unknown>;
50
- const output = Array.isArray(record.output) ? record.output : [];
51
- const error =
52
- record.error && typeof record.error === "object"
53
- ? (record.error as Record<string, unknown>)
54
- : undefined;
55
- const incomplete =
56
- record.incomplete_details && typeof record.incomplete_details === "object"
57
- ? (record.incomplete_details as Record<string, unknown>)
58
- : undefined;
59
- const contentItems = output.flatMap((item) => {
60
- if (!item || typeof item !== "object") return [];
61
- const content = (item as { content?: unknown }).content;
62
- return Array.isArray(content) ? content : [];
63
- });
64
- const outputTypes = output
65
- .map((item) =>
66
- item && typeof item === "object"
67
- ? (item as { type?: unknown }).type
68
- : undefined,
69
- )
70
- .filter((t): t is string => typeof t === "string" && t.length > 0);
71
- const contentTypes = contentItems
72
- .map((item) =>
73
- item && typeof item === "object"
74
- ? (item as { type?: unknown }).type
75
- : undefined,
76
- )
77
- .filter((t): t is string => typeof t === "string" && t.length > 0);
78
- return {
79
- responseBodyKeys: Object.keys(record).slice(0, 12).join(","),
80
- responseStatus: safeUpstreamString(record.status),
81
- responseErrorCode: safeUpstreamString(error?.code),
82
- responseErrorType: safeUpstreamString(error?.type),
83
- responseErrorParam: safeUpstreamString(error?.param),
84
- responseIncompleteReason: safeUpstreamString(incomplete?.reason),
85
- responseOutputTypes: Array.from(new Set(outputTypes))
86
- .slice(0, 12)
87
- .join(","),
88
- responseContentTypes: Array.from(new Set(contentTypes))
89
- .slice(0, 12)
90
- .join(","),
91
- responseOutputCount: output.length,
92
- responseContentCount: contentItems.length,
93
- };
94
- }
95
-
96
- function extractSseData(block: string): string {
97
- return block
98
- .split("\n")
99
- .filter((line) => line.startsWith("data:"))
100
- .map((line) => line.slice(5).trimStart())
101
- .join("\n");
102
- }
103
-
104
- function parseSseJson(block: string): Record<string, unknown> | null {
105
- const data = extractSseData(block);
106
- if (!data || data === "[DONE]") return null;
107
- try {
108
- const parsed = JSON.parse(data) as unknown;
109
- return parsed && typeof parsed === "object" && !Array.isArray(parsed)
110
- ? (parsed as Record<string, unknown>)
111
- : null;
112
- } catch {
113
- return null;
114
- }
115
- }
116
-
117
- export function extractChatText(body: ChatCompletionBody): string {
118
- return (
119
- body.choices?.find(
120
- (c) => typeof c.message?.content === "string" && c.message.content.trim(),
121
- )?.message?.content ?? ""
122
- );
123
- }
124
-
125
- export function extractResponsesText(body: ResponsesBody): string {
126
- if (typeof body.output_text === "string" && body.output_text.trim())
127
- return body.output_text;
128
- for (const item of body.output ?? []) {
129
- for (const content of item.content ?? []) {
130
- if (typeof content.text === "string" && content.text.trim())
131
- return content.text;
132
- if (
133
- content.text &&
134
- typeof content.text === "object" &&
135
- typeof content.text.value === "string" &&
136
- content.text.value.trim()
137
- )
138
- return content.text.value;
139
- if (typeof content.value === "string" && content.value.trim())
140
- return content.value;
141
- if (typeof content.refusal === "string" && content.refusal.trim())
142
- return content.refusal;
143
- }
144
- }
145
- return "";
146
- }
147
-
148
- export async function readResponsesStream(
149
- res: Response,
150
- ): Promise<ResponsesReadResult> {
151
- const reader = res.body?.getReader();
152
- const decoder = new TextDecoder();
153
- const deltas: string[] = [];
154
- let buffer = "";
155
- let usage: Record<string, unknown> | null = null;
156
- let summary = responseSummary(null);
157
- if (!reader) return { content: "", usage, summary };
158
- while (true) {
159
- const { done, value } = await reader.read();
160
- if (done) break;
161
- buffer += decoder.decode(value, { stream: true });
162
- let boundary = buffer.indexOf("\n\n");
163
- while (boundary !== -1) {
164
- const block = buffer.slice(0, boundary);
165
- buffer = buffer.slice(boundary + 2);
166
- const data = parseSseJson(block);
167
- if (data) {
168
- const type = typeof data.type === "string" ? data.type : "";
169
- if (
170
- type === "response.output_text.delta" &&
171
- typeof data.delta === "string"
172
- ) {
173
- deltas.push(data.delta);
174
- } else if (
175
- (type === "response.completed" || type === "response.incomplete") &&
176
- data.response &&
177
- typeof data.response === "object"
178
- ) {
179
- const response = data.response as Record<string, unknown>;
180
- summary = responseSummary(response);
181
- if (response.usage && typeof response.usage === "object")
182
- usage = response.usage as Record<string, unknown>;
183
- } else if (type === "error") {
184
- throw promptBuilderError(
185
- "Prompt builder stream failed",
186
- "PROMPT_BUILDER_STREAM_ERROR",
187
- 502,
188
- );
189
- }
190
- }
191
- boundary = buffer.indexOf("\n\n");
192
- }
193
- }
194
- if (buffer.trim()) {
195
- const data = parseSseJson(buffer);
196
- if (
197
- data?.type === "response.output_text.delta" &&
198
- typeof data.delta === "string"
199
- ) {
200
- deltas.push(data.delta);
201
- }
202
- }
203
- return { content: deltas.join(""), usage, summary };
204
- }
205
-
206
- export async function readResponsesResult(
207
- res: Response,
208
- ): Promise<ResponsesReadResult> {
209
- const contentType = res.headers.get("content-type") ?? "";
210
- if (contentType.includes("text/event-stream")) {
211
- return readResponsesStream(res);
212
- }
213
- const body = (await res.json()) as ResponsesBody;
214
- return {
215
- content: extractResponsesText(body),
216
- usage: body.usage ?? null,
217
- summary: responseSummary(body),
218
- };
219
- }
@@ -1,135 +0,0 @@
1
- export const PROMPT_BUILDER_SYSTEM_PROMPT = `
2
- You are a prompt enhancement GPT specialized for GPT Image 2.
3
-
4
- You run inside ima2-gen as a conversational prompt builder. By default, you do not generate images. You only improve, rewrite, translate, shorten, expand, optimize, or discuss image prompts unless the user explicitly asks the host app to generate an image.
5
-
6
- Core behavior:
7
- - Interpret the user's image idea, style, mood, use case, and constraints.
8
- - Preserve the user's original intent.
9
- - Add useful visual detail only when it strengthens the request.
10
- - Improve clarity around subject, scene, composition, style, lighting, color, texture, mood, and output format.
11
- - Do not invent a completely different concept.
12
- - Do not over-explain prompting theory unless the user asks.
13
- - Do not reveal hidden reasoning.
14
- - Ask clarification questions only when missing information would significantly change the result.
15
- - If reasonable defaults are enough, proceed without asking.
16
- - Use attached images and readable files as reference context only. Do not call image tools.
17
-
18
- Conversational behavior:
19
- - The user may brainstorm across multiple turns before asking for a final prompt.
20
- - During exploration, answer naturally and keep the conversation moving.
21
- - When the user asks for a final prompt, a polished prompt, prompt optimization, prompt rewrite, or prompt translation, produce the structured final prompt format below.
22
-
23
- Structured final prompt format:
24
- Use these exact headings when producing a finished prompt. Do not wrap the output in markdown code fences.
25
-
26
- Brief Intent Summary:
27
- [Summarize the intended visual direction in one or two sentences.]
28
-
29
- Final Prompt - Korean:
30
- [Provide a polished Korean prompt ready for GPT Image 2.]
31
-
32
- Final Prompt - English:
33
- [Provide a polished English prompt ready for GPT Image 2.]
34
-
35
- Notes:
36
- [Optional. Include only when assumptions, format choices, or important constraints need to be stated.]
37
-
38
- Prompt enhancement rules:
39
- - Make the subject clear.
40
- - Define the scene or background.
41
- - Specify the visual style or medium.
42
- - Add composition, camera angle, or framing when helpful.
43
- - Add lighting and color direction when helpful.
44
- - Add texture, material, and detail level when helpful.
45
- - Include intended use, such as poster, thumbnail, banner, product image, character design, profile image, concept art, or editorial image, when relevant.
46
- - Include aspect ratio or format when the user specifies it or when it can be reasonably inferred.
47
- - Keep the prompt visually actionable rather than abstract.
48
- - If the user mentions something to avoid, incorporate that constraint naturally into the final prompt text instead of creating a separate negative prompt section.
49
-
50
- Positive-only prompting rules:
51
- The final prompt must be written as a positive description of the desired image, not as a list of things to avoid.
52
-
53
- When the user describes something they do not want, treat it as an internal constraint only. Do not repeat the unwanted concept in the final Korean or English prompt unless it is absolutely necessary for user-facing clarification.
54
-
55
- Convert negative instructions into positive target attributes:
56
- - "not elderly" -> "young adult"
57
- - "not messy" -> "clean, organized composition"
58
- - "not scary" -> "calm, approachable mood"
59
- - "not cartoonish" -> "realistic, natural proportions and textures"
60
- - "not too colorful" -> "restrained, muted color palette"
61
- - "no clutter" -> "minimal background with clear focal hierarchy"
62
- - "do not change the face" -> "preserve the original facial identity, expression, and proportions"
63
- - "do not change the product shape" -> "preserve the original product silhouette, proportions, and key design features"
64
-
65
- Avoid these patterns in the final Korean and English prompt text:
66
- - "not ..."
67
- - "no ..."
68
- - "without ..."
69
- - "avoid ..."
70
- - "do not ..."
71
- - "instead of ..."
72
- - "rather than ..."
73
- - "unlike ..."
74
-
75
- Before finalizing, perform a positive-only rewrite pass:
76
- 1. Identify any unwanted concept mentioned by the user.
77
- 2. Replace it with the desired visual target.
78
- 3. Remove the unwanted concept from the final prompt.
79
- 4. Remove negation phrasing from both Korean and English prompts.
80
- 5. Ensure the final prompt describes only what should appear in the image.
81
-
82
- When the user gives a vague style word, translate it into concrete visual language:
83
- - Minimal: clean composition, negative space, simple forms, restrained palette.
84
- - Cinematic: filmic framing, dramatic lighting, atmospheric depth, controlled contrast.
85
- - Luxury: refined materials, elegant lighting, polished surfaces, restrained color palette.
86
- - Cute: rounded shapes, friendly expression, soft proportions, bright or pastel colors.
87
- - Dreamy: soft focus, glowing light, haze, delicate details, ethereal mood.
88
- - Vintage: film grain, faded tones, retro palette, nostalgic texture.
89
- - Futuristic: sleek forms, advanced materials, luminous accents, clean technology-inspired design.
90
- - Cyberpunk: neon lighting, rainy urban atmosphere, reflective surfaces, dark high-contrast palette.
91
- - Photorealistic: realistic lighting, natural textures, camera-based composition, believable details.
92
- - 3D: dimensional form, clear materials, shadows, polished rendering.
93
- - Illustration: stylized shapes, linework or painterly treatment, controlled color design.
94
-
95
- For image editing prompts:
96
- - Clearly state what should be preserved.
97
- - Clearly state what should be changed.
98
- - Explain how the new elements should blend with the original image.
99
- - Mention consistency of lighting, perspective, edges, identity, and material when relevant.
100
- - Provide both Korean and English edit prompts.
101
- - If there are unwanted changes to prevent, express them as preservation constraints inside the prompt, such as "keep the original face, pose, clothing, and proportions unchanged."
102
-
103
- For reference images:
104
- - Identify whether the image is a style reference, subject reference, composition reference, product reference, color reference, mood reference, or edit target.
105
- - Preserve the important traits requested by the user.
106
- - Do not assume the reference image should control every detail unless the user says so.
107
-
108
- For text inside images:
109
- - Preserve the exact wording provided by the user.
110
- - Put the exact text in quotation marks.
111
- - Specify placement, typography, hierarchy, and legibility when relevant.
112
- - Do not translate visible text unless the user asks for translation.
113
-
114
- For variations:
115
- - Provide clearly separated versions.
116
- - Each version must include both Korean and English prompts.
117
- - Vary only the requested axis, such as style, mood, color palette, composition, camera angle, background, medium, or lighting.
118
- - Do not generate images unless explicitly asked.
119
-
120
- Safety and style limits:
121
- - Do not create prompts that violate safety policy.
122
- - Do not directly imitate a living artist's distinctive current style.
123
- - When a living artist style is requested, replace it with broader visual characteristics such as medium, color, lighting, era, composition, texture, or mood.
124
- - Avoid prompts that enable deception, impersonation, or harmful misuse.
125
- - For real people, avoid defamatory, sexualized, misleading, or dignity-violating framing.
126
-
127
- Before finalizing, check:
128
- - Does the prompt preserve the user's original idea?
129
- - Are both Korean and English versions included?
130
- - Are the two versions semantically aligned?
131
- - Is the prompt specific enough for image generation?
132
- - Are constraints expressed inside the prompt text rather than as a separate negative prompt?
133
- - Are any assumptions brief and reasonable?
134
- - Is the output ready to copy and use?
135
- `.trim();
@@ -1,94 +0,0 @@
1
- import { attachmentText, hasImageAttachments } from "./attachments.js";
2
- import { PROMPT_BUILDER_RESPONSE_MAX_OUTPUT_TOKENS } from "./constants.js";
3
- import { PROMPT_BUILDER_SYSTEM_PROMPT } from "./systemPrompt.js";
4
- import { contextText } from "./context.js";
5
- import type {
6
- PromptBuilderMessage,
7
- PromptBuilderContext,
8
- ChatContentPart,
9
- ResponsesContentPart,
10
- } from "./types.js";
11
-
12
- function toChatContent(
13
- message: PromptBuilderMessage,
14
- ): string | ChatContentPart[] {
15
- const text = [message.content, attachmentText(message.attachments)]
16
- .filter(Boolean)
17
- .join("\n\n");
18
- const imageParts = (message.attachments ?? [])
19
- .filter((a) => a.kind === "image" && a.dataUrl)
20
- .map(
21
- (a): ChatContentPart => ({
22
- type: "image_url",
23
- image_url: { url: a.dataUrl as string },
24
- }),
25
- );
26
- if (imageParts.length === 0) return text;
27
- return [{ type: "text", text }, ...imageParts];
28
- }
29
-
30
- function toResponsesContent(
31
- message: PromptBuilderMessage,
32
- ): string | ResponsesContentPart[] {
33
- const text = [message.content, attachmentText(message.attachments)]
34
- .filter(Boolean)
35
- .join("\n\n");
36
- const imageParts = (message.attachments ?? [])
37
- .filter((a) => a.kind === "image" && a.dataUrl)
38
- .map(
39
- (a): ResponsesContentPart => ({
40
- type: "input_image",
41
- image_url: a.dataUrl as string,
42
- }),
43
- );
44
- if (imageParts.length === 0) return text;
45
- return [{ type: "input_text", text }, ...imageParts];
46
- }
47
-
48
- export type TransportPayload = {
49
- endpoint: "chat" | "responses";
50
- body: Record<string, unknown>;
51
- };
52
-
53
- export function buildTransportPayload(
54
- model: string,
55
- messages: PromptBuilderMessage[],
56
- context: PromptBuilderContext | undefined,
57
- ): TransportPayload {
58
- const currentContextText = contextText(context);
59
- const systemText = [
60
- PROMPT_BUILDER_SYSTEM_PROMPT,
61
- currentContextText ? `Current ima2-gen context:\n${currentContextText}` : "",
62
- ]
63
- .filter(Boolean)
64
- .join("\n\n");
65
-
66
- const useResponses = hasImageAttachments(messages);
67
- const endpoint = useResponses ? "responses" : "chat";
68
-
69
- const body = useResponses
70
- ? {
71
- model,
72
- instructions: systemText,
73
- input: messages.map((m) => ({
74
- role: m.role,
75
- content: toResponsesContent(m),
76
- })),
77
- stream: true,
78
- max_output_tokens: PROMPT_BUILDER_RESPONSE_MAX_OUTPUT_TOKENS,
79
- }
80
- : {
81
- model,
82
- messages: [
83
- { role: "system", content: systemText },
84
- ...messages.map((m) => ({
85
- role: m.role,
86
- content: toChatContent(m),
87
- })),
88
- ],
89
- stream: false,
90
- reasoning_effort: "low",
91
- };
92
-
93
- return { endpoint, body };
94
- }
@@ -1,109 +0,0 @@
1
- export type PromptBuilderRole = "user" | "assistant";
2
-
3
- export type PromptBuilderAttachment = {
4
- kind: "image" | "text" | "file";
5
- name: string;
6
- mimeType: string;
7
- size: number;
8
- dataUrl?: string;
9
- text?: string;
10
- };
11
-
12
- export type PromptBuilderMessage = {
13
- role: PromptBuilderRole;
14
- content: string;
15
- attachments?: PromptBuilderAttachment[];
16
- };
17
-
18
- export type PromptBuilderContext = {
19
- currentPrompt?: string;
20
- insertedPrompts?: Array<{ name?: string; text?: string }>;
21
- settings?: Record<string, unknown>;
22
- currentResultPrompt?: string | null;
23
- };
24
-
25
- export type PromptBuilderRequest = {
26
- model?: unknown;
27
- messages?: unknown;
28
- context?: PromptBuilderContext;
29
- };
30
-
31
- export type PromptBuilderError = Error & {
32
- status?: number;
33
- code?: string;
34
- upstreamStatus?: number;
35
- upstreamBodyChars?: number;
36
- upstreamEndpoint?: "chat" | "responses";
37
- upstreamCode?: string;
38
- upstreamType?: string;
39
- upstreamParam?: string;
40
- responseBodyKeys?: string;
41
- responseStatus?: string;
42
- responseErrorCode?: string;
43
- responseErrorType?: string;
44
- responseErrorParam?: string;
45
- responseIncompleteReason?: string;
46
- responseOutputTypes?: string;
47
- responseContentTypes?: string;
48
- responseOutputCount?: number;
49
- responseContentCount?: number;
50
- };
51
-
52
- export type ResponseShapeSummary = Pick<
53
- PromptBuilderError,
54
- | "responseBodyKeys"
55
- | "responseStatus"
56
- | "responseErrorCode"
57
- | "responseErrorType"
58
- | "responseErrorParam"
59
- | "responseIncompleteReason"
60
- | "responseOutputTypes"
61
- | "responseContentTypes"
62
- | "responseOutputCount"
63
- | "responseContentCount"
64
- >;
65
-
66
- export type ChatCompletionBody = {
67
- choices?: Array<{
68
- message?: {
69
- role?: string;
70
- content?: string | null;
71
- };
72
- }>;
73
- usage?: Record<string, unknown>;
74
- };
75
-
76
- export type ResponsesBody = {
77
- output_text?: string;
78
- output?: Array<{
79
- type?: string;
80
- content?: Array<{
81
- type?: string;
82
- text?: string | { value?: string };
83
- value?: string;
84
- refusal?: string;
85
- }>;
86
- }>;
87
- usage?: Record<string, unknown>;
88
- };
89
-
90
- export type ResponsesReadResult = {
91
- content: string;
92
- usage: Record<string, unknown> | null;
93
- summary: ResponseShapeSummary;
94
- };
95
-
96
- export type ChatContentPart =
97
- | { type: "text"; text: string }
98
- | { type: "image_url"; image_url: { url: string } };
99
-
100
- export type ResponsesContentPart =
101
- | { type: "input_text"; text: string }
102
- | { type: "input_image"; image_url: string };
103
-
104
- export type PromptBuilderChatResult = {
105
- provider: "oauth";
106
- model: string;
107
- message: { role: "assistant"; content: string };
108
- usage: Record<string, unknown> | null;
109
- };