@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.
Files changed (122) hide show
  1. package/README.md +428 -0
  2. package/dist/adapters/base-adapter.d.ts +69 -0
  3. package/dist/adapters/base-adapter.d.ts.map +1 -0
  4. package/dist/adapters/base-adapter.js +143 -0
  5. package/dist/adapters/base-adapter.js.map +1 -0
  6. package/dist/adapters/claude-adapter.d.ts +38 -0
  7. package/dist/adapters/claude-adapter.d.ts.map +1 -0
  8. package/dist/adapters/claude-adapter.js +251 -0
  9. package/dist/adapters/claude-adapter.js.map +1 -0
  10. package/dist/adapters/glm-adapter.d.ts +15 -0
  11. package/dist/adapters/glm-adapter.d.ts.map +1 -0
  12. package/dist/adapters/glm-adapter.js +131 -0
  13. package/dist/adapters/glm-adapter.js.map +1 -0
  14. package/dist/adapters/modelscope-adapter.d.ts +20 -0
  15. package/dist/adapters/modelscope-adapter.d.ts.map +1 -0
  16. package/dist/adapters/modelscope-adapter.js +142 -0
  17. package/dist/adapters/modelscope-adapter.js.map +1 -0
  18. package/dist/adapters/openai-adapter.d.ts +20 -0
  19. package/dist/adapters/openai-adapter.d.ts.map +1 -0
  20. package/dist/adapters/openai-adapter.js +194 -0
  21. package/dist/adapters/openai-adapter.js.map +1 -0
  22. package/dist/adapters/siliconflow-adapter.d.ts +21 -0
  23. package/dist/adapters/siliconflow-adapter.d.ts.map +1 -0
  24. package/dist/adapters/siliconflow-adapter.js +145 -0
  25. package/dist/adapters/siliconflow-adapter.js.map +1 -0
  26. package/dist/config/model-config.d.ts +39 -0
  27. package/dist/config/model-config.d.ts.map +1 -0
  28. package/dist/config/model-config.js +115 -0
  29. package/dist/config/model-config.js.map +1 -0
  30. package/dist/index.d.ts +17 -0
  31. package/dist/index.d.ts.map +1 -0
  32. package/dist/index.js +186 -0
  33. package/dist/index.js.map +1 -0
  34. package/dist/prompts/system.d.ts +75 -0
  35. package/dist/prompts/system.d.ts.map +1 -0
  36. package/dist/prompts/system.js +272 -0
  37. package/dist/prompts/system.js.map +1 -0
  38. package/dist/providers/provider-registry.d.ts +58 -0
  39. package/dist/providers/provider-registry.d.ts.map +1 -0
  40. package/dist/providers/provider-registry.js +173 -0
  41. package/dist/providers/provider-registry.js.map +1 -0
  42. package/dist/src/adapters/base-adapter.d.ts +59 -0
  43. package/dist/src/adapters/base-adapter.d.ts.map +1 -0
  44. package/dist/src/adapters/base-adapter.js +83 -0
  45. package/dist/src/adapters/base-adapter.js.map +1 -0
  46. package/dist/src/adapters/glm-adapter.d.ts +15 -0
  47. package/dist/src/adapters/glm-adapter.d.ts.map +1 -0
  48. package/dist/src/adapters/glm-adapter.js +116 -0
  49. package/dist/src/adapters/glm-adapter.js.map +1 -0
  50. package/dist/src/adapters/siliconflow-adapter.d.ts +21 -0
  51. package/dist/src/adapters/siliconflow-adapter.d.ts.map +1 -0
  52. package/dist/src/adapters/siliconflow-adapter.js +130 -0
  53. package/dist/src/adapters/siliconflow-adapter.js.map +1 -0
  54. package/dist/src/config/model-config.d.ts +40 -0
  55. package/dist/src/config/model-config.d.ts.map +1 -0
  56. package/dist/src/config/model-config.js +126 -0
  57. package/dist/src/config/model-config.js.map +1 -0
  58. package/dist/src/index.d.ts +17 -0
  59. package/dist/src/index.d.ts.map +1 -0
  60. package/dist/src/index.js +188 -0
  61. package/dist/src/index.js.map +1 -0
  62. package/dist/src/prompts/system.d.ts +75 -0
  63. package/dist/src/prompts/system.d.ts.map +1 -0
  64. package/dist/src/prompts/system.js +272 -0
  65. package/dist/src/prompts/system.js.map +1 -0
  66. package/dist/src/tools/vision-tool.d.ts +91 -0
  67. package/dist/src/tools/vision-tool.d.ts.map +1 -0
  68. package/dist/src/tools/vision-tool.js +171 -0
  69. package/dist/src/tools/vision-tool.js.map +1 -0
  70. package/dist/src/utils/errors.d.ts +65 -0
  71. package/dist/src/utils/errors.d.ts.map +1 -0
  72. package/dist/src/utils/errors.js +146 -0
  73. package/dist/src/utils/errors.js.map +1 -0
  74. package/dist/src/utils/image-input.d.ts +45 -0
  75. package/dist/src/utils/image-input.d.ts.map +1 -0
  76. package/dist/src/utils/image-input.js +226 -0
  77. package/dist/src/utils/image-input.js.map +1 -0
  78. package/dist/src/utils/logger.d.ts +63 -0
  79. package/dist/src/utils/logger.d.ts.map +1 -0
  80. package/dist/src/utils/logger.js +157 -0
  81. package/dist/src/utils/logger.js.map +1 -0
  82. package/dist/test/integration.test.d.ts +10 -0
  83. package/dist/test/integration.test.d.ts.map +1 -0
  84. package/dist/test/integration.test.js +270 -0
  85. package/dist/test/integration.test.js.map +1 -0
  86. package/dist/test/test-utils.d.ts +45 -0
  87. package/dist/test/test-utils.d.ts.map +1 -0
  88. package/dist/test/test-utils.js +107 -0
  89. package/dist/test/test-utils.js.map +1 -0
  90. package/dist/test/vision-tool.test.d.ts +9 -0
  91. package/dist/test/vision-tool.test.d.ts.map +1 -0
  92. package/dist/test/vision-tool.test.js +167 -0
  93. package/dist/test/vision-tool.test.js.map +1 -0
  94. package/dist/tools/vision-tool.d.ts +91 -0
  95. package/dist/tools/vision-tool.d.ts.map +1 -0
  96. package/dist/tools/vision-tool.js +167 -0
  97. package/dist/tools/vision-tool.js.map +1 -0
  98. package/dist/utils/data-url-parser.d.ts +27 -0
  99. package/dist/utils/data-url-parser.d.ts.map +1 -0
  100. package/dist/utils/data-url-parser.js +53 -0
  101. package/dist/utils/data-url-parser.js.map +1 -0
  102. package/dist/utils/errors.d.ts +65 -0
  103. package/dist/utils/errors.d.ts.map +1 -0
  104. package/dist/utils/errors.js +146 -0
  105. package/dist/utils/errors.js.map +1 -0
  106. package/dist/utils/image-input.d.ts +45 -0
  107. package/dist/utils/image-input.d.ts.map +1 -0
  108. package/dist/utils/image-input.js +238 -0
  109. package/dist/utils/image-input.js.map +1 -0
  110. package/dist/utils/logger.d.ts +63 -0
  111. package/dist/utils/logger.d.ts.map +1 -0
  112. package/dist/utils/logger.js +157 -0
  113. package/dist/utils/logger.js.map +1 -0
  114. package/dist/utils/thinking-extractors.d.ts +34 -0
  115. package/dist/utils/thinking-extractors.d.ts.map +1 -0
  116. package/dist/utils/thinking-extractors.js +83 -0
  117. package/dist/utils/thinking-extractors.js.map +1 -0
  118. package/dist/utils/thinking-filter.d.ts +32 -0
  119. package/dist/utils/thinking-filter.d.ts.map +1 -0
  120. package/dist/utils/thinking-filter.js +147 -0
  121. package/dist/utils/thinking-filter.js.map +1 -0
  122. 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"}