mcp-relight-harmonize 1.0.1 → 1.0.3

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.
@@ -0,0 +1,350 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.buildDynamicDiagnostics = buildDynamicDiagnostics;
7
+ exports.extractLayersImpl = extractLayersImpl;
8
+ const fs_1 = __importDefault(require("fs"));
9
+ const path_1 = __importDefault(require("path"));
10
+ const image_io_1 = require("./image_io");
11
+ const optical_analyzer_1 = require("./optical_analyzer");
12
+ const security_1 = require("../core/security");
13
+ function buildDynamicDiagnostics(cctKelvin, azimuthDeg, elevationDeg, hlPct, shPct, aoPct, meanGradient, meanSaturation, userIntent) {
14
+ const findings = [];
15
+ const tailoredOptions = [];
16
+ // 1. Thermal & Chromatic Diagnostics
17
+ let thermalDesc = "";
18
+ if (cctKelvin < 3800) {
19
+ thermalDesc = `طيف لوني دافئ جداً (${Math.round(cctKelvin)}K - Tungsten/Golden Hour)`;
20
+ findings.push(`🔥 **انحياز طيفي دافئ**: الصورة مسجلة بحرارة \`${Math.round(cctKelvin)}K\` مع غلبة للأطياف الكهرمانية والبرتقالية في القنوات الضوئية.`);
21
+ tailoredOptions.push(`موازنة حرارة الألوان من \`${Math.round(cctKelvin)}K\` إلى 5500K نهارية محايدة لإزالة المسحة الكهرمانية.`);
22
+ }
23
+ else if (cctKelvin > 6500) {
24
+ thermalDesc = `طيف لوني بارد (${Math.round(cctKelvin)}K - Cool Atmospheric Skylight)`;
25
+ findings.push(`❄️ **انحياز طيفي بارد**: الصورة مسجلة بحرارة \`${Math.round(cctKelvin)}K\` مع غلبة للزرقة والارتداد السماوي البارد.`);
26
+ tailoredOptions.push(`تدفئة المشهد الضوئي برفع حرارة الألوان إلى 3200K (Mood Tungsten) أو 4500K سينمائي.`);
27
+ }
28
+ else {
29
+ thermalDesc = `طيف نهاري متوازن (${Math.round(cctKelvin)}K - Balanced Daylight)`;
30
+ findings.push(`☀️ **حرارة ألوان متوازنة**: حرارة الألوان عند \`${Math.round(cctKelvin)}K\` تماثل الإضاءة الاستوديوية المتوازنة.`);
31
+ }
32
+ // 2. Lighting Direction & Dynamic Contrast
33
+ const lightDir = (azimuthDeg >= 0 && azimuthDeg < 90) || (azimuthDeg >= 270 && azimuthDeg <= 360) ? "يمين" : "يسار";
34
+ const lightVert = elevationDeg > 50 ? "علوية" : "أفقية جانبية";
35
+ findings.push(`💡 **توجيه الإضاءة الرئيسية**: زاوية السمت \`${Math.round(azimuthDeg)}°\` (إضاءة من جهة ال${lightDir}) مع زاوية ارتفاع \`${Math.round(elevationDeg)}°\` (${lightVert}).`);
36
+ if (shPct > 35.0 && hlPct > 15.0) {
37
+ findings.push(`⚡ **تباين درامي عالي (Chiaroscuro)**: كثافة الظلال \`${shPct.toFixed(1)}%\` مع مساحة ساطعة \`${hlPct.toFixed(1)}%\` تدل على تباين قوي بين المفتاح الضوئي والملء.`);
38
+ tailoredOptions.push("تنعيم التباين ورفع تفاصيل الظلال المغلقة عبر وضع الإضاءة المحيطية (Ambient Fill +0.8 EV).");
39
+ }
40
+ else if (shPct < 12.0 && hlPct < 12.0) {
41
+ findings.push("🌫️ **إضاءة منبسطة ناعمة (Flat Diffuse)**: تباين منخفض وغياب للمناطق الساطعة الحادة، ما يعطي مظهراً هادئاً ومنبسطاً.");
42
+ tailoredOptions.push("إضافة عمق درامي وزيادة التباين بنمط Chiaroscuro عالي التحديد مع إضاءة اتجاهية بارزة.");
43
+ }
44
+ // 3. Grounding & Ambient Occlusion
45
+ if (aoPct < 2.0) {
46
+ findings.push(`⚠️ **فقدان الارتكاز الأرضي (Lack of Grounding)**: نسبة الظلال التلامسية العميقة \`${aoPct.toFixed(2)}%\` تكاد تنعدم، مما قد يظهر العنصر كأنه طافٍ في الفراغ.`);
47
+ tailoredOptions.push("بناء وتثبيت ظل تلامسي أرضي فيزيائي (Contact Shadow Footprint) أسفل أدنى نقطة ارتكاز لمنع الظهور الطافي.");
48
+ }
49
+ else {
50
+ findings.push(`⚓ **ارتكاز أرضي متماسك**: نسبة ظلال التلامس والانغلاق الموضعي \`${aoPct.toFixed(1)}%\` تؤمن التصاقاً بصرياً طبيعياً بالأرضية.`);
51
+ }
52
+ // 4. Micro-texture & Edges
53
+ if (meanGradient > 0.03) {
54
+ findings.push(`🔍 **تفاصيل سطحية دقيقة وحواف حادة**: متوسط تباين سوبل \`${meanGradient.toFixed(4)}\` يشير إلى وفرة في التفاصيل المجهرية والأنسجة السطحية الواضحة.`);
55
+ }
56
+ else {
57
+ findings.push(`🎨 **حواف ناعمة وسطح انسيابي**: متوسط تدرج سوبل \`${meanGradient.toFixed(4)}\` يشير إلى مساحات ناعمة متصلة ومناسبة للتنعيم وإعادة التوزيع.`);
58
+ }
59
+ // 5. Chroma / Saturation
60
+ if (meanSaturation > 0.4) {
61
+ findings.push(`🌈 **تشبع لوني مكثف**: متوسط التشبع \`${meanSaturation.toFixed(3)}\` يظهر كثافة لونية حيوية في البكسلات.`);
62
+ }
63
+ else {
64
+ findings.push(`🔘 **لوحة لونية هادئة أو معتدلة**: متوسط التشبع \`${meanSaturation.toFixed(3)}\` يعكس تدرجات رصينة غير مبالغ بها.`);
65
+ }
66
+ // User intent or default options
67
+ if (userIntent) {
68
+ tailoredOptions.unshift(`تطبيق طلبك المخصص فوراً: "${userIntent}" بتطابق فيزيائي دقيق مع بيانات الطبقات الست.`);
69
+ }
70
+ else {
71
+ tailoredOptions.push("إعادة إضاءة بنمط هالة الحواف (Rim Light Halo +1.2 EV) لإبراز حدود المجسم وعزله عن الخلفية.");
72
+ tailoredOptions.push("دمج العنصر في خلفية جديدة مع مطابقة إحصائيات الألوان ودرجة الحرارة وظلال الارتكاز.");
73
+ }
74
+ const intentClause = userIntent ? `, ${userIntent}` : "";
75
+ const gptPrompt = `A master-quality studio photograph${intentClause}, calibrated optical lighting at ${Math.round(azimuthDeg)}° azimuth ` +
76
+ `and ${Math.round(elevationDeg)}° elevation, authentic ${Math.round(cctKelvin)}K color temperature balance, ` +
77
+ `physically-grounded ambient occlusion contact shadows firmly anchoring the base plane, ` +
78
+ `crisp micro-surface geometry (Sobel roughness index ${meanGradient.toFixed(3)}), ` +
79
+ `smooth luminance falloff and authentic subsurface scattering, 85mm prime lens f/2.0.`;
80
+ const nanoPrompt = `optics relight, cct ${Math.round(cctKelvin)}K, light vector azimuth ${Math.round(azimuthDeg)} deg elevation ${Math.round(elevationDeg)} deg, ` +
81
+ `surface roughness ${meanGradient.toFixed(4)}, saturation index ${meanSaturation.toFixed(3)}, ` +
82
+ `ground contact occlusion caster, volumetric photon bounce, high-key rim highlight accents, ` +
83
+ `denoising strength 0.38${intentClause}`;
84
+ return {
85
+ thermalDescription: thermalDesc,
86
+ findings,
87
+ tailoredOptions,
88
+ gptImagePrompt: gptPrompt,
89
+ nanoBananaPrompt: nanoPrompt,
90
+ };
91
+ }
92
+ function extractLayersImpl(imagePath, outputDir = "Layers", userIntent) {
93
+ const resolvedImagePath = (0, security_1.validateImagePath)(imagePath);
94
+ const resolvedOutputDir = path_1.default.resolve(outputDir);
95
+ if (!fs_1.default.existsSync(resolvedOutputDir)) {
96
+ fs_1.default.mkdirSync(resolvedOutputDir, { recursive: true });
97
+ }
98
+ const raw = (0, image_io_1.readImage)(resolvedImagePath);
99
+ const { width, height, data } = raw;
100
+ const numPixels = width * height;
101
+ const lumArray = new Float32Array(numPixels);
102
+ let sumR = 0;
103
+ let sumG = 0;
104
+ let sumB = 0;
105
+ let sumSat = 0;
106
+ for (let i = 0; i < numPixels; i++) {
107
+ const idx = i * 4;
108
+ const r = data[idx];
109
+ const g = data[idx + 1];
110
+ const b = data[idx + 2];
111
+ sumR += r;
112
+ sumG += g;
113
+ sumB += b;
114
+ const lum = 0.2126 * r + 0.7152 * g + 0.0722 * b;
115
+ lumArray[i] = lum / 255.0;
116
+ const maxC = Math.max(r, g, b);
117
+ const minC = Math.min(r, g, b);
118
+ const chroma = maxC - minC;
119
+ const sat = maxC > 0 ? chroma / maxC : 0;
120
+ sumSat += sat;
121
+ }
122
+ const meanR = sumR / numPixels;
123
+ const meanG = sumG / numPixels;
124
+ const meanB = sumB / numPixels;
125
+ const meanLum = 0.2126 * meanR + 0.7152 * meanG + 0.0722 * meanB;
126
+ const meanSaturation = sumSat / numPixels;
127
+ const cctKelvin = (0, optical_analyzer_1.calculateCctFromRgb)(meanR, meanG, meanB);
128
+ const { roughness, lightVector, angles } = (0, optical_analyzer_1.computeSurfaceNormalsAndLightVector)(lumArray, width, height);
129
+ const bufHighlights = Buffer.alloc(numPixels * 4);
130
+ const bufShadows = Buffer.alloc(numPixels * 4);
131
+ const bufAO = Buffer.alloc(numPixels * 4);
132
+ const bufEdges = Buffer.alloc(numPixels * 4);
133
+ const bufNormals = Buffer.alloc(numPixels * 4);
134
+ const bufChroma = Buffer.alloc(numPixels * 4);
135
+ let highlightsCount = 0;
136
+ let shadowsCount = 0;
137
+ let aoCount = 0;
138
+ let edgeSum = 0;
139
+ const scale = 6.0;
140
+ for (let y = 0; y < height; y++) {
141
+ for (let x = 0; x < width; x++) {
142
+ const idx = y * width + x;
143
+ const pIdx = idx * 4;
144
+ const r = data[pIdx];
145
+ const g = data[pIdx + 1];
146
+ const b = data[pIdx + 2];
147
+ const lum = lumArray[idx] * 255.0;
148
+ // 1. Highlights
149
+ if (lum > 170)
150
+ highlightsCount++;
151
+ const hlMask = Math.min(Math.max((lum - 170.0) / 75.0, 0.0), 1.0);
152
+ bufHighlights[pIdx] = Math.round(r * hlMask);
153
+ bufHighlights[pIdx + 1] = Math.round(g * hlMask);
154
+ bufHighlights[pIdx + 2] = Math.round(b * hlMask);
155
+ bufHighlights[pIdx + 3] = 255;
156
+ // 2. Shadows
157
+ if (lum < 85)
158
+ shadowsCount++;
159
+ const shMask = Math.min(Math.max((95.0 - lum) / 80.0, 0.0), 1.0);
160
+ bufShadows[pIdx] = Math.round(r * shMask);
161
+ bufShadows[pIdx + 1] = Math.round(g * shMask);
162
+ bufShadows[pIdx + 2] = Math.round(b * shMask);
163
+ bufShadows[pIdx + 3] = 255;
164
+ // 3. Deep Ambient Occlusion
165
+ if (lum < 35)
166
+ aoCount++;
167
+ const aoMask = Math.min(Math.max((40.0 - lum) / 40.0, 0.0), 1.0);
168
+ bufAO[pIdx] = Math.round((1.0 - aoMask) * 230.0);
169
+ bufAO[pIdx + 1] = Math.round((1.0 - aoMask) * 240.0 + aoMask * 15.0);
170
+ bufAO[pIdx + 2] = Math.round((1.0 - aoMask) * 255.0 + aoMask * 30.0);
171
+ bufAO[pIdx + 3] = 255;
172
+ // 4. Edges via Sobel
173
+ let gx = 0;
174
+ let gy = 0;
175
+ if (x > 0 && x < width - 1 && y > 0 && y < height - 1) {
176
+ gx =
177
+ -lumArray[(y - 1) * width + (x - 1)] +
178
+ lumArray[(y - 1) * width + (x + 1)] -
179
+ 2 * lumArray[y * width + (x - 1)] +
180
+ 2 * lumArray[y * width + (x + 1)] -
181
+ lumArray[(y + 1) * width + (x - 1)] +
182
+ lumArray[(y + 1) * width + (x + 1)];
183
+ gy =
184
+ -lumArray[(y - 1) * width + (x - 1)] -
185
+ 2 * lumArray[(y - 1) * width + x] -
186
+ lumArray[(y - 1) * width + (x + 1)] +
187
+ lumArray[(y + 1) * width + (x - 1)] +
188
+ 2 * lumArray[(y + 1) * width + x] +
189
+ lumArray[(y + 1) * width + (x + 1)];
190
+ }
191
+ const edgeMag = Math.sqrt(gx * gx + gy * gy);
192
+ edgeSum += edgeMag;
193
+ const edgeVal = Math.min(Math.round(edgeMag * 4.0 * 255.0), 255);
194
+ bufEdges[pIdx] = edgeVal;
195
+ bufEdges[pIdx + 1] = edgeVal;
196
+ bufEdges[pIdx + 2] = edgeVal;
197
+ bufEdges[pIdx + 3] = 255;
198
+ // 5. Depth Normals
199
+ const nx = -gx * scale;
200
+ const ny = -gy * scale;
201
+ const nz = 1.0;
202
+ const mag = Math.sqrt(nx * nx + ny * ny + nz * nz) || 1e-6;
203
+ const normX = nx / mag;
204
+ const normY = ny / mag;
205
+ const normZ = nz / mag;
206
+ bufNormals[pIdx] = Math.round((normX * 0.5 + 0.5) * 255);
207
+ bufNormals[pIdx + 1] = Math.round((normY * 0.5 + 0.5) * 255);
208
+ bufNormals[pIdx + 2] = Math.round((normZ * 0.5 + 0.5) * 255);
209
+ bufNormals[pIdx + 3] = 255;
210
+ // 6. Chroma / Saturation
211
+ const maxC = Math.max(r, g, b);
212
+ const minC = Math.min(r, g, b);
213
+ const chroma = maxC - minC;
214
+ const sat = maxC > 0 ? chroma / maxC : 0;
215
+ bufChroma[pIdx] = Math.min(Math.round(sat * 255.0 * 1.5), 255);
216
+ bufChroma[pIdx + 1] = Math.min(Math.round((1.0 - Math.abs(sat - 0.5) * 2.0) * 220.0), 255);
217
+ bufChroma[pIdx + 2] = Math.min(Math.round((1.0 - sat) * 200.0), 255);
218
+ bufChroma[pIdx + 3] = 255;
219
+ }
220
+ }
221
+ const hlPath = path_1.default.join(resolvedOutputDir, "01_highlights.png");
222
+ const shPath = path_1.default.join(resolvedOutputDir, "02_shadows.png");
223
+ const aoPath = path_1.default.join(resolvedOutputDir, "03_ambient_occlusion.png");
224
+ const edPath = path_1.default.join(resolvedOutputDir, "04_edges.png");
225
+ const normPath = path_1.default.join(resolvedOutputDir, "05_depth_normals.png");
226
+ const chrPath = path_1.default.join(resolvedOutputDir, "06_chroma_saturation.png");
227
+ (0, image_io_1.writeImage)(hlPath, { width, height, data: bufHighlights });
228
+ (0, image_io_1.writeImage)(shPath, { width, height, data: bufShadows });
229
+ (0, image_io_1.writeImage)(aoPath, { width, height, data: bufAO });
230
+ (0, image_io_1.writeImage)(edPath, { width, height, data: bufEdges });
231
+ (0, image_io_1.writeImage)(normPath, { width, height, data: bufNormals });
232
+ (0, image_io_1.writeImage)(chrPath, { width, height, data: bufChroma });
233
+ const hlPct = (highlightsCount / numPixels) * 100.0;
234
+ const shPct = (shadowsCount / numPixels) * 100.0;
235
+ const aoPct = (aoCount / numPixels) * 100.0;
236
+ const meanEdge = edgeSum / numPixels;
237
+ // Build Dynamic Diagnostics
238
+ const diagnostics = buildDynamicDiagnostics(cctKelvin, angles.azimuthDeg, angles.elevationDeg, hlPct, shPct, aoPct, meanEdge, meanSaturation, userIntent);
239
+ const layerMdPath = path_1.default.join(resolvedOutputDir, "Layer.md");
240
+ const toForwardSlash = (p) => p.replace(/\\/g, "/");
241
+ const findingsRendered = diagnostics.findings.join("\n\n");
242
+ const optionsRendered = diagnostics.tailoredOptions.map((opt, idx) => `- **خيار ${idx + 1}**: ${opt}`).join("\n");
243
+ const userIntentHeader = userIntent ? `\n**الهدف المخصص المطلوب**: \`${userIntent}\`\n` : "";
244
+ const mdContent = `# تقرير الطبقات التحليلية الست (Layer.md)
245
+ **مصدر الصورة**: \`${resolvedImagePath}\`
246
+ **أبعاد الصورة**: \`${width}x${height}\` بكسل
247
+ **التصنيف الضوئي المكتشف**: \`${diagnostics.thermalDescription}\`
248
+ **زاوية الإضاءة المسجلة**: سمت \`${angles.azimuthDeg}°\` | ارتفاع \`${angles.elevationDeg}°\`${userIntentHeader}
249
+
250
+ ---
251
+
252
+ ## 1. فهرس الطبقات التحليلية الست (The 6 Extracted Layers)
253
+
254
+ | # | اسم الطبقة | الملف المولد | القراءة الفيزيائية المكتشفة |
255
+ |---|---|---|---|
256
+ | **1** | **طبقة الألوان الفاتحة (Highlights)** | [\`01_highlights.png\`](file:///${toForwardSlash(hlPath)}) | نسبة تغطية الأضواء الساطعة: \`${hlPct.toFixed(2)}%\` |
257
+ | **2** | **طبقة الألوان الغامقة (Shadows)** | [\`02_shadows.png\`](file:///${toForwardSlash(shPath)}) | مساحة الظلال والمناطق الداكنة: \`${shPct.toFixed(2)}%\` |
258
+ | **3** | **طبقة الظل العالي (Ambient Occlusion)** | [\`03_ambient_occlusion.png\`](file:///${toForwardSlash(aoPath)}) | كثافة الارتكاز الأرضي وظلال التلامس: \`${aoPct.toFixed(2)}%\` |
259
+ | **4** | **طبقة الحواف (Edges & Contours)** | [\`04_edges.png\`](file:///${toForwardSlash(edPath)}) | تباين الحواف المجهرية لسوبل: \`${meanEdge.toFixed(4)}\` |
260
+ | **5** | **طبقة العمق (3D Depth Normals)** | [\`05_depth_normals.png\`](file:///${toForwardSlash(normPath)}) | توجيه التنسور المتجهي ثلاثي الأبعاد: سمت \`${angles.azimuthDeg}°\` |
261
+ | **6** | **طبقة الألوان والتشبع (Chroma / Saturation)** | [\`06_chroma_saturation.png\`](file:///${toForwardSlash(chrPath)}) | متوسط تشبع وتوزيع نقاء الألوان: \`${meanSaturation.toFixed(3)}\` |
262
+
263
+ ---
264
+
265
+ ## 2. النتائج البصرية الديناميكية المستخلصة من الصورة (Dynamic Findings)
266
+
267
+ ${findingsRendered}
268
+
269
+ ---
270
+
271
+ ## 3. التوجيه التوليدي المخصص (Calibrated Prompts for Generative Engines)
272
+
273
+ ### أ. موجه GPT Image (DALL-E 3 / GPT-4o Vision):
274
+ > "${diagnostics.gptImagePrompt}"
275
+
276
+ ### ب. موجه Nano Banana (High-Density Optical Tokenizer):
277
+ > "${diagnostics.nanoBananaPrompt}"
278
+
279
+ ---
280
+
281
+ ## 4. الخطوة التفاعلية الموجهة بالبيانات (Dynamic Interactive Decision)
282
+
283
+ **ماذا تريد من تعديل؟**
284
+ بناءً على المعطيات الضوئية المكتشفة في هذه الصورة تحديداً، إليك خيارات التعديل المقترحة:
285
+
286
+ ${optionsRendered}
287
+
288
+ 💬 *يمكنك أيضاً طلب أي تعديل مخصص بحرية تامة، وسيتم فوراً توليد برومبت دقيق للغاية أو إنشاء الصورة المعدلة بالكامل!*
289
+ `;
290
+ fs_1.default.writeFileSync(layerMdPath, mdContent, "utf-8");
291
+ return {
292
+ sourceImage: resolvedImagePath,
293
+ layersDirectory: resolvedOutputDir,
294
+ dimensions: [width, height],
295
+ opticalMetrics: {
296
+ cctKelvin: Math.round(cctKelvin * 10) / 10,
297
+ dominantLightVector: lightVector,
298
+ lightingAngles: angles,
299
+ meanLuminance: Math.round(meanLum * 100) / 100,
300
+ meanSaturation: Math.round(meanSaturation * 1000) / 1000,
301
+ edgeRoughness: Math.round(roughness * 10000) / 10000,
302
+ },
303
+ diagnostics,
304
+ layers: {
305
+ highlights: {
306
+ file: "01_highlights.png",
307
+ path: hlPath,
308
+ description: "طبقة الألوان الفاتحة - High-key Luminance & Specular Zones",
309
+ metricLabel: "coveragePct",
310
+ metricValue: Math.round(hlPct * 100) / 100,
311
+ },
312
+ shadows: {
313
+ file: "02_shadows.png",
314
+ path: shPath,
315
+ description: "طبقة الألوان الغامقة - Low-key & Shadow Zones",
316
+ metricLabel: "coveragePct",
317
+ metricValue: Math.round(shPct * 100) / 100,
318
+ },
319
+ ambientOcclusion: {
320
+ file: "03_ambient_occlusion.png",
321
+ path: aoPath,
322
+ description: "طبقة الظل العالي - High Contact Shadows & Deep Occlusion Crevices",
323
+ metricLabel: "coveragePct",
324
+ metricValue: Math.round(aoPct * 100) / 100,
325
+ },
326
+ edges: {
327
+ file: "04_edges.png",
328
+ path: edPath,
329
+ description: "طبقة الحواف - Sobel High-Frequency Gradient Contours",
330
+ metricLabel: "meanGradient",
331
+ metricValue: Math.round(meanEdge * 10000) / 10000,
332
+ },
333
+ depthNormals: {
334
+ file: "05_depth_normals.png",
335
+ path: normPath,
336
+ description: "طبقة العمق - 3D Surface Normal Gradient Field (RGB Tangent Map)",
337
+ metricLabel: "dominantAzimuth",
338
+ metricValue: angles.azimuthDeg,
339
+ },
340
+ chromaSaturation: {
341
+ file: "06_chroma_saturation.png",
342
+ path: chrPath,
343
+ description: "طبقة الألوان والتشبع والبكسلات - Chrominance & Saturation Distribution",
344
+ metricLabel: "meanSaturation",
345
+ metricValue: Math.round(meanSaturation * 1000) / 1000,
346
+ },
347
+ },
348
+ layerMarkdownPath: layerMdPath,
349
+ };
350
+ }
package/dist/index.js CHANGED
@@ -8,8 +8,8 @@ async function main() {
8
8
  const args = process.argv.slice(2);
9
9
  if (args.includes("--verify")) {
10
10
  console.log("[MarwanDevSpace] Verifying TypeScript mcp-relight-harmonize server...");
11
- console.log("Server 'mcp-relight-harmonize' v1.0.0 initialized.");
12
- console.log("Registered tools: ['analyze_optical_profile', 'generate_relight_variations', 'harmonize_composite', 'synthesize_diffusion_prompt']");
11
+ console.log("Server 'mcp-relight-harmonize' v1.0.3 initialized.");
12
+ console.log("Registered tools: ['analyze_optical_profile', 'generate_relight_variations', 'harmonize_composite', 'synthesize_diffusion_prompt', 'list_cached_variations']");
13
13
  console.log("Registered resources: ['optical://presets']");
14
14
  console.log("Output cache directory:", (0, config_1.ensureOutputDirectory)());
15
15
  console.log("[MarwanDevSpace] Server health verification passed (Exit code 0).");
@@ -3,7 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.LIGHTING_PRESETS_REFERENCE = void 0;
4
4
  exports.getPresetsJson = getPresetsJson;
5
5
  exports.LIGHTING_PRESETS_REFERENCE = {
6
- version: "1.0.0",
6
+ version: "1.0.3",
7
7
  target_generators: ["GPT Image", "Nano Banana"],
8
8
  presets: [
9
9
  {