speccore 8.3.46 → 8.3.48

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 (33) hide show
  1. package/dist/cli.js +10 -1
  2. package/dist/cli.js.map +1 -1
  3. package/dist/commands/analyze.d.ts.map +1 -1
  4. package/dist/commands/analyze.js +6 -1
  5. package/dist/commands/analyze.js.map +1 -1
  6. package/dist/commands/init.d.ts.map +1 -1
  7. package/dist/commands/init.js +62 -12
  8. package/dist/commands/init.js.map +1 -1
  9. package/dist/commands/verify.d.ts +9 -0
  10. package/dist/commands/verify.d.ts.map +1 -1
  11. package/dist/commands/verify.js +294 -6
  12. package/dist/commands/verify.js.map +1 -1
  13. package/dist/core/ui-verify/index.d.ts +8 -0
  14. package/dist/core/ui-verify/index.d.ts.map +1 -0
  15. package/dist/core/ui-verify/index.js +29 -0
  16. package/dist/core/ui-verify/index.js.map +1 -0
  17. package/dist/core/ui-verify/report-generator.d.ts +6 -0
  18. package/dist/core/ui-verify/report-generator.d.ts.map +1 -0
  19. package/dist/core/ui-verify/report-generator.js +209 -0
  20. package/dist/core/ui-verify/report-generator.js.map +1 -0
  21. package/dist/core/ui-verify/smoke-engine.d.ts +16 -0
  22. package/dist/core/ui-verify/smoke-engine.d.ts.map +1 -0
  23. package/dist/core/ui-verify/smoke-engine.js +297 -0
  24. package/dist/core/ui-verify/smoke-engine.js.map +1 -0
  25. package/dist/core/ui-verify/types.d.ts +100 -0
  26. package/dist/core/ui-verify/types.d.ts.map +1 -0
  27. package/dist/core/ui-verify/types.js +8 -0
  28. package/dist/core/ui-verify/types.js.map +1 -0
  29. package/dist/core/ui-verify/visual-engine.d.ts +21 -0
  30. package/dist/core/ui-verify/visual-engine.d.ts.map +1 -0
  31. package/dist/core/ui-verify/visual-engine.js +217 -0
  32. package/dist/core/ui-verify/visual-engine.js.map +1 -0
  33. package/package.json +3 -2
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/core/ui-verify/types.ts"],"names":[],"mappings":";AAAA;;;;GAIG"}
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Visual Engine — 视觉模型分析引擎
3
+ *
4
+ * 对比基准图与当前截图,调用视觉模型分析差异
5
+ */
6
+ import { VisualResult, SmokeResult } from './types';
7
+ interface VisualOptions {
8
+ baselineDir: string;
9
+ screenshotDir: string;
10
+ diffDir: string;
11
+ threshold: 'strict' | 'normal' | 'loose';
12
+ updateBaseline: boolean;
13
+ visualModel?: string;
14
+ }
15
+ export declare function runVisualCheck(smokeResults: SmokeResult[], options: VisualOptions): Promise<VisualResult[]>;
16
+ /**
17
+ * 检查视觉模型 API 是否可用
18
+ */
19
+ export declare function isVisualModelAvailable(): Promise<boolean>;
20
+ export {};
21
+ //# sourceMappingURL=visual-engine.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"visual-engine.d.ts","sourceRoot":"","sources":["../../../src/core/ui-verify/visual-engine.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAKH,OAAO,EAAE,YAAY,EAAe,WAAW,EAAE,MAAM,SAAS,CAAC;AAEjE,UAAU,aAAa;IACrB,WAAW,EAAE,MAAM,CAAC;IACpB,aAAa,EAAE,MAAM,CAAC;IACtB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,QAAQ,GAAG,QAAQ,GAAG,OAAO,CAAC;IACzC,cAAc,EAAE,OAAO,CAAC;IACxB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,wBAAsB,cAAc,CAClC,YAAY,EAAE,WAAW,EAAE,EAC3B,OAAO,EAAE,aAAa,GACrB,OAAO,CAAC,YAAY,EAAE,CAAC,CAqFzB;AA+KD;;GAEG;AACH,wBAAsB,sBAAsB,IAAI,OAAO,CAAC,OAAO,CAAC,CAG/D"}
@@ -0,0 +1,217 @@
1
+ "use strict";
2
+ /**
3
+ * Visual Engine — 视觉模型分析引擎
4
+ *
5
+ * 对比基准图与当前截图,调用视觉模型分析差异
6
+ */
7
+ Object.defineProperty(exports, "__esModule", { value: true });
8
+ exports.runVisualCheck = runVisualCheck;
9
+ exports.isVisualModelAvailable = isVisualModelAvailable;
10
+ const path_1 = require("path");
11
+ const fs_extra_1 = require("fs-extra");
12
+ const logger_1 = require("../../utils/logger");
13
+ async function runVisualCheck(smokeResults, options) {
14
+ const results = [];
15
+ await (0, fs_extra_1.ensureDir)(options.baselineDir);
16
+ await (0, fs_extra_1.ensureDir)(options.diffDir);
17
+ for (const smoke of smokeResults) {
18
+ if (!smoke.screenshot) {
19
+ logger_1.logger.warn(` ⚠️ ${smoke.scenarioName} 无截图,跳过视觉检查`);
20
+ continue;
21
+ }
22
+ const scenarioSafeName = smoke.scenarioName.replace(/[^a-z0-9]/gi, '_').toLowerCase();
23
+ const baselinePath = (0, path_1.join)(options.baselineDir, `${scenarioSafeName}.png`);
24
+ const currentPath = smoke.screenshot;
25
+ const diffPath = (0, path_1.join)(options.diffDir, `${scenarioSafeName}_diff.png`);
26
+ logger_1.logger.info(` 🖼️ 视觉检查: ${smoke.scenarioName}`);
27
+ // 检查是否存在基准图
28
+ const hasBaseline = await (0, fs_extra_1.pathExists)(baselinePath);
29
+ if (!hasBaseline) {
30
+ // 首次运行:保存为基准图 + 单图通用质量扫描
31
+ await (0, fs_extra_1.copy)(currentPath, baselinePath);
32
+ logger_1.logger.info(` ✅ 已保存基准图`);
33
+ // 单图通用质量扫描(无基准图时也能发现问题)
34
+ const scanResult = await analyzeSingleImage({
35
+ imagePath: currentPath,
36
+ scenarioName: smoke.scenarioName,
37
+ threshold: options.threshold,
38
+ model: options.visualModel,
39
+ });
40
+ results.push({
41
+ scenarioName: smoke.scenarioName,
42
+ passed: scanResult.passed,
43
+ baselinePath,
44
+ currentPath,
45
+ analysis: `首次运行,已保存基准图。${scanResult.analysis}`,
46
+ issues: scanResult.issues,
47
+ });
48
+ const icon = scanResult.passed ? '✅' : '⚠️';
49
+ logger_1.logger.info(` ${icon} 单图质量扫描: ${scanResult.passed ? '通过' : '发现问题'} (${scanResult.issues.length} 项)`);
50
+ continue;
51
+ }
52
+ if (options.updateBaseline) {
53
+ // 强制更新基准图
54
+ await (0, fs_extra_1.copy)(currentPath, baselinePath);
55
+ results.push({
56
+ scenarioName: smoke.scenarioName,
57
+ passed: true,
58
+ baselinePath,
59
+ currentPath,
60
+ analysis: '基准图已更新',
61
+ issues: [],
62
+ });
63
+ logger_1.logger.info(` ✅ 基准图已更新`);
64
+ continue;
65
+ }
66
+ // 调用视觉模型分析差异
67
+ const visualResult = await analyzeWithVisualModel({
68
+ baselinePath,
69
+ currentPath,
70
+ diffPath,
71
+ scenarioName: smoke.scenarioName,
72
+ threshold: options.threshold,
73
+ model: options.visualModel,
74
+ });
75
+ results.push(visualResult);
76
+ const icon = visualResult.passed ? '✅' : '⚠️';
77
+ logger_1.logger.info(` ${icon} ${visualResult.passed ? '通过' : '发现问题'} (${visualResult.issues.length} 项)`);
78
+ }
79
+ return results;
80
+ }
81
+ async function analyzeWithVisualModel(options) {
82
+ try {
83
+ // 读取图片为 base64
84
+ const baselineBase64 = await imageToBase64(options.baselinePath);
85
+ const currentBase64 = await imageToBase64(options.currentPath);
86
+ // 调用视觉模型 API
87
+ const response = await callVisualModel({
88
+ baselineBase64,
89
+ currentBase64,
90
+ scenarioName: options.scenarioName,
91
+ model: options.model,
92
+ });
93
+ // 解析响应
94
+ const { passed, analysis, issues } = parseVisualResponse(response, options.threshold);
95
+ return {
96
+ scenarioName: options.scenarioName,
97
+ passed,
98
+ baselinePath: options.baselinePath,
99
+ currentPath: options.currentPath,
100
+ diffPath: options.diffPath,
101
+ analysis,
102
+ issues,
103
+ };
104
+ }
105
+ catch (error) {
106
+ const message = error instanceof Error ? error.message : String(error);
107
+ logger_1.logger.error(` ❌ 视觉模型调用失败: ${message}`);
108
+ // 失败时返回警告而非阻断(避免网络问题导致测试失败)
109
+ return {
110
+ scenarioName: options.scenarioName,
111
+ passed: options.threshold !== 'strict',
112
+ baselinePath: options.baselinePath,
113
+ currentPath: options.currentPath,
114
+ analysis: `视觉模型调用失败: ${message}`,
115
+ issues: [{
116
+ severity: 'warning',
117
+ description: `视觉模型调用失败: ${message}`,
118
+ }],
119
+ };
120
+ }
121
+ }
122
+ async function imageToBase64(path) {
123
+ const buffer = await (0, fs_extra_1.readFile)(path);
124
+ return buffer.toString('base64');
125
+ }
126
+ async function callVisualModel(request) {
127
+ // TODO: 实现具体的视觉模型调用
128
+ // 当前为占位实现,后续接入 GPT-4o / Claude 3.5 Sonnet / Qwen-VL
129
+ const model = request.model || 'gpt-4o';
130
+ logger_1.logger.info(` 🤖 调用视觉模型: ${model}`);
131
+ // 这里应该调用实际的 AI API
132
+ // 示例(OpenAI GPT-4o):
133
+ // const response = await openai.chat.completions.create({
134
+ // model: 'gpt-4o',
135
+ // messages: [
136
+ // {
137
+ // role: 'system',
138
+ // content: '你是一个 UI 视觉测试专家。对比两张截图,分析差异。'
139
+ // },
140
+ // {
141
+ // role: 'user',
142
+ // content: [
143
+ // { type: 'text', text: `对比 "${request.scenarioName}" 的基准图和当前图,分析是否有视觉差异。` },
144
+ // { type: 'image_url', image_url: { url: `data:image/png;base64,${request.baselineBase64}` } },
145
+ // { type: 'image_url', image_url: { url: `data:image/png;base64,${request.currentBase64}` } },
146
+ // ]
147
+ // }
148
+ // ]
149
+ // });
150
+ // 临时返回模拟结果(后续替换为真实调用)
151
+ return JSON.stringify({
152
+ passed: true,
153
+ analysis: '视觉模型分析完成,未发现明显差异。',
154
+ issues: [],
155
+ });
156
+ }
157
+ function parseVisualResponse(response, threshold) {
158
+ try {
159
+ const parsed = JSON.parse(response);
160
+ return {
161
+ passed: parsed.passed ?? true,
162
+ analysis: parsed.analysis || '未提供分析',
163
+ issues: (parsed.issues || []).map((i) => ({
164
+ severity: i.severity || 'info',
165
+ description: i.description || '',
166
+ region: i.region,
167
+ })),
168
+ };
169
+ }
170
+ catch {
171
+ // 非 JSON 响应,视为纯文本分析
172
+ return {
173
+ passed: threshold !== 'strict',
174
+ analysis: response,
175
+ issues: [],
176
+ };
177
+ }
178
+ }
179
+ async function analyzeSingleImage(options) {
180
+ try {
181
+ const imageBase64 = await imageToBase64(options.imagePath);
182
+ const model = options.model || 'gpt-4o';
183
+ logger_1.logger.info(` 🤖 调用视觉模型(单图扫描): ${model}`);
184
+ // TODO: 接入真实视觉模型 API
185
+ // 当前返回模拟结果,后续替换为真实调用
186
+ // 视觉模型应分析:
187
+ // - 页面是否白屏/灰屏
188
+ // - 是否有明显的布局崩坏
189
+ // - 文字是否重叠或截断
190
+ // - 图片是否加载失败
191
+ // - 是否有明显的 UI 异常(弹窗报错、乱码等)
192
+ return {
193
+ passed: true,
194
+ analysis: '单图质量扫描完成,页面渲染正常,未发现明显的白屏、布局崩坏或文字重叠问题。',
195
+ issues: [],
196
+ };
197
+ }
198
+ catch (error) {
199
+ const message = error instanceof Error ? error.message : String(error);
200
+ return {
201
+ passed: options.threshold !== 'strict',
202
+ analysis: `单图扫描失败: ${message}`,
203
+ issues: [{
204
+ severity: 'warning',
205
+ description: `单图扫描失败: ${message}`,
206
+ }],
207
+ };
208
+ }
209
+ }
210
+ /**
211
+ * 检查视觉模型 API 是否可用
212
+ */
213
+ async function isVisualModelAvailable() {
214
+ // TODO: 检查 API key 是否配置
215
+ return false; // 当前未实现真实调用
216
+ }
217
+ //# sourceMappingURL=visual-engine.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"visual-engine.js","sourceRoot":"","sources":["../../../src/core/ui-verify/visual-engine.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "speccore",
3
- "version": "8.3.46",
3
+ "version": "8.3.48",
4
4
  "description": "SpecCore - Code by Spec, Not by Vibe.",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -38,7 +38,8 @@
38
38
  "fs-extra": "^11.2.0",
39
39
  "glob": "^10.3.10",
40
40
  "js-yaml": "^4.1.0",
41
- "jszip": "^3.10.1"
41
+ "jszip": "^3.10.1",
42
+ "playwright": "^1.62.1"
42
43
  },
43
44
  "devDependencies": {
44
45
  "@types/fs-extra": "^11.0.4",