@lutery/vision-mcp 1.0.0
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.
- package/README.md +428 -0
- package/dist/adapters/base-adapter.d.ts +69 -0
- package/dist/adapters/base-adapter.d.ts.map +1 -0
- package/dist/adapters/base-adapter.js +143 -0
- package/dist/adapters/base-adapter.js.map +1 -0
- package/dist/adapters/claude-adapter.d.ts +38 -0
- package/dist/adapters/claude-adapter.d.ts.map +1 -0
- package/dist/adapters/claude-adapter.js +251 -0
- package/dist/adapters/claude-adapter.js.map +1 -0
- package/dist/adapters/glm-adapter.d.ts +15 -0
- package/dist/adapters/glm-adapter.d.ts.map +1 -0
- package/dist/adapters/glm-adapter.js +131 -0
- package/dist/adapters/glm-adapter.js.map +1 -0
- package/dist/adapters/modelscope-adapter.d.ts +20 -0
- package/dist/adapters/modelscope-adapter.d.ts.map +1 -0
- package/dist/adapters/modelscope-adapter.js +142 -0
- package/dist/adapters/modelscope-adapter.js.map +1 -0
- package/dist/adapters/openai-adapter.d.ts +20 -0
- package/dist/adapters/openai-adapter.d.ts.map +1 -0
- package/dist/adapters/openai-adapter.js +194 -0
- package/dist/adapters/openai-adapter.js.map +1 -0
- package/dist/adapters/siliconflow-adapter.d.ts +21 -0
- package/dist/adapters/siliconflow-adapter.d.ts.map +1 -0
- package/dist/adapters/siliconflow-adapter.js +145 -0
- package/dist/adapters/siliconflow-adapter.js.map +1 -0
- package/dist/config/model-config.d.ts +39 -0
- package/dist/config/model-config.d.ts.map +1 -0
- package/dist/config/model-config.js +115 -0
- package/dist/config/model-config.js.map +1 -0
- package/dist/index.d.ts +17 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +186 -0
- package/dist/index.js.map +1 -0
- package/dist/prompts/system.d.ts +75 -0
- package/dist/prompts/system.d.ts.map +1 -0
- package/dist/prompts/system.js +272 -0
- package/dist/prompts/system.js.map +1 -0
- package/dist/providers/provider-registry.d.ts +58 -0
- package/dist/providers/provider-registry.d.ts.map +1 -0
- package/dist/providers/provider-registry.js +173 -0
- package/dist/providers/provider-registry.js.map +1 -0
- package/dist/src/adapters/base-adapter.d.ts +59 -0
- package/dist/src/adapters/base-adapter.d.ts.map +1 -0
- package/dist/src/adapters/base-adapter.js +83 -0
- package/dist/src/adapters/base-adapter.js.map +1 -0
- package/dist/src/adapters/glm-adapter.d.ts +15 -0
- package/dist/src/adapters/glm-adapter.d.ts.map +1 -0
- package/dist/src/adapters/glm-adapter.js +116 -0
- package/dist/src/adapters/glm-adapter.js.map +1 -0
- package/dist/src/adapters/siliconflow-adapter.d.ts +21 -0
- package/dist/src/adapters/siliconflow-adapter.d.ts.map +1 -0
- package/dist/src/adapters/siliconflow-adapter.js +130 -0
- package/dist/src/adapters/siliconflow-adapter.js.map +1 -0
- package/dist/src/config/model-config.d.ts +40 -0
- package/dist/src/config/model-config.d.ts.map +1 -0
- package/dist/src/config/model-config.js +126 -0
- package/dist/src/config/model-config.js.map +1 -0
- package/dist/src/index.d.ts +17 -0
- package/dist/src/index.d.ts.map +1 -0
- package/dist/src/index.js +188 -0
- package/dist/src/index.js.map +1 -0
- package/dist/src/prompts/system.d.ts +75 -0
- package/dist/src/prompts/system.d.ts.map +1 -0
- package/dist/src/prompts/system.js +272 -0
- package/dist/src/prompts/system.js.map +1 -0
- package/dist/src/tools/vision-tool.d.ts +91 -0
- package/dist/src/tools/vision-tool.d.ts.map +1 -0
- package/dist/src/tools/vision-tool.js +171 -0
- package/dist/src/tools/vision-tool.js.map +1 -0
- package/dist/src/utils/errors.d.ts +65 -0
- package/dist/src/utils/errors.d.ts.map +1 -0
- package/dist/src/utils/errors.js +146 -0
- package/dist/src/utils/errors.js.map +1 -0
- package/dist/src/utils/image-input.d.ts +45 -0
- package/dist/src/utils/image-input.d.ts.map +1 -0
- package/dist/src/utils/image-input.js +226 -0
- package/dist/src/utils/image-input.js.map +1 -0
- package/dist/src/utils/logger.d.ts +63 -0
- package/dist/src/utils/logger.d.ts.map +1 -0
- package/dist/src/utils/logger.js +157 -0
- package/dist/src/utils/logger.js.map +1 -0
- package/dist/test/integration.test.d.ts +10 -0
- package/dist/test/integration.test.d.ts.map +1 -0
- package/dist/test/integration.test.js +270 -0
- package/dist/test/integration.test.js.map +1 -0
- package/dist/test/test-utils.d.ts +45 -0
- package/dist/test/test-utils.d.ts.map +1 -0
- package/dist/test/test-utils.js +107 -0
- package/dist/test/test-utils.js.map +1 -0
- package/dist/test/vision-tool.test.d.ts +9 -0
- package/dist/test/vision-tool.test.d.ts.map +1 -0
- package/dist/test/vision-tool.test.js +167 -0
- package/dist/test/vision-tool.test.js.map +1 -0
- package/dist/tools/vision-tool.d.ts +91 -0
- package/dist/tools/vision-tool.d.ts.map +1 -0
- package/dist/tools/vision-tool.js +167 -0
- package/dist/tools/vision-tool.js.map +1 -0
- package/dist/utils/data-url-parser.d.ts +27 -0
- package/dist/utils/data-url-parser.d.ts.map +1 -0
- package/dist/utils/data-url-parser.js +53 -0
- package/dist/utils/data-url-parser.js.map +1 -0
- package/dist/utils/errors.d.ts +65 -0
- package/dist/utils/errors.d.ts.map +1 -0
- package/dist/utils/errors.js +146 -0
- package/dist/utils/errors.js.map +1 -0
- package/dist/utils/image-input.d.ts +45 -0
- package/dist/utils/image-input.d.ts.map +1 -0
- package/dist/utils/image-input.js +238 -0
- package/dist/utils/image-input.js.map +1 -0
- package/dist/utils/logger.d.ts +63 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +157 -0
- package/dist/utils/logger.js.map +1 -0
- package/dist/utils/thinking-extractors.d.ts +34 -0
- package/dist/utils/thinking-extractors.d.ts.map +1 -0
- package/dist/utils/thinking-extractors.js +83 -0
- package/dist/utils/thinking-extractors.js.map +1 -0
- package/dist/utils/thinking-filter.d.ts +32 -0
- package/dist/utils/thinking-filter.d.ts.map +1 -0
- package/dist/utils/thinking-filter.js +147 -0
- package/dist/utils/thinking-filter.js.map +1 -0
- package/package.json +41 -0
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Vision Tool
|
|
3
|
+
*
|
|
4
|
+
* @description MCP 视觉分析工具,提供统一的图片分析接口
|
|
5
|
+
*/
|
|
6
|
+
import { z } from 'zod';
|
|
7
|
+
import { ModelConfig } from '../config/model-config.js';
|
|
8
|
+
/**
|
|
9
|
+
* 工具参数 Schema
|
|
10
|
+
*/
|
|
11
|
+
export declare const VisionToolInputSchema: z.ZodObject<{
|
|
12
|
+
/**
|
|
13
|
+
* 图片输入:支持 URL、base64(data URL) 或本地路径
|
|
14
|
+
* @example "https://example.com/image.jpg"
|
|
15
|
+
* @example "data:image/jpeg;base64,/9j/4AAQ..."
|
|
16
|
+
* @example "/path/to/local/image.png"
|
|
17
|
+
*/
|
|
18
|
+
image: z.ZodString;
|
|
19
|
+
/**
|
|
20
|
+
* 分析提示词:描述要执行的分析任务
|
|
21
|
+
* @example "Describe this UI design and extract all components"
|
|
22
|
+
* @example "Detect objects and provide their coordinates"
|
|
23
|
+
* @example "Extract text using OCR"
|
|
24
|
+
*/
|
|
25
|
+
prompt: z.ZodString;
|
|
26
|
+
/**
|
|
27
|
+
* 输出格式:可选,指定为 "text" 或 "json"
|
|
28
|
+
* @default "text"
|
|
29
|
+
*/
|
|
30
|
+
output_format: z.ZodDefault<z.ZodOptional<z.ZodEnum<["text", "json"]>>>;
|
|
31
|
+
/**
|
|
32
|
+
* 系统提示词模板:可选,指定使用的模板
|
|
33
|
+
* @default auto-detected based on prompt
|
|
34
|
+
* @example "ui-analysis"
|
|
35
|
+
* @example "object-detection"
|
|
36
|
+
*/
|
|
37
|
+
template: z.ZodOptional<z.ZodString>;
|
|
38
|
+
}, "strict", z.ZodTypeAny, {
|
|
39
|
+
image: string;
|
|
40
|
+
prompt: string;
|
|
41
|
+
output_format: "text" | "json";
|
|
42
|
+
template?: string | undefined;
|
|
43
|
+
}, {
|
|
44
|
+
image: string;
|
|
45
|
+
prompt: string;
|
|
46
|
+
output_format?: "text" | "json" | undefined;
|
|
47
|
+
template?: string | undefined;
|
|
48
|
+
}>;
|
|
49
|
+
export type VisionToolInput = z.infer<typeof VisionToolInputSchema>;
|
|
50
|
+
/**
|
|
51
|
+
* 工具响应格式
|
|
52
|
+
*/
|
|
53
|
+
export interface VisionToolResponse {
|
|
54
|
+
content: string;
|
|
55
|
+
format: 'text' | 'json';
|
|
56
|
+
metadata: {
|
|
57
|
+
modelType: string;
|
|
58
|
+
modelName: string;
|
|
59
|
+
imageFormat: string;
|
|
60
|
+
processingTimeMs: number;
|
|
61
|
+
imageSize: number;
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* 视觉工具类
|
|
66
|
+
*/
|
|
67
|
+
export declare class VisionTool {
|
|
68
|
+
private modelConfig;
|
|
69
|
+
private adapter;
|
|
70
|
+
constructor(config?: ModelConfig);
|
|
71
|
+
/**
|
|
72
|
+
* 创建模型适配器(使用 registry)
|
|
73
|
+
*/
|
|
74
|
+
private createAdapter;
|
|
75
|
+
/**
|
|
76
|
+
* 执行视觉分析
|
|
77
|
+
*/
|
|
78
|
+
analyze(input: VisionToolInput): Promise<VisionToolResponse>;
|
|
79
|
+
/**
|
|
80
|
+
* 构建元数据
|
|
81
|
+
*/
|
|
82
|
+
private buildMetadata;
|
|
83
|
+
/**
|
|
84
|
+
* 获取工具信息
|
|
85
|
+
*/
|
|
86
|
+
getToolInfo(): {
|
|
87
|
+
modelConfig: ModelConfig;
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
export declare function getVisionTool(config?: ModelConfig): VisionTool;
|
|
91
|
+
//# sourceMappingURL=vision-tool.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"vision-tool.d.ts","sourceRoot":"","sources":["../../src/tools/vision-tool.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,WAAW,EAAwC,MAAM,2BAA2B,CAAC;AAQ9F;;GAEG;AACH,eAAO,MAAM,qBAAqB;IAChC;;;;;OAKG;;IAGH;;;;;OAKG;;IAGH;;;OAGG;;IAGH;;;;;OAKG;;;;;;;;;;;;EAEM,CAAC;AAEZ,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,qBAAqB,CAAC,CAAC;AAEpE;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC;IACxB,QAAQ,EAAE;QACR,SAAS,EAAE,MAAM,CAAC;QAClB,SAAS,EAAE,MAAM,CAAC;QAClB,WAAW,EAAE,MAAM,CAAC;QACpB,gBAAgB,EAAE,MAAM,CAAC;QACzB,SAAS,EAAE,MAAM,CAAC;KACnB,CAAC;CACH;AAED;;GAEG;AACH,qBAAa,UAAU;IACrB,OAAO,CAAC,WAAW,CAAc;IACjC,OAAO,CAAC,OAAO,CAAqB;gBAExB,MAAM,CAAC,EAAE,WAAW;IAgBhC;;OAEG;IACH,OAAO,CAAC,aAAa;IASrB;;OAEG;IACU,OAAO,CAAC,KAAK,EAAE,eAAe,GAAG,OAAO,CAAC,kBAAkB,CAAC;IA2EzE;;OAEG;IACH,OAAO,CAAC,aAAa;IAUrB;;OAEG;IACI,WAAW,IAAI;QACpB,WAAW,EAAE,WAAW,CAAC;KAC1B;CAKF;AAOD,wBAAgB,aAAa,CAAC,MAAM,CAAC,EAAE,WAAW,GAAG,UAAU,CAK9D"}
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Vision Tool
|
|
3
|
+
*
|
|
4
|
+
* @description MCP 视觉分析工具,提供统一的图片分析接口
|
|
5
|
+
*/
|
|
6
|
+
import { z } from 'zod';
|
|
7
|
+
import { loadModelConfig, validateModelConfig } from '../config/model-config.js';
|
|
8
|
+
import { normalizeImageInput } from '../utils/image-input.js';
|
|
9
|
+
import { ModelConfigError } from '../utils/errors.js';
|
|
10
|
+
import { logger } from '../utils/logger.js';
|
|
11
|
+
import { buildPrompt } from '../prompts/system.js';
|
|
12
|
+
import { registry } from '../providers/provider-registry.js';
|
|
13
|
+
/**
|
|
14
|
+
* 工具参数 Schema
|
|
15
|
+
*/
|
|
16
|
+
export const VisionToolInputSchema = z.object({
|
|
17
|
+
/**
|
|
18
|
+
* 图片输入:支持 URL、base64(data URL) 或本地路径
|
|
19
|
+
* @example "https://example.com/image.jpg"
|
|
20
|
+
* @example "data:image/jpeg;base64,/9j/4AAQ..."
|
|
21
|
+
* @example "/path/to/local/image.png"
|
|
22
|
+
*/
|
|
23
|
+
image: z.string().describe('Image URL, base64 data URL, or local file path'),
|
|
24
|
+
/**
|
|
25
|
+
* 分析提示词:描述要执行的分析任务
|
|
26
|
+
* @example "Describe this UI design and extract all components"
|
|
27
|
+
* @example "Detect objects and provide their coordinates"
|
|
28
|
+
* @example "Extract text using OCR"
|
|
29
|
+
*/
|
|
30
|
+
prompt: z.string().describe('Analysis prompt describing the task'),
|
|
31
|
+
/**
|
|
32
|
+
* 输出格式:可选,指定为 "text" 或 "json"
|
|
33
|
+
* @default "text"
|
|
34
|
+
*/
|
|
35
|
+
output_format: z.enum(['text', 'json']).optional().default('text').describe('Output format preference'),
|
|
36
|
+
/**
|
|
37
|
+
* 系统提示词模板:可选,指定使用的模板
|
|
38
|
+
* @default auto-detected based on prompt
|
|
39
|
+
* @example "ui-analysis"
|
|
40
|
+
* @example "object-detection"
|
|
41
|
+
*/
|
|
42
|
+
template: z.string().optional().describe('System prompt template to use')
|
|
43
|
+
}).strict();
|
|
44
|
+
/**
|
|
45
|
+
* 视觉工具类
|
|
46
|
+
*/
|
|
47
|
+
export class VisionTool {
|
|
48
|
+
modelConfig;
|
|
49
|
+
adapter;
|
|
50
|
+
constructor(config) {
|
|
51
|
+
// 加载配置
|
|
52
|
+
this.modelConfig = config || loadModelConfig();
|
|
53
|
+
// 验证配置
|
|
54
|
+
validateModelConfig(this.modelConfig);
|
|
55
|
+
// 创建适配器
|
|
56
|
+
this.adapter = this.createAdapter(this.modelConfig);
|
|
57
|
+
logger.info('Vision tool initialized', {
|
|
58
|
+
modelType: this.modelConfig.type,
|
|
59
|
+
modelName: this.modelConfig.name
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* 创建模型适配器(使用 registry)
|
|
64
|
+
*/
|
|
65
|
+
createAdapter(config) {
|
|
66
|
+
const provider = registry.get(config.type);
|
|
67
|
+
if (!provider) {
|
|
68
|
+
throw new ModelConfigError(`Unsupported model type: ${config.type}`);
|
|
69
|
+
}
|
|
70
|
+
return provider.createAdapter(config);
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* 执行视觉分析
|
|
74
|
+
*/
|
|
75
|
+
async analyze(input) {
|
|
76
|
+
const startTime = Date.now();
|
|
77
|
+
const requestId = Math.random().toString(36).substring(7);
|
|
78
|
+
logger.logRequest('Vision analysis started', {
|
|
79
|
+
requestId,
|
|
80
|
+
modelType: this.modelConfig.type,
|
|
81
|
+
imageInputLength: input.image.length,
|
|
82
|
+
hasTemplate: !!input.template
|
|
83
|
+
});
|
|
84
|
+
try {
|
|
85
|
+
// 1. 规范化图片输入
|
|
86
|
+
logger.debug('Normalizing image input', { requestId });
|
|
87
|
+
const normalizedImage = await normalizeImageInput(input.image);
|
|
88
|
+
logger.debug('Image normalized successfully', {
|
|
89
|
+
requestId,
|
|
90
|
+
type: normalizedImage.type,
|
|
91
|
+
mimeType: normalizedImage.mimeType,
|
|
92
|
+
dataLength: normalizedImage.dataUrl.length
|
|
93
|
+
});
|
|
94
|
+
// 2. 构建完整提示词
|
|
95
|
+
logger.debug('Building prompt', { requestId });
|
|
96
|
+
const fullPrompt = buildPrompt(input.template, input.prompt);
|
|
97
|
+
logger.debug('Prompt built', {
|
|
98
|
+
requestId,
|
|
99
|
+
promptLength: fullPrompt.length,
|
|
100
|
+
templateUsed: input.template || 'auto-detected'
|
|
101
|
+
});
|
|
102
|
+
// 3. 调用视觉模型
|
|
103
|
+
logger.logRequest('Calling vision model', {
|
|
104
|
+
requestId,
|
|
105
|
+
modelType: this.modelConfig.type,
|
|
106
|
+
modelName: this.modelConfig.name
|
|
107
|
+
});
|
|
108
|
+
const modelResponse = await this.adapter.analyzeWithResponse(normalizedImage.dataUrl, fullPrompt);
|
|
109
|
+
// 4. 构建响应
|
|
110
|
+
const response = {
|
|
111
|
+
content: modelResponse.content,
|
|
112
|
+
format: input.output_format,
|
|
113
|
+
metadata: {
|
|
114
|
+
modelType: this.modelConfig.type,
|
|
115
|
+
modelName: this.modelConfig.name,
|
|
116
|
+
imageFormat: normalizedImage.mimeType,
|
|
117
|
+
processingTimeMs: Date.now() - startTime,
|
|
118
|
+
imageSize: normalizedImage.dataUrl.length
|
|
119
|
+
}
|
|
120
|
+
};
|
|
121
|
+
logger.logRequest('Vision analysis completed', {
|
|
122
|
+
requestId,
|
|
123
|
+
processingTimeMs: response.metadata.processingTimeMs,
|
|
124
|
+
outputLength: response.content.length
|
|
125
|
+
});
|
|
126
|
+
return response;
|
|
127
|
+
}
|
|
128
|
+
catch (error) {
|
|
129
|
+
logger.error('Vision analysis failed', error, {
|
|
130
|
+
requestId,
|
|
131
|
+
processingTimeMs: Date.now() - startTime
|
|
132
|
+
});
|
|
133
|
+
throw error;
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* 构建元数据
|
|
138
|
+
*/
|
|
139
|
+
buildMetadata(normalizedImage, startTime) {
|
|
140
|
+
return {
|
|
141
|
+
modelType: this.modelConfig.type,
|
|
142
|
+
modelName: this.modelConfig.name,
|
|
143
|
+
imageFormat: normalizedImage.mimeType,
|
|
144
|
+
processingTimeMs: Date.now() - startTime,
|
|
145
|
+
imageSize: normalizedImage.dataUrl.length
|
|
146
|
+
};
|
|
147
|
+
}
|
|
148
|
+
/**
|
|
149
|
+
* 获取工具信息
|
|
150
|
+
*/
|
|
151
|
+
getToolInfo() {
|
|
152
|
+
return {
|
|
153
|
+
modelConfig: this.modelConfig
|
|
154
|
+
};
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
/**
|
|
158
|
+
* 创建工具实例(单例模式)
|
|
159
|
+
*/
|
|
160
|
+
let toolInstance;
|
|
161
|
+
export function getVisionTool(config) {
|
|
162
|
+
if (!toolInstance) {
|
|
163
|
+
toolInstance = new VisionTool(config);
|
|
164
|
+
}
|
|
165
|
+
return toolInstance;
|
|
166
|
+
}
|
|
167
|
+
//# sourceMappingURL=vision-tool.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"vision-tool.js","sourceRoot":"","sources":["../../src/tools/vision-tool.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Data URL Parser Utility
|
|
3
|
+
*
|
|
4
|
+
* @description 解析 data URL 格式,将 data:image/png;base64,... 拆解为 mimeType 和 base64 data
|
|
5
|
+
* 用于 Claude API 适配器,因为 Claude 需要单独的 media_type 和 base64 data 字段
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* 解析后的 data URL 结构
|
|
9
|
+
*/
|
|
10
|
+
export interface ParsedDataUrl {
|
|
11
|
+
mimeType: string;
|
|
12
|
+
data: string;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* 解析 data URL
|
|
16
|
+
* @param dataUrl - data:image/png;base64,iVBORw0KG...
|
|
17
|
+
* @returns { mimeType, data }
|
|
18
|
+
* @throws {Error} 如果 data URL 格式无效
|
|
19
|
+
*/
|
|
20
|
+
export declare function parseDataUrl(dataUrl: string): ParsedDataUrl;
|
|
21
|
+
/**
|
|
22
|
+
* 检查是否为 data URL
|
|
23
|
+
* @param value - 待检查的字符串
|
|
24
|
+
* @returns 是否为 data URL
|
|
25
|
+
*/
|
|
26
|
+
export declare function isDataUrl(value: string): boolean;
|
|
27
|
+
//# sourceMappingURL=data-url-parser.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"data-url-parser.d.ts","sourceRoot":"","sources":["../../src/utils/data-url-parser.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;CACd;AAED;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,GAAG,aAAa,CAuC3D;AAED;;;;GAIG;AACH,wBAAgB,SAAS,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAEhD"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Data URL Parser Utility
|
|
3
|
+
*
|
|
4
|
+
* @description 解析 data URL 格式,将 data:image/png;base64,... 拆解为 mimeType 和 base64 data
|
|
5
|
+
* 用于 Claude API 适配器,因为 Claude 需要单独的 media_type 和 base64 data 字段
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* 解析 data URL
|
|
9
|
+
* @param dataUrl - data:image/png;base64,iVBORw0KG...
|
|
10
|
+
* @returns { mimeType, data }
|
|
11
|
+
* @throws {Error} 如果 data URL 格式无效
|
|
12
|
+
*/
|
|
13
|
+
export function parseDataUrl(dataUrl) {
|
|
14
|
+
if (!dataUrl.startsWith('data:')) {
|
|
15
|
+
throw new Error('Invalid data URL: must start with "data:"');
|
|
16
|
+
}
|
|
17
|
+
// 格式:data:image/png;base64,iVBORw0KG...
|
|
18
|
+
// 或:data:image/png;charset=utf-8;base64,iVBORw0KG...(带 charset)
|
|
19
|
+
const commaIndex = dataUrl.indexOf(',');
|
|
20
|
+
if (commaIndex === -1) {
|
|
21
|
+
throw new Error('Invalid data URL: missing comma separator');
|
|
22
|
+
}
|
|
23
|
+
const metaPart = dataUrl.substring(5, commaIndex); // "data:" 之后,"," 之前
|
|
24
|
+
const dataPart = dataUrl.substring(commaIndex + 1);
|
|
25
|
+
// 新增:验证 dataPart 非空
|
|
26
|
+
if (!dataPart) {
|
|
27
|
+
throw new Error('Invalid data URL: empty data part');
|
|
28
|
+
}
|
|
29
|
+
// 解析 meta 部分:image/png;base64 或 image/png;charset=utf-8;base64
|
|
30
|
+
const metaParts = metaPart.split(';');
|
|
31
|
+
const mimeType = metaParts[0];
|
|
32
|
+
if (!mimeType?.startsWith('image/')) {
|
|
33
|
+
throw new Error(`Invalid MIME type in data URL: ${mimeType}`);
|
|
34
|
+
}
|
|
35
|
+
// 修复:使用 includes 查找 base64,而不是假设 position [1]
|
|
36
|
+
// 这样可以处理带 charset 的 data URL,如:data:image/png;charset=utf-8;base64,...
|
|
37
|
+
if (!metaParts.includes('base64')) {
|
|
38
|
+
throw new Error('Invalid data URL: missing base64 encoding');
|
|
39
|
+
}
|
|
40
|
+
return {
|
|
41
|
+
mimeType,
|
|
42
|
+
data: dataPart
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* 检查是否为 data URL
|
|
47
|
+
* @param value - 待检查的字符串
|
|
48
|
+
* @returns 是否为 data URL
|
|
49
|
+
*/
|
|
50
|
+
export function isDataUrl(value) {
|
|
51
|
+
return value.startsWith('data:image/');
|
|
52
|
+
}
|
|
53
|
+
//# sourceMappingURL=data-url-parser.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"data-url-parser.js","sourceRoot":"","sources":["../../src/utils/data-url-parser.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAUH;;;;;GAKG;AACH,MAAM,UAAU,YAAY,CAAC,OAAe;IAC1C,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,OAAO,CAAC,EAAE,CAAC;QACjC,MAAM,IAAI,KAAK,CAAC,2CAA2C,CAAC,CAAC;IAC/D,CAAC;IAED,wCAAwC;IACxC,gEAAgE;IAChE,MAAM,UAAU,GAAG,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;IAExC,IAAI,UAAU,KAAK,CAAC,CAAC,EAAE,CAAC;QACtB,MAAM,IAAI,KAAK,CAAC,2CAA2C,CAAC,CAAC;IAC/D,CAAC;IAED,MAAM,QAAQ,GAAG,OAAO,CAAC,SAAS,CAAC,CAAC,EAAE,UAAU,CAAC,CAAC,CAAC,oBAAoB;IACvE,MAAM,QAAQ,GAAG,OAAO,CAAC,SAAS,CAAC,UAAU,GAAG,CAAC,CAAC,CAAC;IAEnD,oBAAoB;IACpB,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,MAAM,IAAI,KAAK,CAAC,mCAAmC,CAAC,CAAC;IACvD,CAAC;IAED,+DAA+D;IAC/D,MAAM,SAAS,GAAG,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IACtC,MAAM,QAAQ,GAAG,SAAS,CAAC,CAAC,CAAC,CAAC;IAE9B,IAAI,CAAC,QAAQ,EAAE,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;QACpC,MAAM,IAAI,KAAK,CAAC,kCAAkC,QAAQ,EAAE,CAAC,CAAC;IAChE,CAAC;IAED,8CAA8C;IAC9C,uEAAuE;IACvE,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC;QAClC,MAAM,IAAI,KAAK,CAAC,2CAA2C,CAAC,CAAC;IAC/D,CAAC;IAED,OAAO;QACL,QAAQ;QACR,IAAI,EAAE,QAAQ;KACf,CAAC;AACJ,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,SAAS,CAAC,KAAa;IACrC,OAAO,KAAK,CAAC,UAAU,CAAC,aAAa,CAAC,CAAC;AACzC,CAAC"}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Vision MCP Error Types
|
|
3
|
+
*
|
|
4
|
+
* @description 统一错误处理系统,提供清晰的错误分类和信息
|
|
5
|
+
*/
|
|
6
|
+
export declare enum VisionMCPErrorCode {
|
|
7
|
+
INVALID_INPUT = "INVALID_INPUT",
|
|
8
|
+
MODEL_CONFIG_ERROR = "MODEL_CONFIG_ERROR",
|
|
9
|
+
IMAGE_LOAD_ERROR = "IMAGE_LOAD_ERROR",
|
|
10
|
+
MODEL_API_ERROR = "MODEL_API_ERROR",
|
|
11
|
+
TIMEOUT_ERROR = "TIMEOUT_ERROR",
|
|
12
|
+
UNKNOWN_ERROR = "UNKNOWN_ERROR"
|
|
13
|
+
}
|
|
14
|
+
export interface VisionMCPErrorOptions {
|
|
15
|
+
message: string;
|
|
16
|
+
code: VisionMCPErrorCode;
|
|
17
|
+
details?: Record<string, any>;
|
|
18
|
+
cause?: unknown;
|
|
19
|
+
}
|
|
20
|
+
export declare class VisionMCPError extends Error {
|
|
21
|
+
readonly code: VisionMCPErrorCode;
|
|
22
|
+
readonly details?: Record<string, any>;
|
|
23
|
+
readonly timestamp: Date;
|
|
24
|
+
constructor({ message, code, details, cause }: VisionMCPErrorOptions);
|
|
25
|
+
toJSON(): {
|
|
26
|
+
error: {
|
|
27
|
+
message: string;
|
|
28
|
+
code: VisionMCPErrorCode;
|
|
29
|
+
details: {
|
|
30
|
+
[x: string]: any;
|
|
31
|
+
};
|
|
32
|
+
timestamp: string;
|
|
33
|
+
};
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
export declare class InvalidInputError extends VisionMCPError {
|
|
37
|
+
constructor(message: string, details?: Record<string, any>, cause?: unknown);
|
|
38
|
+
}
|
|
39
|
+
export declare class ModelConfigError extends VisionMCPError {
|
|
40
|
+
constructor(message: string, details?: Record<string, any>, cause?: unknown);
|
|
41
|
+
}
|
|
42
|
+
export declare class ImageLoadError extends VisionMCPError {
|
|
43
|
+
constructor(message: string, details?: Record<string, any>, cause?: unknown);
|
|
44
|
+
}
|
|
45
|
+
export declare class ModelAPIError extends VisionMCPError {
|
|
46
|
+
constructor(message: string, details?: Record<string, any>, cause?: unknown);
|
|
47
|
+
}
|
|
48
|
+
export declare class TimeoutError extends VisionMCPError {
|
|
49
|
+
constructor(message: string, details?: Record<string, any>, cause?: unknown);
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* 将未知错误转换为 VisionMCPError
|
|
53
|
+
*/
|
|
54
|
+
export declare function toVisionMCPError(error: unknown, context?: string): VisionMCPError;
|
|
55
|
+
/**
|
|
56
|
+
* 将错误映射为 MCP 工具响应格式
|
|
57
|
+
*/
|
|
58
|
+
export declare function toMCPErrorResponse(error: VisionMCPError): {
|
|
59
|
+
content: {
|
|
60
|
+
type: "text";
|
|
61
|
+
text: string;
|
|
62
|
+
}[];
|
|
63
|
+
isError: boolean;
|
|
64
|
+
};
|
|
65
|
+
//# sourceMappingURL=errors.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/utils/errors.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,oBAAY,kBAAkB;IAC5B,aAAa,kBAAkB;IAC/B,kBAAkB,uBAAuB;IACzC,gBAAgB,qBAAqB;IACrC,eAAe,oBAAoB;IACnC,aAAa,kBAAkB;IAC/B,aAAa,kBAAkB;CAChC;AAED,MAAM,WAAW,qBAAqB;IACpC,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,kBAAkB,CAAC;IACzB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC9B,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAED,qBAAa,cAAe,SAAQ,KAAK;IACvC,SAAgB,IAAI,EAAE,kBAAkB,CAAC;IACzC,SAAgB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC9C,SAAgB,SAAS,EAAE,IAAI,CAAC;gBAEpB,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE,qBAAqB;IAiBpE,MAAM;;;;;;;;;;CAaP;AAED,qBAAa,iBAAkB,SAAQ,cAAc;gBACvC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE,KAAK,CAAC,EAAE,OAAO;CAS5E;AAED,qBAAa,gBAAiB,SAAQ,cAAc;gBACtC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE,KAAK,CAAC,EAAE,OAAO;CAS5E;AAED,qBAAa,cAAe,SAAQ,cAAc;gBACpC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE,KAAK,CAAC,EAAE,OAAO;CAS5E;AAED,qBAAa,aAAc,SAAQ,cAAc;gBACnC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE,KAAK,CAAC,EAAE,OAAO;CAS5E;AAED,qBAAa,YAAa,SAAQ,cAAc;gBAClC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE,KAAK,CAAC,EAAE,OAAO;CAS5E;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,OAAO,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,cAAc,CA+BjF;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,cAAc;;;;;;EAUvD"}
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Vision MCP Error Types
|
|
3
|
+
*
|
|
4
|
+
* @description 统一错误处理系统,提供清晰的错误分类和信息
|
|
5
|
+
*/
|
|
6
|
+
export var VisionMCPErrorCode;
|
|
7
|
+
(function (VisionMCPErrorCode) {
|
|
8
|
+
VisionMCPErrorCode["INVALID_INPUT"] = "INVALID_INPUT";
|
|
9
|
+
VisionMCPErrorCode["MODEL_CONFIG_ERROR"] = "MODEL_CONFIG_ERROR";
|
|
10
|
+
VisionMCPErrorCode["IMAGE_LOAD_ERROR"] = "IMAGE_LOAD_ERROR";
|
|
11
|
+
VisionMCPErrorCode["MODEL_API_ERROR"] = "MODEL_API_ERROR";
|
|
12
|
+
VisionMCPErrorCode["TIMEOUT_ERROR"] = "TIMEOUT_ERROR";
|
|
13
|
+
VisionMCPErrorCode["UNKNOWN_ERROR"] = "UNKNOWN_ERROR";
|
|
14
|
+
})(VisionMCPErrorCode || (VisionMCPErrorCode = {}));
|
|
15
|
+
export class VisionMCPError extends Error {
|
|
16
|
+
code;
|
|
17
|
+
details;
|
|
18
|
+
timestamp;
|
|
19
|
+
constructor({ message, code, details, cause }) {
|
|
20
|
+
super(message);
|
|
21
|
+
this.name = 'VisionMCPError';
|
|
22
|
+
this.code = code;
|
|
23
|
+
this.details = details;
|
|
24
|
+
this.timestamp = new Date();
|
|
25
|
+
if (cause) {
|
|
26
|
+
this.cause = cause;
|
|
27
|
+
}
|
|
28
|
+
// 保持正确的错误堆栈
|
|
29
|
+
if (Error.captureStackTrace) {
|
|
30
|
+
Error.captureStackTrace(this, VisionMCPError);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
toJSON() {
|
|
34
|
+
// 从错误响应中移除堆栈跟踪(仅保留在日志中)
|
|
35
|
+
const { stack, ...detailsWithoutStack } = this.details || {};
|
|
36
|
+
return {
|
|
37
|
+
error: {
|
|
38
|
+
message: this.message,
|
|
39
|
+
code: this.code,
|
|
40
|
+
details: detailsWithoutStack,
|
|
41
|
+
timestamp: this.timestamp.toISOString()
|
|
42
|
+
}
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
export class InvalidInputError extends VisionMCPError {
|
|
47
|
+
constructor(message, details, cause) {
|
|
48
|
+
super({
|
|
49
|
+
message: `Invalid input: ${message}`,
|
|
50
|
+
code: VisionMCPErrorCode.INVALID_INPUT,
|
|
51
|
+
details,
|
|
52
|
+
cause
|
|
53
|
+
});
|
|
54
|
+
this.name = 'InvalidInputError';
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
export class ModelConfigError extends VisionMCPError {
|
|
58
|
+
constructor(message, details, cause) {
|
|
59
|
+
super({
|
|
60
|
+
message: `Model configuration error: ${message}`,
|
|
61
|
+
code: VisionMCPErrorCode.MODEL_CONFIG_ERROR,
|
|
62
|
+
details,
|
|
63
|
+
cause
|
|
64
|
+
});
|
|
65
|
+
this.name = 'ModelConfigError';
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
export class ImageLoadError extends VisionMCPError {
|
|
69
|
+
constructor(message, details, cause) {
|
|
70
|
+
super({
|
|
71
|
+
message: `Failed to load image: ${message}`,
|
|
72
|
+
code: VisionMCPErrorCode.IMAGE_LOAD_ERROR,
|
|
73
|
+
details,
|
|
74
|
+
cause
|
|
75
|
+
});
|
|
76
|
+
this.name = 'ImageLoadError';
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
export class ModelAPIError extends VisionMCPError {
|
|
80
|
+
constructor(message, details, cause) {
|
|
81
|
+
super({
|
|
82
|
+
message: `Model API error: ${message}`,
|
|
83
|
+
code: VisionMCPErrorCode.MODEL_API_ERROR,
|
|
84
|
+
details,
|
|
85
|
+
cause
|
|
86
|
+
});
|
|
87
|
+
this.name = 'ModelAPIError';
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
export class TimeoutError extends VisionMCPError {
|
|
91
|
+
constructor(message, details, cause) {
|
|
92
|
+
super({
|
|
93
|
+
message: `Request timeout: ${message}`,
|
|
94
|
+
code: VisionMCPErrorCode.TIMEOUT_ERROR,
|
|
95
|
+
details,
|
|
96
|
+
cause
|
|
97
|
+
});
|
|
98
|
+
this.name = 'TimeoutError';
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* 将未知错误转换为 VisionMCPError
|
|
103
|
+
*/
|
|
104
|
+
export function toVisionMCPError(error, context) {
|
|
105
|
+
if (error instanceof VisionMCPError) {
|
|
106
|
+
return error;
|
|
107
|
+
}
|
|
108
|
+
if (error instanceof Error) {
|
|
109
|
+
// 堆栈跟踪只记录在日志中,不包含在错误详情中
|
|
110
|
+
const details = {
|
|
111
|
+
originalError: error.name
|
|
112
|
+
};
|
|
113
|
+
// 仅当 LOG_LEVEL 为 debug 时才包含堆栈跟踪
|
|
114
|
+
if (process.env.LOG_LEVEL === 'debug') {
|
|
115
|
+
details.stack = error.stack;
|
|
116
|
+
}
|
|
117
|
+
return new VisionMCPError({
|
|
118
|
+
message: context ? `${context}: ${error.message}` : error.message,
|
|
119
|
+
code: VisionMCPErrorCode.UNKNOWN_ERROR,
|
|
120
|
+
details,
|
|
121
|
+
cause: error
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
return new VisionMCPError({
|
|
125
|
+
message: context || 'An unknown error occurred',
|
|
126
|
+
code: VisionMCPErrorCode.UNKNOWN_ERROR,
|
|
127
|
+
details: {
|
|
128
|
+
error: String(error)
|
|
129
|
+
}
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* 将错误映射为 MCP 工具响应格式
|
|
134
|
+
*/
|
|
135
|
+
export function toMCPErrorResponse(error) {
|
|
136
|
+
return {
|
|
137
|
+
content: [
|
|
138
|
+
{
|
|
139
|
+
type: 'text',
|
|
140
|
+
text: JSON.stringify(error.toJSON(), null, 2)
|
|
141
|
+
}
|
|
142
|
+
],
|
|
143
|
+
isError: true
|
|
144
|
+
};
|
|
145
|
+
}
|
|
146
|
+
//# sourceMappingURL=errors.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../../src/utils/errors.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Image Input Normalization Utility
|
|
3
|
+
*
|
|
4
|
+
* @description 统一处理图片输入:支持 URL、base64(data URL) 和本地路径
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* 图片输入类型
|
|
8
|
+
*/
|
|
9
|
+
export type ImageInputType = 'url' | 'base64' | 'local';
|
|
10
|
+
/**
|
|
11
|
+
* 规范化后的图片输入格式(总是转换为 base64 data URL)
|
|
12
|
+
*/
|
|
13
|
+
export interface NormalizedImageInput {
|
|
14
|
+
type: ImageInputType;
|
|
15
|
+
originalInput: string;
|
|
16
|
+
dataUrl: string;
|
|
17
|
+
mimeType: string;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* 检测输入类型
|
|
21
|
+
*/
|
|
22
|
+
export declare function detectInputType(input: string): ImageInputType;
|
|
23
|
+
/**
|
|
24
|
+
* 从文件扩展名获取 MIME 类型
|
|
25
|
+
*/
|
|
26
|
+
export declare function getMimeTypeFromFileName(filename: string): string;
|
|
27
|
+
/**
|
|
28
|
+
* 从 data URL 提取 MIME 类型
|
|
29
|
+
*/
|
|
30
|
+
export declare function getMimeTypeFromDataUrl(dataUrl: string): string;
|
|
31
|
+
/**
|
|
32
|
+
* 检测 URL 是否指向图片文件
|
|
33
|
+
*/
|
|
34
|
+
export declare function isImageUrl(url: string): boolean;
|
|
35
|
+
/**
|
|
36
|
+
* 规范化图片输入为统一的 data URL 格式
|
|
37
|
+
*/
|
|
38
|
+
export declare function normalizeImageInput(input: string): Promise<NormalizedImageInput>;
|
|
39
|
+
/**
|
|
40
|
+
* 获取图片大小信息(用于日志)
|
|
41
|
+
*/
|
|
42
|
+
export declare function getImageSizeInfo(dataUrl: string): {
|
|
43
|
+
size: number;
|
|
44
|
+
};
|
|
45
|
+
//# sourceMappingURL=image-input.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"image-input.d.ts","sourceRoot":"","sources":["../../src/utils/image-input.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAMH;;GAEG;AACH,MAAM,MAAM,cAAc,GAAG,KAAK,GAAG,QAAQ,GAAG,OAAO,CAAC;AAExD;;GAEG;AACH,MAAM,WAAW,oBAAoB;IACnC,IAAI,EAAE,cAAc,CAAC;IACrB,aAAa,EAAE,MAAM,CAAC;IACtB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAyBD;;GAEG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,cAAc,CAa7D;AAED;;GAEG;AACH,wBAAgB,uBAAuB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAYhE;AAED;;GAEG;AACH,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAoB9D;AAED;;GAEG;AACH,wBAAgB,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAY/C;AAED;;GAEG;AACH,wBAAsB,mBAAmB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,oBAAoB,CAAC,CAuCtF;AAkKD;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,CAalE"}
|