ima2-gen 1.1.20 → 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 (239) hide show
  1. package/README.md +42 -26
  2. package/bin/commands/capabilities.js +2 -2
  3. package/bin/commands/defaults.js +2 -2
  4. package/bin/commands/doctor.js +3 -3
  5. package/bin/commands/edit.js +1 -1
  6. package/bin/commands/gen.js +1 -1
  7. package/bin/commands/grok.js +16 -11
  8. package/bin/commands/multimode.js +1 -1
  9. package/bin/commands/observability.js +2 -2
  10. package/bin/commands/video.js +335 -13
  11. package/bin/ima2.js +23 -13
  12. package/bin/lib/error-hints.js +2 -2
  13. package/bin/lib/platform.js +34 -5
  14. package/docs/API.md +112 -3
  15. package/docs/CLI.md +61 -7
  16. package/docs/FAQ.ko.md +15 -20
  17. package/docs/FAQ.md +14 -19
  18. package/docs/NPX_QUICKSTART.md +40 -0
  19. package/docs/PROMPT_STUDIO.ko.md +1 -1
  20. package/docs/PROMPT_STUDIO.md +1 -1
  21. package/docs/README.ja.md +6 -16
  22. package/docs/README.ko.md +35 -14
  23. package/docs/README.zh-CN.md +7 -17
  24. package/docs/migration/runtime-test-inventory.md +8 -1
  25. package/lib/agentQueueWorker.js +6 -0
  26. package/lib/agentRuntime.js +20 -5
  27. package/lib/atomicWrite.js +14 -0
  28. package/lib/capabilities.js +1 -1
  29. package/lib/generationErrors.js +1 -1
  30. package/lib/grokProxyLauncher.js +31 -6
  31. package/lib/grokVideoAdapter.js +18 -89
  32. package/lib/grokVideoCanvas.js +25 -0
  33. package/lib/grokVideoDownload.js +58 -0
  34. package/lib/grokVideoPlannerPrompt.js +64 -0
  35. package/lib/historyList.js +7 -1
  36. package/lib/inflight.js +1 -1
  37. package/lib/oauthLauncher.js +26 -6
  38. package/lib/videoContinuity.js +149 -0
  39. package/lib/videoFrameExtract.js +80 -0
  40. package/node_modules/progrok/dist/index.js +187 -88
  41. package/node_modules/progrok/dist/index.js.map +1 -1
  42. package/node_modules/progrok/package.json +1 -1
  43. package/node_modules/progrok/skills/progrok/SKILL.md +33 -4
  44. package/package.json +6 -8
  45. package/routes/edit.js +2 -1
  46. package/routes/generate.js +4 -3
  47. package/routes/health.js +4 -3
  48. package/routes/index.js +4 -0
  49. package/routes/multimode.js +2 -1
  50. package/routes/quota.js +66 -0
  51. package/routes/video.js +80 -16
  52. package/routes/videoExtended.js +293 -0
  53. package/server.js +35 -4
  54. package/skills/ima2/SKILL.md +320 -7
  55. package/ui/dist/.vite/manifest.json +12 -12
  56. package/ui/dist/assets/{AgentWorkspace-DS8uvoLI.js → AgentWorkspace-COxQ5TjU.js} +2 -2
  57. package/ui/dist/assets/{CardNewsWorkspace-CYxMsE67.js → CardNewsWorkspace-B0OkcuVz.js} +1 -1
  58. package/ui/dist/assets/{NodeCanvas-DccIc347.js → NodeCanvas-BSsclEBh.js} +1 -1
  59. package/ui/dist/assets/{PromptBuilderPanel-BvxxwSJp.js → PromptBuilderPanel-DpC9A5Rz.js} +1 -1
  60. package/ui/dist/assets/{PromptImportDialog-u1_BFDRd.js → PromptImportDialog-CVwT0rLd.js} +2 -2
  61. package/ui/dist/assets/{PromptImportDiscoverySection-C5uvkVSz.js → PromptImportDiscoverySection-BDCkRCRs.js} +1 -1
  62. package/ui/dist/assets/{PromptImportFolderSection-D3E_O1SD.js → PromptImportFolderSection-QoKbZD83.js} +1 -1
  63. package/ui/dist/assets/{PromptLibraryPanel-4gyf9CB9.js → PromptLibraryPanel-BhFgeKnY.js} +2 -2
  64. package/ui/dist/assets/SettingsWorkspace-CfjrlH5R.js +1 -0
  65. package/ui/dist/assets/index-C-mur7pa.css +1 -0
  66. package/ui/dist/assets/index-CCP5nUOj.js +42 -0
  67. package/ui/dist/assets/{index-DoKtXbod.js → index-Cxhzi3bs.js} +1 -1
  68. package/ui/dist/index.html +2 -2
  69. package/vendor/progrok-0.2.0.tgz +0 -0
  70. package/bin/commands/annotate.ts +0 -119
  71. package/bin/commands/cancel.ts +0 -48
  72. package/bin/commands/canvas-versions.ts +0 -80
  73. package/bin/commands/capabilities.ts +0 -110
  74. package/bin/commands/cardnews.ts +0 -249
  75. package/bin/commands/comfy.ts +0 -54
  76. package/bin/commands/config.ts +0 -186
  77. package/bin/commands/defaults.ts +0 -192
  78. package/bin/commands/doctor.ts +0 -202
  79. package/bin/commands/edit.ts +0 -150
  80. package/bin/commands/gen.ts +0 -214
  81. package/bin/commands/grok.ts +0 -85
  82. package/bin/commands/history.ts +0 -146
  83. package/bin/commands/ls.ts +0 -64
  84. package/bin/commands/metadata.ts +0 -39
  85. package/bin/commands/multimode.ts +0 -196
  86. package/bin/commands/node.ts +0 -166
  87. package/bin/commands/observability.ts +0 -176
  88. package/bin/commands/ping.ts +0 -31
  89. package/bin/commands/prompt-sub/build.ts +0 -101
  90. package/bin/commands/prompt.ts +0 -492
  91. package/bin/commands/ps.ts +0 -81
  92. package/bin/commands/session.ts +0 -266
  93. package/bin/commands/show.ts +0 -72
  94. package/bin/commands/skill.ts +0 -70
  95. package/bin/commands/video.ts +0 -205
  96. package/bin/ima2.ts +0 -430
  97. package/bin/lib/args.ts +0 -92
  98. package/bin/lib/browser-id.ts +0 -16
  99. package/bin/lib/client.ts +0 -122
  100. package/bin/lib/config-store.ts +0 -120
  101. package/bin/lib/destructive-confirm.ts +0 -19
  102. package/bin/lib/doctor-checks.ts +0 -91
  103. package/bin/lib/error-hints.ts +0 -23
  104. package/bin/lib/files.ts +0 -39
  105. package/bin/lib/output.ts +0 -73
  106. package/bin/lib/platform.ts +0 -99
  107. package/bin/lib/recover-output.ts +0 -139
  108. package/bin/lib/sse.ts +0 -73
  109. package/bin/lib/star-prompt.ts +0 -97
  110. package/bin/lib/storage-doctor.ts +0 -39
  111. package/bin/lib/ui-build.ts +0 -85
  112. package/config.ts +0 -354
  113. package/lib/agentCommandParser.ts +0 -69
  114. package/lib/agentGenerationPlanner.ts +0 -273
  115. package/lib/agentQuestionResponder.ts +0 -266
  116. package/lib/agentQueueStore.ts +0 -270
  117. package/lib/agentQueueWorker.ts +0 -89
  118. package/lib/agentRuntime.ts +0 -592
  119. package/lib/agentSettings.ts +0 -72
  120. package/lib/agentStore.ts +0 -422
  121. package/lib/agentStoreRows.ts +0 -136
  122. package/lib/agentTypes.ts +0 -154
  123. package/lib/apiCachePolicy.ts +0 -11
  124. package/lib/assetLifecycle.ts +0 -146
  125. package/lib/canvasVersionStore.ts +0 -223
  126. package/lib/capabilities.ts +0 -126
  127. package/lib/cardNewsGenerator.ts +0 -271
  128. package/lib/cardNewsJobStore.ts +0 -142
  129. package/lib/cardNewsManifestStore.ts +0 -154
  130. package/lib/cardNewsPlanner.ts +0 -236
  131. package/lib/cardNewsPlannerClient.ts +0 -155
  132. package/lib/cardNewsPlannerPrompt.ts +0 -62
  133. package/lib/cardNewsPlannerSchema.ts +0 -321
  134. package/lib/cardNewsRoleTemplateStore.ts +0 -47
  135. package/lib/cardNewsTemplateStore.ts +0 -252
  136. package/lib/codexDetect.ts +0 -71
  137. package/lib/comfyBridge.ts +0 -235
  138. package/lib/composerSnapshot.ts +0 -33
  139. package/lib/configKeys.ts +0 -62
  140. package/lib/db.ts +0 -295
  141. package/lib/errInfo.ts +0 -43
  142. package/lib/errorClassify.ts +0 -100
  143. package/lib/generationCancel.ts +0 -28
  144. package/lib/generationErrors.ts +0 -238
  145. package/lib/grokImageAdapter.ts +0 -513
  146. package/lib/grokMultimodeAdapter.ts +0 -84
  147. package/lib/grokProxyLauncher.ts +0 -129
  148. package/lib/grokRuntime.ts +0 -23
  149. package/lib/grokSizeMapper.ts +0 -71
  150. package/lib/grokVideoAdapter.ts +0 -519
  151. package/lib/historyIndex.ts +0 -51
  152. package/lib/historyList.ts +0 -177
  153. package/lib/imageMetadata.ts +0 -113
  154. package/lib/imageMetadataStore.ts +0 -67
  155. package/lib/imageModels.ts +0 -165
  156. package/lib/inflight.ts +0 -281
  157. package/lib/localImportStore.ts +0 -114
  158. package/lib/logger.ts +0 -161
  159. package/lib/nodeStore.ts +0 -91
  160. package/lib/oauthLauncher.ts +0 -78
  161. package/lib/oauthNormalize.ts +0 -30
  162. package/lib/oauthProxy/errors.ts +0 -128
  163. package/lib/oauthProxy/generators.ts +0 -494
  164. package/lib/oauthProxy/index.ts +0 -28
  165. package/lib/oauthProxy/prompts.ts +0 -123
  166. package/lib/oauthProxy/references.ts +0 -45
  167. package/lib/oauthProxy/runtime.ts +0 -115
  168. package/lib/oauthProxy/streams.ts +0 -232
  169. package/lib/oauthProxy/types.ts +0 -9
  170. package/lib/oauthProxy.ts +0 -3
  171. package/lib/openDirectory.ts +0 -47
  172. package/lib/pngInfo.ts +0 -26
  173. package/lib/promptBuilder/attachments.ts +0 -74
  174. package/lib/promptBuilder/client.ts +0 -130
  175. package/lib/promptBuilder/constants.ts +0 -9
  176. package/lib/promptBuilder/context.ts +0 -36
  177. package/lib/promptBuilder/errors.ts +0 -12
  178. package/lib/promptBuilder/requestSchema.ts +0 -56
  179. package/lib/promptBuilder/responseParser.ts +0 -219
  180. package/lib/promptBuilder/systemPrompt.ts +0 -135
  181. package/lib/promptBuilder/transport.ts +0 -94
  182. package/lib/promptBuilder/types.ts +0 -109
  183. package/lib/promptImport/curatedSources.ts +0 -141
  184. package/lib/promptImport/discoveryRegistry.ts +0 -329
  185. package/lib/promptImport/errors.ts +0 -18
  186. package/lib/promptImport/githubDiscovery.ts +0 -309
  187. package/lib/promptImport/githubFolder.ts +0 -397
  188. package/lib/promptImport/githubSource.ts +0 -257
  189. package/lib/promptImport/gptImageHints.ts +0 -70
  190. package/lib/promptImport/parsePromptCandidates.ts +0 -179
  191. package/lib/promptImport/promptIndex.ts +0 -326
  192. package/lib/promptImport/rankPromptCandidates.ts +0 -65
  193. package/lib/promptImport/types.ts +0 -103
  194. package/lib/promptSafetyPolicy.ts +0 -5
  195. package/lib/providerOptions.ts +0 -56
  196. package/lib/referenceImageCompress.ts +0 -84
  197. package/lib/refs.ts +0 -133
  198. package/lib/requestLogger.ts +0 -49
  199. package/lib/responsesDoctor.ts +0 -456
  200. package/lib/responsesErrors.ts +0 -83
  201. package/lib/responsesFallback.ts +0 -114
  202. package/lib/responsesImageAdapter.ts +0 -466
  203. package/lib/responsesParse.ts +0 -452
  204. package/lib/responsesTools.ts +0 -28
  205. package/lib/runtimeContext.ts +0 -146
  206. package/lib/runtimePorts.ts +0 -105
  207. package/lib/sessionStore.ts +0 -308
  208. package/lib/storageMigration.ts +0 -310
  209. package/lib/styleSheet.ts +0 -139
  210. package/lib/systemTrash.ts +0 -20
  211. package/lib/videoSeriesChain.ts +0 -29
  212. package/lib/visibleTextLanguagePolicy.ts +0 -7
  213. package/routes/agent.ts +0 -308
  214. package/routes/annotations.ts +0 -118
  215. package/routes/canvasVersions.ts +0 -69
  216. package/routes/capabilities.ts +0 -18
  217. package/routes/cardNews.ts +0 -211
  218. package/routes/comfy.ts +0 -43
  219. package/routes/edit.ts +0 -352
  220. package/routes/generate.ts +0 -492
  221. package/routes/grok.ts +0 -24
  222. package/routes/health.ts +0 -123
  223. package/routes/history.ts +0 -221
  224. package/routes/imageImport.ts +0 -37
  225. package/routes/index.ts +0 -48
  226. package/routes/metadata.ts +0 -77
  227. package/routes/multimode.ts +0 -499
  228. package/routes/nodes.ts +0 -578
  229. package/routes/promptBuilder.ts +0 -37
  230. package/routes/promptImport.ts +0 -379
  231. package/routes/prompts.ts +0 -428
  232. package/routes/sessions.ts +0 -317
  233. package/routes/storage.ts +0 -47
  234. package/routes/video.ts +0 -232
  235. package/server.ts +0 -290
  236. package/ui/dist/assets/SettingsWorkspace-F3eNu3mJ.js +0 -1
  237. package/ui/dist/assets/index-B6tcw_UF.css +0 -1
  238. package/ui/dist/assets/index-DYOh6gQD.js +0 -32
  239. package/vendor/progrok-0.1.1.tgz +0 -0
@@ -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
- };