speccore 8.3.49 → 8.3.51

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 (35) hide show
  1. package/README.md +33 -0
  2. package/dist/cli.js +5 -2
  3. package/dist/cli.js.map +1 -1
  4. package/dist/commands/analyze.d.ts.map +1 -1
  5. package/dist/commands/analyze.js +5 -2
  6. package/dist/commands/analyze.js.map +1 -1
  7. package/dist/commands/execute.js +6 -43
  8. package/dist/commands/execute.js.map +1 -1
  9. package/dist/commands/verify.d.ts +1 -0
  10. package/dist/commands/verify.d.ts.map +1 -1
  11. package/dist/commands/verify.js +31 -1
  12. package/dist/commands/verify.js.map +1 -1
  13. package/dist/core/quality-gate.d.ts +4 -0
  14. package/dist/core/quality-gate.d.ts.map +1 -1
  15. package/dist/core/quality-gate.js +5 -0
  16. package/dist/core/quality-gate.js.map +1 -1
  17. package/dist/core/ui-verify/types.d.ts +9 -2
  18. package/dist/core/ui-verify/types.d.ts.map +1 -1
  19. package/dist/core/ui-verify/visual-engine.d.ts +3 -6
  20. package/dist/core/ui-verify/visual-engine.d.ts.map +1 -1
  21. package/dist/core/ui-verify/visual-engine.js +48 -90
  22. package/dist/core/ui-verify/visual-engine.js.map +1 -1
  23. package/dist/core/ui-verify/visual-model-client.d.ts +33 -0
  24. package/dist/core/ui-verify/visual-model-client.d.ts.map +1 -0
  25. package/dist/core/ui-verify/visual-model-client.js +397 -0
  26. package/dist/core/ui-verify/visual-model-client.js.map +1 -0
  27. package/dist/core/unified-config.d.ts +13 -0
  28. package/dist/core/unified-config.d.ts.map +1 -1
  29. package/dist/core/unified-config.js +61 -0
  30. package/dist/core/unified-config.js.map +1 -1
  31. package/dist/core/verify-report-aggregator.d.ts +43 -0
  32. package/dist/core/verify-report-aggregator.d.ts.map +1 -0
  33. package/dist/core/verify-report-aggregator.js +406 -0
  34. package/dist/core/verify-report-aggregator.js.map +1 -0
  35. package/package.json +1 -1
@@ -0,0 +1,397 @@
1
+ "use strict";
2
+ /**
3
+ * Visual Model Client — 视觉模型调用客户端
4
+ *
5
+ * 支持多提供商切换:
6
+ * - qwen-vl: 阿里云 DashScope(默认)
7
+ * - openai: OpenAI GPT-4o
8
+ * - anthropic: Claude 3.5 Sonnet
9
+ * - local: 本地模型(OpenAI 兼容格式)
10
+ */
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.callVisualModel = callVisualModel;
13
+ exports.isVisualModelAvailable = isVisualModelAvailable;
14
+ const logger_1 = require("../../utils/logger");
15
+ // ─────────────────────────────────────────
16
+ // 主入口
17
+ // ─────────────────────────────────────────
18
+ async function callVisualModel(config, options) {
19
+ const provider = config.provider || 'qwen-vl';
20
+ switch (provider) {
21
+ case 'qwen-vl':
22
+ return callQwenVL(config, options);
23
+ case 'openai':
24
+ return callOpenAI(config, options);
25
+ case 'anthropic':
26
+ return callAnthropic(config, options);
27
+ case 'local':
28
+ return callLocalModel(config, options);
29
+ default:
30
+ throw new Error(`不支持的视觉模型提供商: ${provider}`);
31
+ }
32
+ }
33
+ // ─────────────────────────────────────────
34
+ // Qwen-VL(阿里云 DashScope)
35
+ // ─────────────────────────────────────────
36
+ async function callQwenVL(config, options) {
37
+ const apiKey = config.apiKey || process.env.DASHSCOPE_API_KEY;
38
+ if (!apiKey) {
39
+ throw new Error('未配置 DASHSCOPE_API_KEY,请在 .speccore.yml 或环境变量中设置');
40
+ }
41
+ const model = config.model || 'qwen-vl-max';
42
+ const endpoint = config.endpoint || 'https://dashscope.aliyuncs.com/compatible-mode/v1/chat/completions';
43
+ const timeout = config.timeout || 60000;
44
+ const prompt = buildPrompt(options.scenarioName, options.baselineImageBase64 ? 'compare' : 'single', options.threshold);
45
+ const messages = [
46
+ {
47
+ role: 'system',
48
+ content: '你是一个专业的 UI 视觉测试专家。请严格按照 JSON 格式输出分析结果。',
49
+ },
50
+ {
51
+ role: 'user',
52
+ content: [
53
+ { type: 'text', text: prompt },
54
+ {
55
+ type: 'image_url',
56
+ image_url: { url: `data:image/png;base64,${options.currentImageBase64}` },
57
+ },
58
+ ],
59
+ },
60
+ ];
61
+ // 如果有基准图,加入对比
62
+ if (options.baselineImageBase64) {
63
+ messages[1].content.push({
64
+ type: 'text',
65
+ text: '上方第一张是基准图(预期效果),第二张是当前截图(待检测)。',
66
+ });
67
+ messages[1].content.push({
68
+ type: 'image_url',
69
+ image_url: { url: `data:image/png;base64,${options.baselineImageBase64}` },
70
+ });
71
+ }
72
+ logger_1.logger.info(` 🤖 调用 Qwen-VL: ${model}`);
73
+ const controller = new AbortController();
74
+ const timer = setTimeout(() => controller.abort(), timeout);
75
+ try {
76
+ const response = await fetch(endpoint, {
77
+ method: 'POST',
78
+ headers: {
79
+ 'Content-Type': 'application/json',
80
+ 'Authorization': `Bearer ${apiKey}`,
81
+ },
82
+ body: JSON.stringify({
83
+ model,
84
+ messages,
85
+ max_tokens: 2000,
86
+ temperature: 0.1,
87
+ }),
88
+ signal: controller.signal,
89
+ });
90
+ clearTimeout(timer);
91
+ if (!response.ok) {
92
+ const errorText = await response.text();
93
+ throw new Error(`DashScope API 错误 (${response.status}): ${errorText}`);
94
+ }
95
+ const data = await response.json();
96
+ const content = data.choices?.[0]?.message?.content || '';
97
+ return parseModelResponse(content, options.threshold);
98
+ }
99
+ catch (error) {
100
+ if (error.name === 'AbortError') {
101
+ throw new Error(`Qwen-VL 请求超时 (${timeout}ms)`);
102
+ }
103
+ throw error;
104
+ }
105
+ }
106
+ // ─────────────────────────────────────────
107
+ // OpenAI GPT-4o
108
+ // ─────────────────────────────────────────
109
+ async function callOpenAI(config, options) {
110
+ const apiKey = config.apiKey || process.env.OPENAI_API_KEY;
111
+ if (!apiKey) {
112
+ throw new Error('未配置 OPENAI_API_KEY,请在 .speccore.yml 或环境变量中设置');
113
+ }
114
+ const model = config.model || 'gpt-4o';
115
+ const endpoint = config.endpoint || 'https://api.openai.com/v1/chat/completions';
116
+ const timeout = config.timeout || 60000;
117
+ const prompt = buildPrompt(options.scenarioName, options.baselineImageBase64 ? 'compare' : 'single', options.threshold);
118
+ const content = [
119
+ { type: 'text', text: prompt },
120
+ {
121
+ type: 'image_url',
122
+ image_url: { url: `data:image/png;base64,${options.currentImageBase64}` },
123
+ },
124
+ ];
125
+ if (options.baselineImageBase64) {
126
+ content.push({
127
+ type: 'image_url',
128
+ image_url: { url: `data:image/png;base64,${options.baselineImageBase64}` },
129
+ });
130
+ }
131
+ logger_1.logger.info(` 🤖 调用 OpenAI: ${model}`);
132
+ const controller = new AbortController();
133
+ const timer = setTimeout(() => controller.abort(), timeout);
134
+ try {
135
+ const response = await fetch(endpoint, {
136
+ method: 'POST',
137
+ headers: {
138
+ 'Content-Type': 'application/json',
139
+ 'Authorization': `Bearer ${apiKey}`,
140
+ },
141
+ body: JSON.stringify({
142
+ model,
143
+ messages: [{ role: 'user', content }],
144
+ max_tokens: 2000,
145
+ temperature: 0.1,
146
+ }),
147
+ signal: controller.signal,
148
+ });
149
+ clearTimeout(timer);
150
+ if (!response.ok) {
151
+ const errorText = await response.text();
152
+ throw new Error(`OpenAI API 错误 (${response.status}): ${errorText}`);
153
+ }
154
+ const data = await response.json();
155
+ const text = data.choices?.[0]?.message?.content || '';
156
+ return parseModelResponse(text, options.threshold);
157
+ }
158
+ catch (error) {
159
+ if (error.name === 'AbortError') {
160
+ throw new Error(`OpenAI 请求超时 (${timeout}ms)`);
161
+ }
162
+ throw error;
163
+ }
164
+ }
165
+ // ─────────────────────────────────────────
166
+ // Anthropic Claude
167
+ // ─────────────────────────────────────────
168
+ async function callAnthropic(config, options) {
169
+ const apiKey = config.apiKey || process.env.ANTHROPIC_API_KEY;
170
+ if (!apiKey) {
171
+ throw new Error('未配置 ANTHROPIC_API_KEY,请在 .speccore.yml 或环境变量中设置');
172
+ }
173
+ const model = config.model || 'claude-3-5-sonnet-20241022';
174
+ const endpoint = config.endpoint || 'https://api.anthropic.com/v1/messages';
175
+ const timeout = config.timeout || 60000;
176
+ const prompt = buildPrompt(options.scenarioName, options.baselineImageBase64 ? 'compare' : 'single', options.threshold);
177
+ const content = [
178
+ { type: 'text', text: prompt },
179
+ {
180
+ type: 'image',
181
+ source: {
182
+ type: 'base64',
183
+ media_type: 'image/png',
184
+ data: options.currentImageBase64,
185
+ },
186
+ },
187
+ ];
188
+ if (options.baselineImageBase64) {
189
+ content.push({
190
+ type: 'image',
191
+ source: {
192
+ type: 'base64',
193
+ media_type: 'image/png',
194
+ data: options.baselineImageBase64,
195
+ },
196
+ });
197
+ }
198
+ logger_1.logger.info(` 🤖 调用 Claude: ${model}`);
199
+ const controller = new AbortController();
200
+ const timer = setTimeout(() => controller.abort(), timeout);
201
+ try {
202
+ const response = await fetch(endpoint, {
203
+ method: 'POST',
204
+ headers: {
205
+ 'Content-Type': 'application/json',
206
+ 'x-api-key': apiKey,
207
+ 'anthropic-version': '2023-06-01',
208
+ },
209
+ body: JSON.stringify({
210
+ model,
211
+ max_tokens: 2000,
212
+ messages: [{ role: 'user', content }],
213
+ }),
214
+ signal: controller.signal,
215
+ });
216
+ clearTimeout(timer);
217
+ if (!response.ok) {
218
+ const errorText = await response.text();
219
+ throw new Error(`Anthropic API 错误 (${response.status}): ${errorText}`);
220
+ }
221
+ const data = await response.json();
222
+ const text = data.content?.[0]?.text || '';
223
+ return parseModelResponse(text, options.threshold);
224
+ }
225
+ catch (error) {
226
+ if (error.name === 'AbortError') {
227
+ throw new Error(`Claude 请求超时 (${timeout}ms)`);
228
+ }
229
+ throw error;
230
+ }
231
+ }
232
+ // ─────────────────────────────────────────
233
+ // 本地模型(预留)
234
+ // ─────────────────────────────────────────
235
+ async function callLocalModel(config, options) {
236
+ const endpoint = config.endpoint || 'http://localhost:8000/v1/chat/completions';
237
+ const model = config.model || 'local-vision-model';
238
+ const timeout = config.timeout || 120000;
239
+ logger_1.logger.info(` 🤖 调用本地模型: ${endpoint}`);
240
+ const prompt = buildPrompt(options.scenarioName, options.baselineImageBase64 ? 'compare' : 'single', options.threshold);
241
+ const messages = [
242
+ {
243
+ role: 'user',
244
+ content: [
245
+ { type: 'text', text: prompt },
246
+ {
247
+ type: 'image_url',
248
+ image_url: { url: `data:image/png;base64,${options.currentImageBase64}` },
249
+ },
250
+ ],
251
+ },
252
+ ];
253
+ if (options.baselineImageBase64) {
254
+ messages[0].content.push({
255
+ type: 'image_url',
256
+ image_url: { url: `data:image/png;base64,${options.baselineImageBase64}` },
257
+ });
258
+ }
259
+ const controller = new AbortController();
260
+ const timer = setTimeout(() => controller.abort(), timeout);
261
+ try {
262
+ const response = await fetch(endpoint, {
263
+ method: 'POST',
264
+ headers: { 'Content-Type': 'application/json' },
265
+ body: JSON.stringify({ model, messages, max_tokens: 2000 }),
266
+ signal: controller.signal,
267
+ });
268
+ clearTimeout(timer);
269
+ if (!response.ok) {
270
+ const errorText = await response.text();
271
+ throw new Error(`本地模型错误 (${response.status}): ${errorText}`);
272
+ }
273
+ const data = await response.json();
274
+ const text = data.choices?.[0]?.message?.content || '';
275
+ return parseModelResponse(text, options.threshold);
276
+ }
277
+ catch (error) {
278
+ if (error.name === 'AbortError') {
279
+ throw new Error(`本地模型请求超时 (${timeout}ms)`);
280
+ }
281
+ throw error;
282
+ }
283
+ }
284
+ // ─────────────────────────────────────────
285
+ // Prompt 构建
286
+ // ─────────────────────────────────────────
287
+ function buildPrompt(scenarioName, mode, threshold) {
288
+ const strictness = threshold === 'strict'
289
+ ? '非常严格:任何微小的视觉差异都应视为问题。'
290
+ : threshold === 'normal'
291
+ ? '正常标准:明显的布局偏移、元素缺失、颜色变化视为问题,微小像素差异可忽略。'
292
+ : '宽松标准:只关注严重的视觉问题(如白屏、元素大面积缺失、明显崩坏)。';
293
+ if (mode === 'compare') {
294
+ return `请对比分析「${scenarioName}」的基准图和当前截图的视觉差异。
295
+
296
+ 检测标准:${strictness}
297
+
298
+ 请重点检查以下问题:
299
+ 1. 布局偏移:元素位置是否发生明显变化
300
+ 2. 元素缺失/新增:是否有元素消失或出现新元素
301
+ 3. 颜色变化:背景色、文字色、按钮色是否改变
302
+ 4. 文字变动:文案内容、字体大小是否变化
303
+ 5. 图片加载:图片是否正常显示,有无裂图
304
+ 6. 明显崩坏:CSS 样式是否失效,布局是否混乱
305
+
306
+ 请严格按照以下 JSON 格式输出结果,不要输出其他内容:
307
+ {
308
+ "passed": true/false,
309
+ "analysis": "总体分析结论(中文,200字以内)",
310
+ "issues": [
311
+ {
312
+ "severity": "critical/warning/info",
313
+ "description": "问题描述(中文)",
314
+ "region": "问题区域(如:顶部导航栏/登录表单)"
315
+ }
316
+ ]
317
+ }`;
318
+ }
319
+ return `请分析「${scenarioName}」的当前截图,进行通用 UI 质量扫描。
320
+
321
+ 检测标准:${strictness}
322
+
323
+ 请重点检查以下问题:
324
+ 1. 白屏/灰屏:页面是否正常渲染
325
+ 2. 布局崩坏:是否有明显的 CSS 失效、元素重叠、溢出
326
+ 3. 文字问题:文字是否重叠、截断、乱码
327
+ 4. 图片加载:图片是否正常显示,有无裂图图标
328
+ 5. UI 异常:是否有明显的报错弹窗、空白区域、按钮不可点击
329
+ 6. 响应式问题:在不同尺寸下是否有明显的适配问题
330
+
331
+ 请严格按照以下 JSON 格式输出结果,不要输出其他内容:
332
+ {
333
+ "passed": true/false,
334
+ "analysis": "总体分析结论(中文,200字以内)",
335
+ "issues": [
336
+ {
337
+ "severity": "critical/warning/info",
338
+ "description": "问题描述(中文)",
339
+ "region": "问题区域(如:顶部导航栏/登录表单)"
340
+ }
341
+ ]
342
+ }`;
343
+ }
344
+ // ─────────────────────────────────────────
345
+ // 响应解析
346
+ // ─────────────────────────────────────────
347
+ function parseModelResponse(text, threshold) {
348
+ // 尝试从文本中提取 JSON
349
+ const jsonMatch = text.match(/\{[\s\S]*\}/);
350
+ if (!jsonMatch) {
351
+ // 没有 JSON,按纯文本处理
352
+ return {
353
+ passed: threshold !== 'strict',
354
+ analysis: text.slice(0, 500),
355
+ issues: [],
356
+ };
357
+ }
358
+ try {
359
+ const parsed = JSON.parse(jsonMatch[0]);
360
+ return {
361
+ passed: parsed.passed ?? true,
362
+ analysis: parsed.analysis || '未提供分析',
363
+ issues: (parsed.issues || []).map((i) => ({
364
+ severity: i.severity || 'info',
365
+ description: i.description || '',
366
+ region: i.region,
367
+ })),
368
+ };
369
+ }
370
+ catch {
371
+ return {
372
+ passed: threshold !== 'strict',
373
+ analysis: text.slice(0, 500),
374
+ issues: [],
375
+ };
376
+ }
377
+ }
378
+ // ─────────────────────────────────────────
379
+ // 配置可用性检查
380
+ // ─────────────────────────────────────────
381
+ async function isVisualModelAvailable(config) {
382
+ if (!config)
383
+ return false;
384
+ const envKeys = {
385
+ 'qwen-vl': 'DASHSCOPE_API_KEY',
386
+ 'openai': 'OPENAI_API_KEY',
387
+ 'anthropic': 'ANTHROPIC_API_KEY',
388
+ 'local': '',
389
+ };
390
+ if (config.apiKey)
391
+ return true;
392
+ if (config.provider === 'local')
393
+ return true;
394
+ const envKey = envKeys[config.provider];
395
+ return envKey ? !!process.env[envKey] : false;
396
+ }
397
+ //# sourceMappingURL=visual-model-client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"visual-model-client.js","sourceRoot":"","sources":["../../../src/core/ui-verify/visual-model-client.ts"],"names":[],"mappings":"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"}
@@ -42,6 +42,19 @@ export interface SpecConfig {
42
42
  devices: string[];
43
43
  browsers: string[];
44
44
  timeout: number;
45
+ /** 视觉模型配置 */
46
+ visual_model?: {
47
+ /** 提供商: qwen-vl(默认) | openai | anthropic | local */
48
+ provider: 'qwen-vl' | 'openai' | 'anthropic' | 'local';
49
+ /** 模型名称 */
50
+ model?: string;
51
+ /** API Key(可选,默认从环境变量读取) */
52
+ apiKey?: string;
53
+ /** 自定义端点(可选) */
54
+ endpoint?: string;
55
+ /** 请求超时(毫秒,默认 60000) */
56
+ timeout?: number;
57
+ };
45
58
  };
46
59
  };
47
60
  arbitration: {
@@ -1 +1 @@
1
- {"version":3,"file":"unified-config.d.ts","sourceRoot":"","sources":["../../src/core/unified-config.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"unified-config.d.ts","sourceRoot":"","sources":["../../src/core/unified-config.ts"],"names":[],"mappings":"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"}
@@ -49,6 +49,10 @@ exports.DEFAULT_CONFIG = {
49
49
  devices: ['desktop'],
50
50
  browsers: ['chromium'],
51
51
  timeout: 30000,
52
+ visual_model: {
53
+ provider: 'qwen-vl',
54
+ model: 'qwen-vl-max',
55
+ },
52
56
  },
53
57
  },
54
58
  arbitration: { enabled: true, mode: 'full' },
@@ -656,6 +660,22 @@ function validateConfig(obj) {
656
660
  if (vui.timeout !== undefined && typeof vui.timeout !== 'number') {
657
661
  issues.push('quality_gates.verify_ui.timeout 必须是数字');
658
662
  }
663
+ // visual_model 校验
664
+ if (vui.visual_model !== undefined) {
665
+ if (!isObject(vui.visual_model)) {
666
+ issues.push('quality_gates.verify_ui.visual_model 必须是对象');
667
+ }
668
+ else {
669
+ const vm = vui.visual_model;
670
+ const providers = ['qwen-vl', 'openai', 'anthropic', 'local'];
671
+ if (vm.provider && !providers.includes(vm.provider)) {
672
+ issues.push(`quality_gates.verify_ui.visual_model.provider 必须是 ${providers.join('/')} 之一`);
673
+ }
674
+ if (vm.timeout !== undefined && typeof vm.timeout !== 'number') {
675
+ issues.push('quality_gates.verify_ui.visual_model.timeout 必须是数字');
676
+ }
677
+ }
678
+ }
659
679
  }
660
680
  }
661
681
  // arbitration
@@ -824,6 +844,47 @@ function toYaml(config) {
824
844
  yaml += ' # require_pr: 是否强制通过 PR 合并代码\n';
825
845
  yaml += ' # true → 禁止直接 push 到保护分支,必须通过 speccore pr 提交\n';
826
846
  yaml += ` require_pr: ${config.quality_gates.require_pr}\n`;
847
+ // verify_ui 配置
848
+ const vui = config.quality_gates.verify_ui;
849
+ if (vui) {
850
+ yaml += '\n # ── UI 验证(v8.3.47+)──\n';
851
+ yaml += ' verify_ui:\n';
852
+ yaml += ' # enabled: 是否启用 UI 验证(冒烟测试 + 视觉检查)\n';
853
+ yaml += ` enabled: ${vui.enabled}\n`;
854
+ yaml += ' # smoke_test: 是否执行冒烟测试\n';
855
+ yaml += ` smoke_test: ${vui.smoke_test}\n`;
856
+ yaml += ' # visual_check: 是否执行视觉检查\n';
857
+ yaml += ` visual_check: ${vui.visual_check}\n`;
858
+ yaml += ' # threshold: 检测严格度\n';
859
+ yaml += ' # strict → 任何微小差异都视为问题\n';
860
+ yaml += ' # normal → 明显差异视为问题\n';
861
+ yaml += ' # loose → 仅严重问题\n';
862
+ yaml += ` threshold: ${vui.threshold}\n`;
863
+ yaml += ' # devices: 测试设备列表\n';
864
+ yaml += ` devices: [${vui.devices.map((d) => `'${d}'`).join(', ')}]\n`;
865
+ yaml += ' # browsers: 测试浏览器列表\n';
866
+ yaml += ` browsers: [${vui.browsers.map((b) => `'${b}'`).join(', ')}]\n`;
867
+ yaml += ' # timeout: 单场景超时(毫秒)\n';
868
+ yaml += ` timeout: ${vui.timeout}\n`;
869
+ if (vui.visual_model) {
870
+ yaml += ' # visual_model: 视觉模型配置(v8.3.50+)\n';
871
+ yaml += ' # provider: qwen-vl(默认) | openai | anthropic | local\n';
872
+ yaml += ' # model: 模型名称(可选)\n';
873
+ yaml += ' # apiKey: API Key(可选,默认从环境变量读取)\n';
874
+ yaml += ' # endpoint: 自定义端点(可选)\n';
875
+ yaml += ' # timeout: 请求超时(毫秒,可选)\n';
876
+ yaml += ' visual_model:\n';
877
+ yaml += ` provider: ${vui.visual_model.provider}\n`;
878
+ if (vui.visual_model.model)
879
+ yaml += ` model: ${vui.visual_model.model}\n`;
880
+ if (vui.visual_model.apiKey)
881
+ yaml += ` apiKey: ${vui.visual_model.apiKey}\n`;
882
+ if (vui.visual_model.endpoint)
883
+ yaml += ` endpoint: ${vui.visual_model.endpoint}\n`;
884
+ if (vui.visual_model.timeout)
885
+ yaml += ` timeout: ${vui.visual_model.timeout}\n`;
886
+ }
887
+ }
827
888
  yaml += '\n# ─────────────────────────────────────────────────────────────────────────────\n';
828
889
  yaml += '# 契约冲突裁决(Arbitration)\n';
829
890
  yaml += '# ─────────────────────────────────────────────────────────────────────────────\n';