browser-devtools-mcp 0.0.3 → 0.1.1

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 (91) hide show
  1. package/README.md +507 -59
  2. package/dist/browser.js +6 -0
  3. package/dist/browser.js.map +1 -1
  4. package/dist/config.js +60 -24
  5. package/dist/config.js.map +1 -1
  6. package/dist/context.js +28 -0
  7. package/dist/context.js.map +1 -1
  8. package/dist/otel/otel-controller.js +4 -0
  9. package/dist/otel/otel-controller.js.map +1 -1
  10. package/dist/server-info.js +133 -18
  11. package/dist/server-info.js.map +1 -1
  12. package/dist/tools/content/take-screenshot.js +183 -1
  13. package/dist/tools/content/take-screenshot.js.map +1 -1
  14. package/dist/tools/figma/compare/compare-image-embedding.js +159 -0
  15. package/dist/tools/figma/compare/compare-image-embedding.js.map +1 -0
  16. package/dist/tools/figma/compare/compare-mssim.js +98 -0
  17. package/dist/tools/figma/compare/compare-mssim.js.map +1 -0
  18. package/dist/tools/figma/compare/compare-text-embedding.js +291 -0
  19. package/dist/tools/figma/compare/compare-text-embedding.js.map +1 -0
  20. package/dist/tools/figma/compare/index.js +139 -0
  21. package/dist/tools/figma/compare/index.js.map +1 -0
  22. package/dist/tools/figma/compare/types.js +3 -0
  23. package/dist/tools/figma/compare/types.js.map +1 -0
  24. package/dist/tools/figma/compare/vector.js +46 -0
  25. package/dist/tools/figma/compare/vector.js.map +1 -0
  26. package/dist/tools/figma/compare-page-with-design.js +240 -0
  27. package/dist/tools/figma/compare-page-with-design.js.map +1 -0
  28. package/dist/tools/figma/figma-service.js +134 -0
  29. package/dist/tools/figma/figma-service.js.map +1 -0
  30. package/dist/tools/figma/index.js +6 -0
  31. package/dist/tools/figma/index.js.map +1 -0
  32. package/dist/tools/index.js +12 -2
  33. package/dist/tools/index.js.map +1 -1
  34. package/dist/tools/interaction/index.js +6 -2
  35. package/dist/tools/interaction/index.js.map +1 -1
  36. package/dist/tools/interaction/resize-viewport.js +110 -0
  37. package/dist/tools/interaction/resize-viewport.js.map +1 -0
  38. package/dist/tools/interaction/resize-window.js +261 -0
  39. package/dist/tools/interaction/resize-window.js.map +1 -0
  40. package/dist/tools/interaction/scroll.js +304 -0
  41. package/dist/tools/interaction/scroll.js.map +1 -0
  42. package/dist/tools/{monitoring → o11y}/get-console-messages.js +1 -1
  43. package/dist/tools/o11y/get-console-messages.js.map +1 -0
  44. package/dist/tools/{monitoring → o11y}/get-http-requests.js +1 -1
  45. package/dist/tools/o11y/get-http-requests.js.map +1 -0
  46. package/dist/tools/{monitoring → o11y}/get-trace-id.js +1 -1
  47. package/dist/tools/o11y/get-trace-id.js.map +1 -0
  48. package/dist/tools/o11y/get-web-vitals.js +595 -0
  49. package/dist/tools/o11y/get-web-vitals.js.map +1 -0
  50. package/dist/tools/{monitoring → o11y}/index.js +2 -0
  51. package/dist/tools/o11y/index.js.map +1 -0
  52. package/dist/tools/{monitoring → o11y}/new-trace-id.js +1 -1
  53. package/dist/tools/o11y/new-trace-id.js.map +1 -0
  54. package/dist/tools/{monitoring → o11y}/set-trace-id.js +1 -1
  55. package/dist/tools/o11y/set-trace-id.js.map +1 -0
  56. package/dist/tools/react/get-component-for-element.js +941 -0
  57. package/dist/tools/react/get-component-for-element.js.map +1 -0
  58. package/dist/tools/react/get-element-for-component.js +1190 -0
  59. package/dist/tools/react/get-element-for-component.js.map +1 -0
  60. package/dist/tools/react/index.js +10 -0
  61. package/dist/tools/react/index.js.map +1 -0
  62. package/dist/tools/run/index.js +7 -0
  63. package/dist/tools/run/index.js.map +1 -0
  64. package/dist/tools/{interaction/evaluate.js → run/js-in-browser.js} +24 -6
  65. package/dist/tools/run/js-in-browser.js.map +1 -0
  66. package/dist/tools/run/js-in-sandbox.js +175 -0
  67. package/dist/tools/run/js-in-sandbox.js.map +1 -0
  68. package/dist/tools/stub/clear.js +41 -0
  69. package/dist/tools/stub/clear.js.map +1 -0
  70. package/dist/tools/stub/index.js +14 -0
  71. package/dist/tools/stub/index.js.map +1 -0
  72. package/dist/tools/stub/intercept-http-request.js +112 -0
  73. package/dist/tools/stub/intercept-http-request.js.map +1 -0
  74. package/dist/tools/stub/list.js +75 -0
  75. package/dist/tools/stub/list.js.map +1 -0
  76. package/dist/tools/stub/mock-http-response.js +152 -0
  77. package/dist/tools/stub/mock-http-response.js.map +1 -0
  78. package/dist/tools/stub/stub-controller.js +284 -0
  79. package/dist/tools/stub/stub-controller.js.map +1 -0
  80. package/dist/tools/sync/index.js +6 -0
  81. package/dist/tools/sync/index.js.map +1 -0
  82. package/dist/tools/sync/wait-for-network-idle.js +152 -0
  83. package/dist/tools/sync/wait-for-network-idle.js.map +1 -0
  84. package/package.json +16 -3
  85. package/dist/tools/interaction/evaluate.js.map +0 -1
  86. package/dist/tools/monitoring/get-console-messages.js.map +0 -1
  87. package/dist/tools/monitoring/get-http-requests.js.map +0 -1
  88. package/dist/tools/monitoring/get-trace-id.js.map +0 -1
  89. package/dist/tools/monitoring/index.js.map +0 -1
  90. package/dist/tools/monitoring/new-trace-id.js.map +0 -1
  91. package/dist/tools/monitoring/set-trace-id.js.map +0 -1
@@ -0,0 +1,291 @@
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.compare = compare;
7
+ const config_1 = require("../../../config");
8
+ const vector_1 = require("./vector");
9
+ const client_bedrock_runtime_1 = require("@aws-sdk/client-bedrock-runtime");
10
+ const credential_providers_1 = require("@aws-sdk/credential-providers");
11
+ const sharp_1 = __importDefault(require("sharp"));
12
+ const UI_DESCRIBE_PROMPT = `
13
+ You are analyzing a UI screenshot to compare it against another UI.
14
+
15
+ Your goal is to produce a STRUCTURAL LAYOUT FINGERPRINT that remains stable
16
+ even when real data, text values, or content change.
17
+
18
+ Write a concise but highly informative description using the rules below.
19
+
20
+ GENERAL RULES
21
+ - Describe WHAT EXISTS and WHERE IT IS, not how it looks visually.
22
+ - Prefer explicit structure and hierarchy over natural language.
23
+ - Be consistent and deterministic in wording.
24
+ - Do NOT describe colors, fonts, themes, or exact text.
25
+ - Do NOT include user data, names, numbers, timestamps, or labels.
26
+
27
+ LAYOUT STRUCTURE
28
+ Describe the UI from top to bottom:
29
+
30
+ 1) PAGE REGIONS
31
+ - Identify major regions in order:
32
+ - top header / app bar
33
+ - left or right sidebar
34
+ - main content area
35
+ - footer (if present)
36
+
37
+ 2) REGION DETAILS
38
+ For EACH region, describe:
39
+ - Position (top / left / right / center / full-width)
40
+ - Layout type (row, column, grid, split, stacked)
41
+ - Whether it is fixed or scrollable
42
+ - Primary purpose (navigation, content, controls, metadata)
43
+
44
+ 3) COMPONENT INVENTORY
45
+ List the components that exist, grouped by region:
46
+ - navigation menus
47
+ - tabs
48
+ - tables (rows/columns, header present or not)
49
+ - lists (vertical/horizontal, item density: sparse/medium/dense)
50
+ - cards (count: single / few / many)
51
+ - forms (inline / multi-section)
52
+ - modals, drawers, overlays (present or not)
53
+
54
+ 4) HIERARCHY & RELATIONSHIPS
55
+ Explicitly mention:
56
+ - parent → child relationships
57
+ - repeated patterns (e.g. "repeating card list", "uniform table rows")
58
+ - alignment relationships (sidebar + main content, header spanning all columns)
59
+
60
+ 5) ABSENCE IS SIGNAL
61
+ If something is NOT present, state it explicitly when relevant:
62
+ - no sidebar
63
+ - no table
64
+ - no modal
65
+ - no pagination
66
+
67
+ FORMAT
68
+ - Use short bullet-style sentences.
69
+ - Use consistent phrasing across similar structures.
70
+ - Avoid synonyms (always say “sidebar”, not sometimes “side panel”).
71
+ - Keep the output under ~30 lines.
72
+
73
+ Return plain text only. No markdown.
74
+ `;
75
+ /**
76
+ * -----------------------------------------------------------------------------
77
+ * Helpers
78
+ * -----------------------------------------------------------------------------
79
+ */
80
+ function _resolvePrompt(opt) {
81
+ return opt?.prompt ?? UI_DESCRIBE_PROMPT.trim();
82
+ }
83
+ function _resolveMaxDim(opt) {
84
+ return typeof opt?.maxDim === 'number' && opt.maxDim > 0
85
+ ? Math.floor(opt.maxDim)
86
+ : 1024;
87
+ }
88
+ function _resolveImageFormat(opt) {
89
+ return opt?.imageFormat === 'jpeg' ? 'jpeg' : 'png';
90
+ }
91
+ function _resolveJpegQuality(opt) {
92
+ const q = opt?.jpegQuality;
93
+ return typeof q === 'number' && q >= 50 && q <= 100 ? Math.floor(q) : 90;
94
+ }
95
+ async function _preprocessImage(buf, opt) {
96
+ const maxDim = _resolveMaxDim(opt);
97
+ const format = _resolveImageFormat(opt);
98
+ const jpegQuality = _resolveJpegQuality(opt);
99
+ let img = (0, sharp_1.default)(buf).resize({
100
+ width: maxDim,
101
+ height: maxDim,
102
+ fit: 'inside',
103
+ withoutEnlargement: true,
104
+ });
105
+ let out;
106
+ let mimeType;
107
+ if (format === 'png') {
108
+ out = await img.png().toBuffer();
109
+ mimeType = 'image/png';
110
+ }
111
+ else {
112
+ out = await img.jpeg({ quality: jpegQuality }).toBuffer();
113
+ mimeType = 'image/jpeg';
114
+ }
115
+ return { bytes: out, mimeType };
116
+ }
117
+ /**
118
+ * -----------------------------------------------------------------------------
119
+ * Amazon Bedrock specific embedding implementations
120
+ * -----------------------------------------------------------------------------
121
+ */
122
+ ////////////////////////////////////////////////////////////////////////////////
123
+ const SUPPORTED_AMAZON_BEDROCK_TEXT_EMBED_MODEL_IDS = new Set([
124
+ 'amazon.titan-embed-text-v2:0',
125
+ ]);
126
+ const DEFAULT_AMAZON_BEDROCK_TEXT_EMBED_MODEL_ID = 'amazon.titan-embed-text-v2:0';
127
+ const SUPPORTED_AMAZON_BEDROCK_VISION_MODEL_IDS = new Set([
128
+ 'anthropic.claude-3-haiku-20240307-v1',
129
+ 'anthropic.claude-3-sonnet-20240229-v1:0',
130
+ 'anthropic.claude-3-5-sonnet-20241022-v2:0',
131
+ 'anthropic.claude-3-7-sonnet-20250219-v1:0',
132
+ 'anthropic.claude-3-opus-20240229-v1:0',
133
+ 'anthropic.claude-haiku-4-5-20251001-v1:0',
134
+ 'anthropic.claude-opus-4-1-20250805-v1:0',
135
+ 'anthropic.claude-opus-4-5-20251101-v1:0',
136
+ ]);
137
+ const DEFAULT_AMAZON_BEDROCK_VISION_MODEL_ID = 'anthropic.claude-3-sonnet-20240229-v1:0';
138
+ let _bedrockClient;
139
+ function _isAwsBedrockActive() {
140
+ // Minimal "is Bedrock usable?" check:
141
+ // - Amazon Bedrock must be enabled
142
+ // - Region must exist
143
+ // - Credentials are resolved by AWS SDK default chain or AWS_PROFILE
144
+ return config_1.AMAZON_BEDROCK_ENABLE && Boolean(config_1.AWS_REGION);
145
+ }
146
+ function _getOrCreateBedrockClient() {
147
+ if (_bedrockClient) {
148
+ return _bedrockClient;
149
+ }
150
+ const region = config_1.AWS_REGION;
151
+ if (!region) {
152
+ return undefined;
153
+ }
154
+ const profile = config_1.AWS_PROFILE;
155
+ if (profile) {
156
+ _bedrockClient = new client_bedrock_runtime_1.BedrockRuntimeClient({
157
+ region,
158
+ credentials: (0, credential_providers_1.fromIni)({ profile }),
159
+ });
160
+ return _bedrockClient;
161
+ }
162
+ _bedrockClient = new client_bedrock_runtime_1.BedrockRuntimeClient({ region });
163
+ return _bedrockClient;
164
+ }
165
+ async function _invokeBedrock(client, modelId, payload) {
166
+ const cmd = new client_bedrock_runtime_1.InvokeModelCommand({
167
+ modelId,
168
+ contentType: 'application/json',
169
+ accept: 'application/json',
170
+ body: Buffer.from(JSON.stringify(payload)),
171
+ });
172
+ const resp = await client.send(cmd);
173
+ const raw = Buffer.from(resp.body).toString('utf-8');
174
+ return JSON.parse(raw);
175
+ }
176
+ async function _describeUIWithAmazonBedrockClaude(ss, opt, client, modelId) {
177
+ const { bytes, mimeType } = await _preprocessImage(ss.image, opt);
178
+ const prompt = _resolvePrompt(opt);
179
+ const payload = {
180
+ anthropic_version: 'bedrock-2023-05-31',
181
+ max_tokens: 10_000,
182
+ temperature: 0,
183
+ messages: [
184
+ {
185
+ role: 'user',
186
+ content: [
187
+ { type: 'text', text: prompt },
188
+ {
189
+ type: 'image',
190
+ source: {
191
+ type: 'base64',
192
+ media_type: mimeType,
193
+ data: bytes.toString('base64'),
194
+ },
195
+ },
196
+ ],
197
+ },
198
+ ],
199
+ };
200
+ const parsed = await _invokeBedrock(client, modelId, payload);
201
+ const text = parsed?.content?.[0]?.text ?? parsed?.output_text ?? parsed?.completion;
202
+ if (!text || !text.trim()) {
203
+ throw new Error('Amazon Bedrock Claude returned empty description.');
204
+ }
205
+ return text.trim();
206
+ }
207
+ async function _embedTextWithAmazonBedrockTitan(text, client, modelId) {
208
+ const payload = {
209
+ inputText: text,
210
+ };
211
+ const parsed = await _invokeBedrock(client, modelId, payload);
212
+ const emb = parsed?.embedding;
213
+ if (!Array.isArray(emb) || typeof emb[0] !== 'number') {
214
+ throw new Error('Unexpected embedding response for Amazon Bedrock Titan text embedding.');
215
+ }
216
+ return emb;
217
+ }
218
+ async function _describeUIWithAmazonBedrock(ss, opt, client) {
219
+ const modelId = opt?.visionModelId ??
220
+ config_1.AMAZON_BEDROCK_VISION_MODEL_ID ??
221
+ DEFAULT_AMAZON_BEDROCK_VISION_MODEL_ID;
222
+ if (!SUPPORTED_AMAZON_BEDROCK_VISION_MODEL_IDS.has(modelId)) {
223
+ throw new Error(`Unsupported Amazon Bedrock vision model id: ${modelId}`);
224
+ }
225
+ return await _describeUIWithAmazonBedrockClaude(ss, opt, client, modelId);
226
+ }
227
+ async function _embedTextWithAmazonBedrock(text, opt, client) {
228
+ const modelId = opt?.textEmbedModelId ??
229
+ config_1.AMAZON_BEDROCK_TEXT_EMBED_MODEL_ID ??
230
+ DEFAULT_AMAZON_BEDROCK_TEXT_EMBED_MODEL_ID;
231
+ if (!SUPPORTED_AMAZON_BEDROCK_TEXT_EMBED_MODEL_IDS.has(modelId)) {
232
+ throw new Error(`Unsupported Amazon Bedrock text embedding model id: ${modelId}`);
233
+ }
234
+ return await _embedTextWithAmazonBedrockTitan(text, client, modelId);
235
+ }
236
+ /**
237
+ * -----------------------------------------------------------------------------
238
+ * Routing (LLM-agnostic)
239
+ * -----------------------------------------------------------------------------
240
+ */
241
+ async function _describeUI(ss, opt) {
242
+ // Provider A: Amazon Bedrock
243
+ if (_isAwsBedrockActive()) {
244
+ const client = _getOrCreateBedrockClient();
245
+ if (!client) {
246
+ return undefined;
247
+ }
248
+ return _describeUIWithAmazonBedrock(ss, opt, client);
249
+ }
250
+ // No providers active
251
+ return undefined;
252
+ }
253
+ async function _embedTextVector(text, opt) {
254
+ // Provider A: Amazon Bedrock
255
+ if (_isAwsBedrockActive()) {
256
+ const client = _getOrCreateBedrockClient();
257
+ if (!client) {
258
+ return undefined;
259
+ }
260
+ return _embedTextWithAmazonBedrock(text, opt, client);
261
+ }
262
+ // No providers active
263
+ return undefined;
264
+ }
265
+ /**
266
+ * -----------------------------------------------------------------------------
267
+ * Public API
268
+ * -----------------------------------------------------------------------------
269
+ */
270
+ async function compare(page, figma, options) {
271
+ const normalize = typeof options?.normalize === 'boolean' ? options.normalize : true;
272
+ const figmaDesc = await _describeUI(figma, options);
273
+ if (!figmaDesc) {
274
+ return undefined;
275
+ }
276
+ const pageDesc = await _describeUI(page, options);
277
+ if (!pageDesc) {
278
+ return undefined;
279
+ }
280
+ const figmaVec = await _embedTextVector(figmaDesc, options);
281
+ if (!figmaVec) {
282
+ return undefined;
283
+ }
284
+ const pageVec = await _embedTextVector(pageDesc, options);
285
+ if (!pageVec) {
286
+ return undefined;
287
+ }
288
+ const score = (0, vector_1.cosineSimilarity)(figmaVec, pageVec, normalize);
289
+ return { score };
290
+ }
291
+ //# sourceMappingURL=compare-text-embedding.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"compare-text-embedding.js","sourceRoot":"","sources":["../../../../src/tools/figma/compare/compare-text-embedding.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,139 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ exports.compareWithNotes = compareWithNotes;
18
+ const compare_mssim_1 = require("./compare-mssim");
19
+ const compare_image_embedding_1 = require("./compare-image-embedding");
20
+ const compare_text_embedding_1 = require("./compare-text-embedding");
21
+ /**
22
+ * ------------------------------------------------------------
23
+ * Constants
24
+ * ------------------------------------------------------------
25
+ */
26
+ const DEFAULT_MSSIM_WEIGHT = 0.25;
27
+ const DEFAULT_VECTOR_EMBEDDING_WEIGHT = 0.5;
28
+ const DEFAULT_TEXT_EMBEDDING_WEIGHT = 0.25;
29
+ /**
30
+ * ------------------------------------------------------------
31
+ * Helpers
32
+ * ------------------------------------------------------------
33
+ */
34
+ function _clamp01(v) {
35
+ if (!Number.isFinite(v)) {
36
+ return 0;
37
+ }
38
+ return Math.max(0, Math.min(1, v));
39
+ }
40
+ function _weightOrDefault(v, def) {
41
+ if (typeof v === 'number' && Number.isFinite(v) && v > 0) {
42
+ return v;
43
+ }
44
+ return def;
45
+ }
46
+ /**
47
+ * ------------------------------------------------------------
48
+ * Main combiner
49
+ * ------------------------------------------------------------
50
+ *
51
+ * - MSSIM is assumed to always work
52
+ * - Image / text embedding may return `undefined`
53
+ * - Only successful signals participate in the weighted average
54
+ */
55
+ async function compareWithNotes(page, figma, options) {
56
+ const notes = [];
57
+ const wMssim = _weightOrDefault(options?.weights?.mssim, DEFAULT_MSSIM_WEIGHT);
58
+ const wVector = _weightOrDefault(options?.weights?.vectorEmbedding, DEFAULT_VECTOR_EMBEDDING_WEIGHT);
59
+ const wText = _weightOrDefault(options?.weights?.textEmbedding, DEFAULT_TEXT_EMBEDDING_WEIGHT);
60
+ /**
61
+ * --------------------------------------------------------
62
+ * 1) MSSIM (always)
63
+ * --------------------------------------------------------
64
+ */
65
+ const mssimRes = await (0, compare_mssim_1.compare)(page, figma, options?.mssim);
66
+ const mssimScore = _clamp01(mssimRes.score);
67
+ notes.push(`mssim=${mssimScore.toFixed(5)}`);
68
+ /**
69
+ * --------------------------------------------------------
70
+ * 2) Image embedding (optional)
71
+ * --------------------------------------------------------
72
+ */
73
+ let imageScore;
74
+ try {
75
+ const res = await (0, compare_image_embedding_1.compare)(page, figma, options?.imageEmbedding);
76
+ if (res && typeof res.score === 'number') {
77
+ imageScore = _clamp01(res.score);
78
+ notes.push(`image-embedding=${imageScore.toFixed(5)}`);
79
+ }
80
+ else {
81
+ notes.push('image-embedding=skipped (inactive)');
82
+ }
83
+ }
84
+ catch (err) {
85
+ notes.push(`image-embedding=skipped (${err instanceof Error ? err.message : String(err)})`);
86
+ }
87
+ /**
88
+ * --------------------------------------------------------
89
+ * 3) Vision → text → text embedding (optional)
90
+ * --------------------------------------------------------
91
+ */
92
+ let textScore;
93
+ try {
94
+ const res = await (0, compare_text_embedding_1.compare)(page, figma, options?.textEmbedding);
95
+ if (res && typeof res.score === 'number') {
96
+ textScore = _clamp01(res.score);
97
+ notes.push(`text-embedding=${textScore.toFixed(5)}`);
98
+ }
99
+ else {
100
+ notes.push('text-embedding=skipped (inactive)');
101
+ }
102
+ }
103
+ catch (err) {
104
+ notes.push(`text-embedding=skipped (${err instanceof Error ? err.message : String(err)})`);
105
+ }
106
+ /**
107
+ * --------------------------------------------------------
108
+ * Combine scores (weight renormalization)
109
+ * --------------------------------------------------------
110
+ */
111
+ const parts = [
112
+ { name: 'mssim', score: mssimScore, weight: wMssim },
113
+ ];
114
+ if (typeof imageScore === 'number') {
115
+ parts.push({
116
+ name: 'image-embedding',
117
+ score: imageScore,
118
+ weight: wVector,
119
+ });
120
+ }
121
+ if (typeof textScore === 'number') {
122
+ parts.push({
123
+ name: 'text-embedding',
124
+ score: textScore,
125
+ weight: wText,
126
+ });
127
+ }
128
+ const totalWeight = parts.reduce((s, p) => s + p.weight, 0);
129
+ const combined = totalWeight > 0
130
+ ? parts.reduce((s, p) => s + p.score * (p.weight / totalWeight), 0)
131
+ : 0;
132
+ const score = _clamp01(combined);
133
+ notes.push(`combined=${score.toFixed(5)} (signals=${parts
134
+ .map((p) => p.name)
135
+ .join(', ')})`);
136
+ return { score, notes };
137
+ }
138
+ __exportStar(require("./types"), exports);
139
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/tools/figma/compare/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAwGA,4CA6HC;AAnOD,mDAA0D;AAM1D,uEAAoE;AAMpE,qEAAkE;AAmDlE;;;;GAIG;AAEH,MAAM,oBAAoB,GAAW,IAAI,CAAC;AAC1C,MAAM,+BAA+B,GAAW,GAAG,CAAC;AACpD,MAAM,6BAA6B,GAAW,IAAI,CAAC;AAEnD;;;;GAIG;AAEH,SAAS,QAAQ,CAAC,CAAS;IACvB,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC;QACtB,OAAO,CAAC,CAAC;IACb,CAAC;IACD,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;AACvC,CAAC;AAED,SAAS,gBAAgB,CAAC,CAAU,EAAE,GAAW;IAC7C,IAAI,OAAO,CAAC,KAAK,QAAQ,IAAI,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;QACvD,OAAO,CAAC,CAAC;IACb,CAAC;IACD,OAAO,GAAG,CAAC;AACf,CAAC;AAED;;;;;;;;GAQG;AACI,KAAK,UAAU,gBAAgB,CAClC,IAAoB,EACpB,KAAqB,EACrB,OAA2B;IAE3B,MAAM,KAAK,GAAa,EAAE,CAAC;IAE3B,MAAM,MAAM,GAAW,gBAAgB,CACnC,OAAO,EAAE,OAAO,EAAE,KAAK,EACvB,oBAAoB,CACvB,CAAC;IACF,MAAM,OAAO,GAAW,gBAAgB,CACpC,OAAO,EAAE,OAAO,EAAE,eAAe,EACjC,+BAA+B,CAClC,CAAC;IACF,MAAM,KAAK,GAAW,gBAAgB,CAClC,OAAO,EAAE,OAAO,EAAE,aAAa,EAC/B,6BAA6B,CAChC,CAAC;IAEF;;;;OAIG;IACH,MAAM,QAAQ,GAAuB,MAAM,IAAA,uBAAY,EACnD,IAAI,EACJ,KAAK,EACL,OAAO,EAAE,KAAK,CACjB,CAAC;IACF,MAAM,UAAU,GAAW,QAAQ,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;IAEpD,KAAK,CAAC,IAAI,CAAC,SAAS,UAAU,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;IAE7C;;;;OAIG;IACH,IAAI,UAA8B,CAAC;IAEnC,IAAI,CAAC;QACD,MAAM,GAAG,GAAmC,MAAM,IAAA,iCAAY,EAC1D,IAAI,EACJ,KAAK,EACL,OAAO,EAAE,cAAc,CAC1B,CAAC;QACF,IAAI,GAAG,IAAI,OAAO,GAAG,CAAC,KAAK,KAAK,QAAQ,EAAE,CAAC;YACvC,UAAU,GAAG,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;YACjC,KAAK,CAAC,IAAI,CAAC,mBAAmB,UAAU,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;QAC3D,CAAC;aAAM,CAAC;YACJ,KAAK,CAAC,IAAI,CAAC,oCAAoC,CAAC,CAAC;QACrD,CAAC;IACL,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACX,KAAK,CAAC,IAAI,CACN,4BAA4B,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,CAClF,CAAC;IACN,CAAC;IAED;;;;OAIG;IACH,IAAI,SAA6B,CAAC;IAElC,IAAI,CAAC;QACD,MAAM,GAAG,GAAkC,MAAM,IAAA,gCAAW,EACxD,IAAI,EACJ,KAAK,EACL,OAAO,EAAE,aAAa,CACzB,CAAC;QACF,IAAI,GAAG,IAAI,OAAO,GAAG,CAAC,KAAK,KAAK,QAAQ,EAAE,CAAC;YACvC,SAAS,GAAG,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;YAChC,KAAK,CAAC,IAAI,CAAC,kBAAkB,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;QACzD,CAAC;aAAM,CAAC;YACJ,KAAK,CAAC,IAAI,CAAC,mCAAmC,CAAC,CAAC;QACpD,CAAC;IACL,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACX,KAAK,CAAC,IAAI,CACN,2BAA2B,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,CACjF,CAAC;IACN,CAAC;IAED;;;;OAIG;IACH,MAAM,KAAK,GAA2D;QAClE,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,EAAE;KACvD,CAAC;IAEF,IAAI,OAAO,UAAU,KAAK,QAAQ,EAAE,CAAC;QACjC,KAAK,CAAC,IAAI,CAAC;YACP,IAAI,EAAE,iBAAiB;YACvB,KAAK,EAAE,UAAU;YACjB,MAAM,EAAE,OAAO;SAClB,CAAC,CAAC;IACP,CAAC;IAED,IAAI,OAAO,SAAS,KAAK,QAAQ,EAAE,CAAC;QAChC,KAAK,CAAC,IAAI,CAAC;YACP,IAAI,EAAE,gBAAgB;YACtB,KAAK,EAAE,SAAS;YAChB,MAAM,EAAE,KAAK;SAChB,CAAC,CAAC;IACP,CAAC;IAED,MAAM,WAAW,GAAW,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;IAEpE,MAAM,QAAQ,GACV,WAAW,GAAG,CAAC;QACX,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,MAAM,GAAG,WAAW,CAAC,EAAE,CAAC,CAAC;QACnE,CAAC,CAAC,CAAC,CAAC;IAEZ,MAAM,KAAK,GAAW,QAAQ,CAAC,QAAQ,CAAC,CAAC;IAEzC,KAAK,CAAC,IAAI,CACN,YAAY,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,aAAa,KAAK;SACzC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;SAClB,IAAI,CAAC,IAAI,CAAC,GAAG,CACrB,CAAC;IAEF,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC;AAC5B,CAAC;AAED,0CAAwB"}
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../../src/tools/figma/compare/types.ts"],"names":[],"mappings":""}
@@ -0,0 +1,46 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.dot = dot;
4
+ exports.norm = norm;
5
+ exports.l2Normalize = l2Normalize;
6
+ exports.cosineSimilarity = cosineSimilarity;
7
+ function dot(a, b) {
8
+ const n = Math.min(a.length, b.length);
9
+ let s = 0;
10
+ for (let i = 0; i < n; i++) {
11
+ s += a[i] * b[i];
12
+ }
13
+ return s;
14
+ }
15
+ function norm(a) {
16
+ let s = 0;
17
+ for (let i = 0; i < a.length; i++) {
18
+ const x = a[i];
19
+ s += x * x;
20
+ }
21
+ return Math.sqrt(s);
22
+ }
23
+ function l2Normalize(v) {
24
+ const n = norm(v);
25
+ if (n === 0) {
26
+ return v.slice();
27
+ }
28
+ const out = new Array(v.length);
29
+ for (let i = 0; i < v.length; i++) {
30
+ out[i] = v[i] / n;
31
+ }
32
+ return out;
33
+ }
34
+ function cosineSimilarity(a, b, normalize) {
35
+ if (normalize) {
36
+ const na = l2Normalize(a);
37
+ const nb = l2Normalize(b);
38
+ return dot(na, nb);
39
+ }
40
+ const denom = norm(a) * norm(b);
41
+ if (denom === 0) {
42
+ return 0;
43
+ }
44
+ return dot(a, b) / denom;
45
+ }
46
+ //# sourceMappingURL=vector.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"vector.js","sourceRoot":"","sources":["../../../../src/tools/figma/compare/vector.ts"],"names":[],"mappings":";;AAEA,kBAOC;AAED,oBAOC;AAED,kCAWC;AAED,4CAgBC;AA/CD,SAAgB,GAAG,CAAC,CAAS,EAAE,CAAS;IACpC,MAAM,CAAC,GAAW,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC;IAC/C,IAAI,CAAC,GAAW,CAAC,CAAC;IAClB,KAAK,IAAI,CAAC,GAAW,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;QACjC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;IACrB,CAAC;IACD,OAAO,CAAC,CAAC;AACb,CAAC;AAED,SAAgB,IAAI,CAAC,CAAS;IAC1B,IAAI,CAAC,GAAW,CAAC,CAAC;IAClB,KAAK,IAAI,CAAC,GAAW,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACxC,MAAM,CAAC,GAAW,CAAC,CAAC,CAAC,CAAC,CAAC;QACvB,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACf,CAAC;IACD,OAAO,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AACxB,CAAC;AAED,SAAgB,WAAW,CAAC,CAAS;IACjC,MAAM,CAAC,GAAW,IAAI,CAAC,CAAC,CAAC,CAAC;IAC1B,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;QACV,OAAO,CAAC,CAAC,KAAK,EAAE,CAAC;IACrB,CAAC;IAED,MAAM,GAAG,GAAW,IAAI,KAAK,CAAS,CAAC,CAAC,MAAM,CAAC,CAAC;IAChD,KAAK,IAAI,CAAC,GAAW,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACxC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;IACtB,CAAC;IACD,OAAO,GAAG,CAAC;AACf,CAAC;AAED,SAAgB,gBAAgB,CAC5B,CAAS,EACT,CAAS,EACT,SAAkB;IAElB,IAAI,SAAS,EAAE,CAAC;QACZ,MAAM,EAAE,GAAW,WAAW,CAAC,CAAC,CAAC,CAAC;QAClC,MAAM,EAAE,GAAW,WAAW,CAAC,CAAC,CAAC,CAAC;QAClC,OAAO,GAAG,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC;IACvB,CAAC;IAED,MAAM,KAAK,GAAW,IAAI,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;IACxC,IAAI,KAAK,KAAK,CAAC,EAAE,CAAC;QACd,OAAO,CAAC,CAAC;IACb,CAAC;IACD,OAAO,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,KAAK,CAAC;AAC7B,CAAC"}