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,326 +0,0 @@
1
- import { createHash } from "node:crypto";
2
- import { mkdir, readFile, rename, writeFile } from "node:fs/promises";
3
- import { dirname } from "node:path";
4
- import { getCuratedSource, getDefaultSearchSources, listCuratedSources } from "./curatedSources.js";
5
- import { buildGitHubRawFileSource, fetchGitHubSource } from "./githubSource.js";
6
- import { parsePromptCandidates } from "./parsePromptCandidates.js";
7
- import { extractGptImageHints } from "./gptImageHints.js";
8
- import { rankPromptCandidates } from "./rankPromptCandidates.js";
9
- import { errInfo } from "../errInfo.js";
10
- import { requireRuntimeContext } from "../runtimeContext.js";
11
- import {
12
- getDefaultReviewedDiscoverySources,
13
- getReviewedDiscoverySource,
14
- listReviewedDiscoverySources,
15
- } from "./discoveryRegistry.js";
16
- import type {
17
- CuratedSourceLike,
18
- GitHubFileSource,
19
- PromptCandidate,
20
- PromptImportCtx,
21
- PromptImportLimits,
22
- } from "./types.js";
23
-
24
- const INDEX_VERSION = 1;
25
- const EXTRACTOR_VERSION = 2;
26
-
27
- interface IndexedFile {
28
- sourceFileId: string;
29
- owner: string | undefined;
30
- repo: string;
31
- ref: string;
32
- path: string;
33
- extension: string;
34
- contentHash: string;
35
- etag: string | null;
36
- sizeBytes: number;
37
- licenseSpdx: string;
38
- htmlUrl: string;
39
- indexedAt: string;
40
- lastFetchStatus: string;
41
- promptCandidateCount: number;
42
- extractorVersion: number;
43
- }
44
-
45
- interface IndexedCandidate extends PromptCandidate {
46
- candidateId: string;
47
- }
48
-
49
- interface CacheEntry {
50
- source: CuratedSourceLike;
51
- files: IndexedFile[];
52
- candidates: IndexedCandidate[];
53
- refreshedAt: number;
54
- }
55
-
56
- interface IndexCache {
57
- version: number;
58
- sources: Record<string, CacheEntry>;
59
- }
60
-
61
- interface IndexLimits extends PromptImportLimits {
62
- searchLimit: number;
63
- ttlMs: number;
64
- }
65
-
66
- function limitsFromCtx(ctx: PromptImportCtx): IndexLimits {
67
- const limits = (ctx.config?.limits ?? {}) as Record<string, number>;
68
- return {
69
- maxFileBytesForPreview: limits.promptImportMaxFileBytes,
70
- maxPromptCandidatesPerFile: limits.promptImportMaxCandidatesPerFile,
71
- maxPromptCandidatesPerImport: limits.promptImportMaxCandidatesPerImport,
72
- fetchTimeoutMs: limits.promptImportFetchTimeoutMs,
73
- maxCandidateChars: limits.promptImportMaxCandidateChars,
74
- minCandidateChars: limits.promptImportMinCandidateChars,
75
- maxSourceCharsScanned: limits.promptImportMaxSourceCharsScanned,
76
- maxRepoIndexFiles: limits.promptImportMaxRepoIndexFiles,
77
- maxFolderFiles: limits.promptImportMaxFolderFiles ?? 0,
78
- maxFolderPreviewFiles: limits.promptImportMaxFolderPreviewFiles ?? 0,
79
- searchLimit: limits.promptImportCuratedSearchLimit,
80
- ttlMs: limits.promptImportIndexCacheTtlMs,
81
- };
82
- }
83
-
84
- function cacheFile(ctx: PromptImportCtx): string {
85
- const storage = (ctx.config as { storage?: { promptImportIndexCacheFile?: string } } | undefined)?.storage;
86
- return storage?.promptImportIndexCacheFile ?? "";
87
- }
88
-
89
- function sourceFileId(source: CuratedSourceLike, path: string): string {
90
- return `github:${source.repo}@${source.defaultRef}:${path}`;
91
- }
92
-
93
- function hashId(...parts: string[]): string {
94
- return createHash("sha256").update(parts.join("\0")).digest("hex");
95
- }
96
-
97
- async function readCache(ctx: PromptImportCtx): Promise<IndexCache> {
98
- try {
99
- const parsed = JSON.parse(await readFile(cacheFile(ctx), "utf8")) as IndexCache;
100
- if (parsed.version !== INDEX_VERSION) return { version: INDEX_VERSION, sources: {} };
101
- return { version: INDEX_VERSION, sources: parsed.sources || {} };
102
- } catch {
103
- return { version: INDEX_VERSION, sources: {} };
104
- }
105
- }
106
-
107
- async function writeCache(ctx: PromptImportCtx, cache: IndexCache): Promise<void> {
108
- const file = cacheFile(ctx);
109
- await mkdir(dirname(file), { recursive: true });
110
- const tmp = `${file}.${process.pid}.${Date.now()}.tmp`;
111
- await writeFile(tmp, JSON.stringify(cache, null, 2));
112
- await rename(tmp, file);
113
- }
114
-
115
- function sourceTags(source: CuratedSourceLike, fileSource: GitHubFileSource): string[] {
116
- return [
117
- ...(fileSource.tags ?? []),
118
- `source:${source.id}`,
119
- `license:${source.licenseSpdx}`,
120
- `trust:${source.trustTier}`,
121
- source.requiresAttribution ? "attribution-required" : null,
122
- ].filter(Boolean) as string[];
123
- }
124
-
125
- interface IndexedCandidateInput {
126
- candidate: PromptCandidate;
127
- source: CuratedSourceLike;
128
- fileSource: GitHubFileSource;
129
- fileIndex: IndexedFile;
130
- index: number;
131
- }
132
-
133
- function indexedCandidate({ candidate, source, fileSource, fileIndex, index }: IndexedCandidateInput): IndexedCandidate {
134
- const scoreHints = extractGptImageHints(candidate.text);
135
- const headingPath = candidate.headingPath || candidate.name || "";
136
- const candidateId = hashId(fileIndex.sourceFileId, fileIndex.contentHash, headingPath, String(candidate.ordinal || index + 1));
137
- const tags = [...new Set([...(candidate.tags || []), ...sourceTags(source, fileSource)])];
138
- return {
139
- ...candidate,
140
- id: candidateId,
141
- candidateId,
142
- name: candidate.name,
143
- text: candidate.text,
144
- textPreview: candidate.textPreview || candidate.text.slice(0, 220),
145
- tags,
146
- warnings: [...new Set([...(candidate.warnings || []), ...(scoreHints.warnings ?? [])])],
147
- source: {
148
- kind: "github",
149
- owner: source.owner,
150
- repo: source.name,
151
- ref: source.defaultRef,
152
- path: fileSource.path,
153
- htmlUrl: fileSource.htmlUrl,
154
- sourceId: source.id,
155
- },
156
- sourceFileId: fileIndex.sourceFileId,
157
- headingPath,
158
- ordinal: candidate.ordinal || index + 1,
159
- promptHash: candidate.promptHash || hashId(candidate.text.trim().toLowerCase()),
160
- scoreHints,
161
- };
162
- }
163
-
164
- interface IndexSourceResult {
165
- source: CuratedSourceLike | null | undefined;
166
- indexedFiles: number;
167
- candidateCount: number;
168
- warnings: string[];
169
- entry?: CacheEntry;
170
- }
171
-
172
- async function indexSource(ctx: PromptImportCtx, sourceId: string): Promise<IndexSourceResult> {
173
- const source = (getCuratedSource(sourceId) as CuratedSourceLike | undefined) || await getReviewedDiscoverySource(ctx, sourceId);
174
- if (!source || source.trustTier === "manual-review") {
175
- return { source, indexedFiles: 0, candidateCount: 0, warnings: ["curated-source-unavailable"] };
176
- }
177
- if (String(source.defaultRef || "").includes("/")) {
178
- return { source, indexedFiles: 0, candidateCount: 0, warnings: ["discovery-default-branch-unsupported"] };
179
- }
180
- if (!Array.isArray(source.allowedPaths) || source.allowedPaths.length === 0) {
181
- return { source, indexedFiles: 0, candidateCount: 0, warnings: ["discovery-requires-paths"] };
182
- }
183
-
184
- const limits = limitsFromCtx(ctx);
185
- const warnings: string[] = [];
186
- const files: IndexedFile[] = [];
187
- const candidates: IndexedCandidate[] = [];
188
- const allowedPaths = source.allowedPaths.slice(0, limits.maxRepoIndexFiles);
189
-
190
- for (const path of allowedPaths) {
191
- try {
192
- const fileSource = buildGitHubRawFileSource({
193
- owner: source.owner ?? "",
194
- repo: source.name ?? source.repo,
195
- ref: source.defaultRef,
196
- path,
197
- });
198
- const fetched = await fetchGitHubSource(fileSource, limits);
199
- const fileIndex: IndexedFile = {
200
- sourceFileId: sourceFileId(source, path),
201
- owner: source.owner,
202
- repo: source.name ?? source.repo,
203
- ref: source.defaultRef,
204
- path,
205
- extension: fileSource.extension ?? "",
206
- contentHash: fetched.contentHash,
207
- etag: fetched.etag,
208
- sizeBytes: fetched.sizeBytes,
209
- licenseSpdx: source.licenseSpdx,
210
- htmlUrl: fileSource.htmlUrl ?? "",
211
- indexedAt: new Date().toISOString(),
212
- lastFetchStatus: "ok",
213
- promptCandidateCount: 0,
214
- extractorVersion: EXTRACTOR_VERSION,
215
- };
216
- const parsed = parsePromptCandidates({
217
- text: fetched.text,
218
- filename: path,
219
- source: { kind: "github", owner: source.owner, repo: source.name, ref: source.defaultRef, path, htmlUrl: fileSource.htmlUrl },
220
- tags: sourceTags(source, fileSource),
221
- limits,
222
- });
223
- const indexed = parsed.map((candidate, index) => indexedCandidate({ candidate, source, fileSource, fileIndex, index }));
224
- fileIndex.promptCandidateCount = indexed.length;
225
- files.push(fileIndex);
226
- candidates.push(...indexed);
227
- } catch (error) {
228
- const err = errInfo(error);
229
- warnings.push(`${path}: ${err.message || "index failed"}`);
230
- }
231
- }
232
-
233
- return {
234
- source,
235
- indexedFiles: files.length,
236
- candidateCount: candidates.length,
237
- warnings,
238
- entry: {
239
- source,
240
- files,
241
- candidates,
242
- refreshedAt: Date.now(),
243
- },
244
- };
245
- }
246
-
247
- function isFresh(entry: CacheEntry | undefined, ttlMs: number): boolean {
248
- return Boolean(entry?.refreshedAt && Date.now() - entry.refreshedAt < ttlMs);
249
- }
250
-
251
- async function ensureSearchCache(ctx: PromptImportCtx) {
252
- const cache = await readCache(ctx);
253
- const limits = limitsFromCtx(ctx);
254
- const sources = [
255
- ...getDefaultSearchSources() as CuratedSourceLike[],
256
- ...await getDefaultReviewedDiscoverySources(ctx),
257
- ];
258
- let changed = false;
259
- const warnings: string[] = [];
260
-
261
- for (const source of sources) {
262
- if (isFresh(cache.sources[source.id], limits.ttlMs)) continue;
263
- const result = await indexSource(ctx, source.id);
264
- if (result.entry) {
265
- cache.sources[source.id] = result.entry;
266
- changed = true;
267
- }
268
- warnings.push(...result.warnings);
269
- }
270
- if (changed) await writeCache(ctx, cache);
271
- return { cache, warnings };
272
- }
273
-
274
- export async function refreshCuratedSource(ctxIn: PromptImportCtx, sourceId: string) {
275
- const ctx = requireRuntimeContext(ctxIn);
276
- const cache = await readCache(ctx);
277
- const result = await indexSource(ctx, sourceId);
278
- if (result.entry) {
279
- cache.sources[sourceId] = result.entry;
280
- await writeCache(ctx, cache);
281
- }
282
- return {
283
- source: result.source,
284
- indexedFiles: result.indexedFiles,
285
- candidateCount: result.candidateCount,
286
- warnings: result.warnings,
287
- };
288
- }
289
-
290
- interface SearchCuratedPromptsOptions {
291
- q?: string;
292
- sourceIds?: string[];
293
- limit?: number;
294
- }
295
-
296
- export async function searchCuratedPrompts(ctxIn: PromptImportCtx, { q = "", sourceIds, limit }: SearchCuratedPromptsOptions = {}) {
297
- const ctx = requireRuntimeContext(ctxIn);
298
- const { cache, warnings } = await ensureSearchCache(ctx);
299
- const limits = limitsFromCtx(ctx);
300
- const defaultSources = [
301
- ...getDefaultSearchSources() as CuratedSourceLike[],
302
- ...await getDefaultReviewedDiscoverySources(ctx),
303
- ];
304
- const allowedIds = Array.isArray(sourceIds) && sourceIds.length
305
- ? new Set(sourceIds)
306
- : new Set(defaultSources.map((source) => source.id));
307
- const candidates = Object.values(cache.sources)
308
- .filter((entry) => allowedIds.has(entry.source.id))
309
- .flatMap((entry) => entry.candidates || []);
310
- const results = rankPromptCandidates({
311
- candidates,
312
- query: q,
313
- limit: Math.min(Number(limit) || limits.searchLimit, limits.searchLimit),
314
- });
315
- const sources = [
316
- ...listCuratedSources(),
317
- ...await listReviewedDiscoverySources(ctx),
318
- ];
319
- return { results, sources, warnings };
320
- }
321
-
322
- export async function getPromptImportSources(ctxIn: PromptImportCtx | null) {
323
- const ctx = ctxIn ? requireRuntimeContext(ctxIn) : null;
324
- const reviewed = ctx ? await listReviewedDiscoverySources(ctx) : [];
325
- return { sources: [...listCuratedSources(), ...reviewed] };
326
- }
@@ -1,65 +0,0 @@
1
- import type { PromptCandidate } from "./types.js";
2
-
3
- interface RankablePromptCandidate extends Partial<PromptCandidate> {
4
- id: string;
5
- name: string;
6
- text: string;
7
- sourceFileId?: string;
8
- score?: number;
9
- }
10
-
11
- interface RankPromptCandidatesOptions {
12
- candidates: RankablePromptCandidate[];
13
- query: string;
14
- limit?: number;
15
- }
16
-
17
- function tokenize(value: unknown): string[] {
18
- return String(value || "")
19
- .toLowerCase()
20
- .split(/[^a-z0-9가-힣-]+/i)
21
- .map((token) => token.trim())
22
- .filter(Boolean);
23
- }
24
-
25
- function includesAny(values: unknown[], terms: string[]): boolean {
26
- const haystack = values.map((value) => String(value || "").toLowerCase());
27
- return terms.some((term) => haystack.some((value) => value.includes(term)));
28
- }
29
-
30
- export function rankPromptCandidates({ candidates, query, limit }: RankPromptCandidatesOptions): RankablePromptCandidate[] {
31
- const terms = tokenize(query);
32
- const boundedLimit = Math.max(1, Math.min(Number(limit) || 50, 100));
33
- const ranked = candidates.map((candidate) => {
34
- const text = String(candidate.text || "").toLowerCase();
35
- const name = String(candidate.name || "").toLowerCase();
36
- const tags = Array.isArray(candidate.tags) ? candidate.tags : [];
37
- const hints = candidate.scoreHints || {};
38
- const hintValues: unknown[] = [
39
- ...(hints.modelHints || []),
40
- ...(hints.generationSurfaceHints || []),
41
- ...(hints.taskHints || []),
42
- ...(hints.sizeHints || []),
43
- ...(hints.qualityHints || []),
44
- ];
45
- let score = 0;
46
-
47
- if (terms.length === 0) score += 1;
48
- for (const term of terms) {
49
- if (name.includes(term)) score += 18;
50
- if (includesAny(tags, [term])) score += 12;
51
- if (includesAny(hintValues, [term])) score += 14;
52
- if (text.includes(term)) score += 5;
53
- if (String(candidate.sourceFileId || "").toLowerCase().includes(term)) score += 4;
54
- }
55
- if (tags.some((tag) => tag === "trust:curated")) score += 5;
56
- if (candidate.warnings?.length) score -= candidate.warnings.length * 3;
57
-
58
- return { ...candidate, score };
59
- });
60
-
61
- return ranked
62
- .filter((candidate) => terms.length === 0 || (candidate.score ?? 0) > 0)
63
- .sort((a, b) => (b.score ?? 0) - (a.score ?? 0) || String(a.name).localeCompare(String(b.name)))
64
- .slice(0, boundedLimit);
65
- }
@@ -1,103 +0,0 @@
1
- import type { RouteRuntimeContext } from "../runtimeContext.js";
2
-
3
- export type PromptImportCtx = RouteRuntimeContext;
4
-
5
- export interface PromptImportLimits {
6
- maxFileBytesForPreview: number;
7
- maxPromptCandidatesPerFile: number;
8
- maxPromptCandidatesPerImport: number;
9
- fetchTimeoutMs: number;
10
- maxCandidateChars: number;
11
- minCandidateChars: number;
12
- maxSourceCharsScanned: number;
13
- maxRepoIndexFiles?: number;
14
- searchLimit?: number;
15
- ttlMs?: number;
16
- maxFolderFiles?: number;
17
- maxFolderPreviewFiles?: number;
18
- }
19
-
20
- export interface PromptCandidateSource {
21
- kind: string;
22
- owner?: string;
23
- repo?: string;
24
- ref?: string;
25
- path?: string;
26
- htmlUrl?: string;
27
- sourceId?: string;
28
- filename?: string;
29
- }
30
-
31
- export interface PromptCandidateScoreHints {
32
- modelHints?: string[];
33
- generationSurfaceHints?: string[];
34
- taskHints?: string[];
35
- sizeHints?: string[];
36
- qualityHints?: string[];
37
- warnings?: string[];
38
- }
39
-
40
- export interface PromptCandidate {
41
- id: string;
42
- candidateId?: string;
43
- name: string;
44
- text: string;
45
- textPreview: string;
46
- tags: string[];
47
- warnings: string[];
48
- source: PromptCandidateSource;
49
- sourceFileId?: string;
50
- headingPath: string | null;
51
- ordinal: number;
52
- promptHash: string;
53
- scoreHints: PromptCandidateScoreHints;
54
- }
55
-
56
- export interface CuratedSourceLike {
57
- id: string;
58
- repo: string;
59
- owner?: string;
60
- name?: string;
61
- displayName?: string;
62
- defaultRef: string;
63
- allowedPaths: string[];
64
- extensions: string[];
65
- sourceType?: string;
66
- licenseSpdx: string;
67
- requiresAttribution?: boolean;
68
- trustTier: string;
69
- lastVerifiedAt?: string | null;
70
- notes?: string;
71
- searchSeeds?: string[];
72
- defaultSearch?: boolean;
73
- }
74
-
75
- export interface GitHubFileSource {
76
- kind?: string;
77
- owner?: string;
78
- repo?: string;
79
- ref?: string;
80
- path?: string;
81
- extension?: string;
82
- htmlUrl?: string;
83
- rawUrl: string;
84
- tags?: string[];
85
- }
86
-
87
- export interface DiscoveryRepo {
88
- full_name?: string;
89
- description?: string | null;
90
- topics?: string[];
91
- pushed_at?: string | null;
92
- stargazers_count?: number;
93
- forks_count?: number;
94
- open_issues_count?: number;
95
- updated_at?: string | null;
96
- license?: { spdx_id?: string | null } | null;
97
- archived?: boolean;
98
- disabled?: boolean;
99
- fork?: boolean;
100
- default_branch?: string | null;
101
- html_url?: string | null;
102
- language?: string | null;
103
- }
@@ -1,5 +0,0 @@
1
- export const SAFETY_INTENT_POLICY = [
2
- "* [Level of Intent to Sexual Exploitation]: Zero",
3
- "* [Level of Intent to Sexual Commodification]: Zero",
4
- "* [Judged by Appearance Alone]: Forbidden",
5
- ].join("\n");
@@ -1,56 +0,0 @@
1
- import type { RuntimeContext } from "./runtimeContext.js";
2
- import { normalizeImageModel, normalizeReasoningEffort, normalizeGrokImageModel } from "./imageModels.js";
3
-
4
- export function resolveProviderOptions(ctx: RuntimeContext | null | undefined, {
5
- provider = "oauth",
6
- rawModel,
7
- rawReasoningEffort,
8
- rawSize = "1024x1024",
9
- rawWebSearchEnabled = true,
10
- searchMode = "on",
11
- }: any = {}) {
12
- if (provider === "grok") {
13
- const grokCfg: { defaultImageModel?: string } = (ctx?.config as any)?.grokProvider || {};
14
- const modelInput = rawModel || grokCfg.defaultImageModel;
15
- const grokModelCheck = normalizeGrokImageModel(modelInput);
16
- if (grokModelCheck.error) return { error: grokModelCheck.error, code: grokModelCheck.code, status: grokModelCheck.status };
17
- return {
18
- provider: "grok" as const,
19
- model: grokModelCheck.model,
20
- reasoningEffort: "none",
21
- size: rawSize,
22
- webSearchEnabled: true,
23
- };
24
- }
25
-
26
- const activeProvider = provider === "api" ? "api" : "oauth";
27
- const apiConfig: { defaultImageModel?: string; defaultReasoningEffort?: string; defaultSize?: string; allowWebSearch?: boolean } = (ctx?.config as { apiProvider?: any })?.apiProvider || {};
28
- const modelInput = activeProvider === "api"
29
- ? (rawModel || apiConfig.defaultImageModel || "gpt-5.4-mini")
30
- : rawModel;
31
- const modelCheck = normalizeImageModel(ctx, modelInput);
32
- if (modelCheck.error) return { error: modelCheck.error, code: modelCheck.code, status: modelCheck.status };
33
-
34
- const reasoningInput = activeProvider === "api"
35
- ? (rawReasoningEffort || apiConfig.defaultReasoningEffort || "low")
36
- : rawReasoningEffort;
37
- const reasoningCheck = normalizeReasoningEffort(ctx, reasoningInput);
38
- if (reasoningCheck.error) {
39
- return { error: reasoningCheck.error, code: reasoningCheck.code, status: reasoningCheck.status };
40
- }
41
-
42
- const size = activeProvider === "api" && (typeof rawSize !== "string" || rawSize.length === 0)
43
- ? (apiConfig.defaultSize || "1024x1024")
44
- : rawSize;
45
- const webSearchEnabled = activeProvider === "api"
46
- ? apiConfig.allowWebSearch !== false && rawWebSearchEnabled !== false && searchMode !== "off"
47
- : rawWebSearchEnabled !== false && searchMode !== "off";
48
-
49
- return {
50
- provider: activeProvider,
51
- model: modelCheck.model,
52
- reasoningEffort: reasoningCheck.effort,
53
- size,
54
- webSearchEnabled,
55
- };
56
- }
@@ -1,84 +0,0 @@
1
- import sharp from "sharp";
2
-
3
- const DEFAULT_MAX_B64_BYTES = 6 * 1024 * 1024;
4
- const DEFAULT_MAX_EDGE = 3840;
5
- const DEFAULT_QUALITY_LADDER = [85, 75, 65, 55];
6
- const FALLBACK_MAX_EDGE = 2048;
7
- const FALLBACK_QUALITY_LADDER = [75, 65, 55];
8
-
9
- function stripDataUrlPrefix(value: unknown) {
10
- return String(value || "").replace(/^data:[^;]+;base64,/, "");
11
- }
12
-
13
- function toBase64(buffer: Buffer) {
14
- return buffer.toString("base64");
15
- }
16
-
17
- async function encodeJpegWithinBudget(input: Buffer, {
18
- maxB64Bytes,
19
- maxEdge,
20
- qualityLadder,
21
- }: { maxB64Bytes: number; maxEdge: number; qualityLadder: number[] }) {
22
- for (const quality of qualityLadder) {
23
- const out = await sharp(input, { failOn: "none" })
24
- .rotate()
25
- .resize({
26
- width: maxEdge,
27
- height: maxEdge,
28
- fit: "inside",
29
- withoutEnlargement: true,
30
- })
31
- .flatten({ background: "#ffffff" })
32
- .jpeg({ quality, progressive: true })
33
- .toBuffer();
34
- const b64 = toBase64(out);
35
- if (b64.length <= maxB64Bytes) return { b64, compressed: true, quality, maxEdge };
36
- }
37
- return null;
38
- }
39
-
40
- interface CompressOptions {
41
- maxB64Bytes?: number;
42
- maxEdge?: number;
43
- qualityLadder?: number[];
44
- fallbackMaxEdge?: number;
45
- fallbackQualityLadder?: number[];
46
- force?: boolean;
47
- }
48
-
49
- export async function compressReferenceB64ForOAuth(imageB64: string | undefined | null, options: CompressOptions = {}) {
50
- const rawB64 = stripDataUrlPrefix(imageB64);
51
- const maxB64Bytes = options.maxB64Bytes ?? DEFAULT_MAX_B64_BYTES;
52
- const maxEdge = options.maxEdge ?? DEFAULT_MAX_EDGE;
53
- const qualityLadder = options.qualityLadder ?? DEFAULT_QUALITY_LADDER;
54
- if (!rawB64) return { b64: rawB64, compressed: false, inputBytes: 0, outputBytes: 0 };
55
-
56
- const input = Buffer.from(rawB64, "base64");
57
- const inputBytes = rawB64.length;
58
- if (!options.force && inputBytes <= maxB64Bytes) {
59
- return { b64: rawB64, compressed: false, inputBytes, outputBytes: inputBytes };
60
- }
61
-
62
- const primary = await encodeJpegWithinBudget(input, {
63
- maxB64Bytes,
64
- maxEdge,
65
- qualityLadder,
66
- });
67
- if (primary) {
68
- return { ...primary, inputBytes, outputBytes: primary.b64.length };
69
- }
70
-
71
- const fallback = await encodeJpegWithinBudget(input, {
72
- maxB64Bytes,
73
- maxEdge: options.fallbackMaxEdge ?? FALLBACK_MAX_EDGE,
74
- qualityLadder: options.fallbackQualityLadder ?? FALLBACK_QUALITY_LADDER,
75
- });
76
- if (fallback) {
77
- return { ...fallback, inputBytes, outputBytes: fallback.b64.length };
78
- }
79
-
80
- const err = new Error(`Reference image remains above ${maxB64Bytes} base64 bytes after compression`) as Error & { code?: string; status?: number };
81
- err.code = "REF_TOO_LARGE";
82
- err.status = 400;
83
- throw err;
84
- }