@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,173 @@
1
+ /**
2
+ * Provider Registry
3
+ *
4
+ * @description 提供方注册表,集中管理所有支持的模型提供商
5
+ * 添加新提供商只需在这里注册,无需修改其他文件
6
+ */
7
+ import { extractGLMThinking, extractOpenAIThinking, extractClaudeThinking } from '../utils/thinking-extractors.js';
8
+ import { GLM4VisionAdapter } from '../adapters/glm-adapter.js';
9
+ import { SiliconFlowAdapter } from '../adapters/siliconflow-adapter.js';
10
+ import { ModelScopeAdapter } from '../adapters/modelscope-adapter.js';
11
+ import { OpenAIAdapter } from '../adapters/openai-adapter.js';
12
+ import { ClaudeAdapter } from '../adapters/claude-adapter.js';
13
+ /**
14
+ * 提供商注册表
15
+ */
16
+ class ProviderRegistry {
17
+ providers = new Map();
18
+ /**
19
+ * 注册提供商
20
+ */
21
+ register(provider) {
22
+ this.providers.set(provider.type, provider);
23
+ }
24
+ /**
25
+ * 获取提供商
26
+ */
27
+ get(type) {
28
+ return this.providers.get(type);
29
+ }
30
+ /**
31
+ * 检查是否支持该类型
32
+ */
33
+ has(type) {
34
+ return this.providers.has(type);
35
+ }
36
+ /**
37
+ * 获取所有支持的类型
38
+ */
39
+ getSupportedTypes() {
40
+ return Array.from(this.providers.keys());
41
+ }
42
+ }
43
+ // 创建全局注册表实例
44
+ export const registry = new ProviderRegistry();
45
+ // ========================================================================
46
+ // 注册内置提供商
47
+ // ========================================================================
48
+ // GLM-4.6V Provider
49
+ registry.register({
50
+ type: 'glm-4.6v',
51
+ displayName: 'GLM-4.6V',
52
+ defaults: {
53
+ baseUrl: 'https://open.bigmodel.cn/api/paas/v4',
54
+ modelName: 'glm-4.6v',
55
+ timeout: 60000,
56
+ maxRetries: 2
57
+ },
58
+ validateApiKey: (apiKey) => {
59
+ if (!apiKey.includes('.')) {
60
+ return 'GLM API Key should contain a dot (.)';
61
+ }
62
+ return true;
63
+ },
64
+ createAdapter: (config) => new GLM4VisionAdapter(config),
65
+ thinkingExtractor: extractGLMThinking,
66
+ enableThinking: true
67
+ });
68
+ // GLM alias for backward compatibility (allows using 'glm' instead of 'glm-4.6v')
69
+ registry.register({
70
+ type: 'glm',
71
+ displayName: 'GLM-4.6V (Alias)',
72
+ defaults: {
73
+ baseUrl: 'https://open.bigmodel.cn/api/paas/v4',
74
+ modelName: 'glm-4.6v',
75
+ timeout: 60000,
76
+ maxRetries: 2
77
+ },
78
+ validateApiKey: (apiKey) => {
79
+ if (!apiKey.includes('.')) {
80
+ return 'GLM API Key should contain a dot (.)';
81
+ }
82
+ return true;
83
+ },
84
+ createAdapter: (config) => new GLM4VisionAdapter({
85
+ ...config,
86
+ type: 'glm-4.6v' // Use the full type for the adapter
87
+ }),
88
+ thinkingExtractor: extractGLMThinking,
89
+ enableThinking: true
90
+ });
91
+ // SiliconFlow Provider
92
+ registry.register({
93
+ type: 'siliconflow',
94
+ displayName: 'SiliconFlow',
95
+ defaults: {
96
+ baseUrl: 'https://api.siliconflow.cn/v1',
97
+ modelName: 'Qwen/Qwen2-VL-72B-Instruct',
98
+ timeout: 60000,
99
+ maxRetries: 2
100
+ },
101
+ validateApiKey: (apiKey) => {
102
+ if (!apiKey.startsWith('sk-')) {
103
+ return 'SiliconFlow API Key should start with "sk-"';
104
+ }
105
+ return true;
106
+ },
107
+ createAdapter: (config) => new SiliconFlowAdapter(config),
108
+ thinkingExtractor: extractOpenAIThinking,
109
+ enableThinking: false
110
+ });
111
+ // ModelScope Provider
112
+ registry.register({
113
+ type: 'modelscope',
114
+ displayName: 'ModelScope API-Inference',
115
+ defaults: {
116
+ baseUrl: 'https://api-inference.modelscope.cn/v1',
117
+ modelName: 'ZhipuAI/GLM-4.6V',
118
+ timeout: 60000,
119
+ maxRetries: 2
120
+ },
121
+ validateApiKey: (apiKey) => {
122
+ if (!apiKey.startsWith('ms-')) {
123
+ return 'ModelScope API Key should start with "ms-"';
124
+ }
125
+ return true;
126
+ },
127
+ createAdapter: (config) => new ModelScopeAdapter(config),
128
+ thinkingExtractor: extractOpenAIThinking,
129
+ enableThinking: false
130
+ });
131
+ // OpenAI Provider
132
+ registry.register({
133
+ type: 'openai',
134
+ displayName: 'OpenAI',
135
+ defaults: {
136
+ baseUrl: 'https://api.openai.com/v1',
137
+ modelName: 'gpt-4o',
138
+ timeout: 60000,
139
+ maxRetries: 2
140
+ },
141
+ validateApiKey: (apiKey) => {
142
+ if (!apiKey.startsWith('sk-')) {
143
+ return 'OpenAI API Key should start with "sk-"';
144
+ }
145
+ return true;
146
+ },
147
+ createAdapter: (config) => new OpenAIAdapter(config),
148
+ thinkingExtractor: extractOpenAIThinking,
149
+ enableThinking: false
150
+ });
151
+ // Claude (Anthropic Messages API) Provider
152
+ registry.register({
153
+ type: 'claude',
154
+ displayName: 'Anthropic Claude',
155
+ defaults: {
156
+ baseUrl: 'https://api.anthropic.com',
157
+ modelName: 'claude-3-5-sonnet-20241022',
158
+ timeout: 60000,
159
+ maxRetries: 2
160
+ },
161
+ validateApiKey: (apiKey) => {
162
+ // Claude API key format: sk-ant-...
163
+ // Not strictly enforcing as some providers may use different formats
164
+ if (!apiKey.startsWith('sk-ant-')) {
165
+ return 'Claude API Key typically starts with "sk-ant-". Proxy providers may use different formats.';
166
+ }
167
+ return true;
168
+ },
169
+ createAdapter: (config) => new ClaudeAdapter(config),
170
+ thinkingExtractor: extractClaudeThinking,
171
+ enableThinking: false
172
+ });
173
+ //# sourceMappingURL=provider-registry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"provider-registry.js","sourceRoot":"","sources":["../../src/providers/provider-registry.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,59 @@
1
+ /**
2
+ * Base Vision Model Adapter
3
+ *
4
+ * @description 定义模型适配器的统一接口和抽象基类
5
+ */
6
+ import { ModelConfig } from '../config/model-config.js';
7
+ /**
8
+ * 模型响应接口
9
+ */
10
+ export interface VisionModelResponse {
11
+ content: string;
12
+ usage?: {
13
+ promptTokens?: number;
14
+ completionTokens?: number;
15
+ totalTokens?: number;
16
+ };
17
+ model?: string;
18
+ }
19
+ /**
20
+ * 模型适配器接口
21
+ */
22
+ export interface VisionModelAdapter {
23
+ config: ModelConfig;
24
+ /**
25
+ * 分析图片
26
+ * @param imageData - 图片数据(URL 或 base64)
27
+ * @param prompt - 提示词
28
+ * @returns 模型响应
29
+ */
30
+ analyze(imageData: string, prompt: string): Promise<string>;
31
+ /**
32
+ * 分析图片(带完整响应)
33
+ * @param imageData - 图片数据(URL 或 base64)
34
+ * @param prompt - 提示词
35
+ * @returns 完整响应
36
+ */
37
+ analyzeWithResponse(imageData: string, prompt: string): Promise<VisionModelResponse>;
38
+ }
39
+ /**
40
+ * 抽象基类实现通用功能
41
+ */
42
+ export declare abstract class BaseVisionModelAdapter implements VisionModelAdapter {
43
+ config: ModelConfig;
44
+ constructor(config: ModelConfig);
45
+ abstract analyze(imageData: string, prompt: string): Promise<string>;
46
+ abstract analyzeWithResponse(imageData: string, prompt: string): Promise<VisionModelResponse>;
47
+ /**
48
+ * 带重试和超时控制的请求包装器
49
+ */
50
+ protected withRetry<T>(operation: (signal: AbortSignal) => Promise<T>, config?: {
51
+ maxRetries?: number;
52
+ timeout?: number;
53
+ }): Promise<T>;
54
+ /**
55
+ * 解析模型响应
56
+ */
57
+ protected parseResponse(response: unknown): VisionModelResponse;
58
+ }
59
+ //# sourceMappingURL=base-adapter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"base-adapter.d.ts","sourceRoot":"","sources":["../../../src/adapters/base-adapter.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAC;AAIxD;;GAEG;AACH,MAAM,WAAW,mBAAmB;IAClC,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE;QACN,YAAY,CAAC,EAAE,MAAM,CAAC;QACtB,gBAAgB,CAAC,EAAE,MAAM,CAAC;QAC1B,WAAW,CAAC,EAAE,MAAM,CAAC;KACtB,CAAC;IACF,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,MAAM,EAAE,WAAW,CAAC;IAEpB;;;;;OAKG;IACH,OAAO,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IAE5D;;;;;OAKG;IACH,mBAAmB,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,mBAAmB,CAAC,CAAC;CACtF;AAED;;GAEG;AACH,8BAAsB,sBAAuB,YAAW,kBAAkB;IACrD,MAAM,EAAE,WAAW;gBAAnB,MAAM,EAAE,WAAW;IAEtC,QAAQ,CAAC,OAAO,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IACpE,QAAQ,CAAC,mBAAmB,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,mBAAmB,CAAC;IAE7F;;OAEG;cACa,SAAS,CAAC,CAAC,EACzB,SAAS,EAAE,CAAC,MAAM,EAAE,WAAW,KAAK,OAAO,CAAC,CAAC,CAAC,EAC9C,MAAM,GAAE;QAAE,UAAU,CAAC,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAAO,GACrD,OAAO,CAAC,CAAC,CAAC;IAsDb;;OAEG;IACH,SAAS,CAAC,aAAa,CAAC,QAAQ,EAAE,OAAO,GAAG,mBAAmB;CA4BhE"}
@@ -0,0 +1,83 @@
1
+ /**
2
+ * Base Vision Model Adapter
3
+ *
4
+ * @description 定义模型适配器的统一接口和抽象基类
5
+ */
6
+ import { ModelAPIError, TimeoutError } from '../utils/errors.js';
7
+ import { logger } from '../utils/logger.js';
8
+ /**
9
+ * 抽象基类实现通用功能
10
+ */
11
+ export class BaseVisionModelAdapter {
12
+ config;
13
+ constructor(config) {
14
+ this.config = config;
15
+ }
16
+ /**
17
+ * 带重试和超时控制的请求包装器
18
+ */
19
+ async withRetry(operation, config = {}) {
20
+ const { maxRetries = this.config.maxRetries || 2, timeout = this.config.timeout || 60000 } = config;
21
+ let lastError;
22
+ for (let attempt = 0; attempt <= maxRetries; attempt++) {
23
+ try {
24
+ logger.debug(`Attempt ${attempt + 1}/${maxRetries + 1}`);
25
+ // 使用 AbortController 实现超时
26
+ const controller = new AbortController();
27
+ const timeoutId = setTimeout(() => controller.abort(), timeout);
28
+ try {
29
+ const result = await operation(controller.signal);
30
+ clearTimeout(timeoutId);
31
+ return result;
32
+ }
33
+ catch (error) {
34
+ clearTimeout(timeoutId);
35
+ throw error;
36
+ }
37
+ }
38
+ catch (error) {
39
+ lastError = error;
40
+ // 如果是 AbortError,转换为 TimeoutError
41
+ if (error instanceof Error && error.name === 'AbortError') {
42
+ throw new TimeoutError(`Request timed out after ${timeout}ms`);
43
+ }
44
+ // 最后一次尝试失败,抛出错误
45
+ if (attempt === maxRetries) {
46
+ break;
47
+ }
48
+ // 计算退避时间(指数退避)
49
+ const backoffTime = Math.min(1000 * Math.pow(2, attempt), 5000);
50
+ logger.warn(`Attempt ${attempt + 1} failed, retrying in ${backoffTime}ms`, {
51
+ error: lastError.message
52
+ });
53
+ // 等待后退时间
54
+ await new Promise(resolve => setTimeout(resolve, backoffTime));
55
+ }
56
+ }
57
+ throw new ModelAPIError(`Failed after ${maxRetries + 1} attempts`, { lastError: lastError?.message });
58
+ }
59
+ /**
60
+ * 解析模型响应
61
+ */
62
+ parseResponse(response) {
63
+ try {
64
+ // @ts-ignore - 检查响应结构
65
+ const content = response?.choices?.[0]?.message?.content;
66
+ if (!content || typeof content !== 'string') {
67
+ throw new ModelAPIError('Invalid response format: missing or invalid content', { response });
68
+ }
69
+ return {
70
+ content,
71
+ // @ts-ignore
72
+ usage: response?.usage,
73
+ // @ts-ignore
74
+ model: response?.model
75
+ };
76
+ }
77
+ catch (error) {
78
+ logger.error('Failed to parse model response', error);
79
+ throw new ModelAPIError('Failed to parse model response', { response }, error);
80
+ }
81
+ }
82
+ }
83
+ //# sourceMappingURL=base-adapter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"base-adapter.js","sourceRoot":"","sources":["../../../src/adapters/base-adapter.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AACjE,OAAO,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAsC5C;;GAEG;AACH,MAAM,OAAgB,sBAAsB;IACvB;IAAnB,YAAmB,MAAmB;QAAnB,WAAM,GAAN,MAAM,CAAa;IAAG,CAAC;IAK1C;;OAEG;IACO,KAAK,CAAC,SAAS,CACvB,SAA8C,EAC9C,SAAoD,EAAE;QAEtD,MAAM,EACJ,UAAU,GAAG,IAAI,CAAC,MAAM,CAAC,UAAU,IAAI,CAAC,EACxC,OAAO,GAAG,IAAI,CAAC,MAAM,CAAC,OAAO,IAAI,KAAK,EACvC,GAAG,MAAM,CAAC;QAEX,IAAI,SAA4B,CAAC;QAEjC,KAAK,IAAI,OAAO,GAAG,CAAC,EAAE,OAAO,IAAI,UAAU,EAAE,OAAO,EAAE,EAAE,CAAC;YACvD,IAAI,CAAC;gBACH,MAAM,CAAC,KAAK,CAAC,WAAW,OAAO,GAAG,CAAC,IAAI,UAAU,GAAG,CAAC,EAAE,CAAC,CAAC;gBAEzD,0BAA0B;gBAC1B,MAAM,UAAU,GAAG,IAAI,eAAe,EAAE,CAAC;gBACzC,MAAM,SAAS,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,UAAU,CAAC,KAAK,EAAE,EAAE,OAAO,CAAC,CAAC;gBAEhE,IAAI,CAAC;oBACH,MAAM,MAAM,GAAG,MAAM,SAAS,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC;oBAClD,YAAY,CAAC,SAAS,CAAC,CAAC;oBACxB,OAAO,MAAM,CAAC;gBAChB,CAAC;gBAAC,OAAO,KAAK,EAAE,CAAC;oBACf,YAAY,CAAC,SAAS,CAAC,CAAC;oBACxB,MAAM,KAAK,CAAC;gBACd,CAAC;YACH,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,SAAS,GAAG,KAAc,CAAC;gBAE3B,kCAAkC;gBAClC,IAAI,KAAK,YAAY,KAAK,IAAI,KAAK,CAAC,IAAI,KAAK,YAAY,EAAE,CAAC;oBAC1D,MAAM,IAAI,YAAY,CAAC,2BAA2B,OAAO,IAAI,CAAC,CAAC;gBACjE,CAAC;gBAED,gBAAgB;gBAChB,IAAI,OAAO,KAAK,UAAU,EAAE,CAAC;oBAC3B,MAAM;gBACR,CAAC;gBAED,eAAe;gBACf,MAAM,WAAW,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,OAAO,CAAC,EAAE,IAAI,CAAC,CAAC;gBAChE,MAAM,CAAC,IAAI,CAAC,WAAW,OAAO,GAAG,CAAC,wBAAwB,WAAW,IAAI,EAAE;oBACzE,KAAK,EAAE,SAAS,CAAC,OAAO;iBACzB,CAAC,CAAC;gBAEH,SAAS;gBACT,MAAM,IAAI,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,WAAW,CAAC,CAAC,CAAC;YACjE,CAAC;QACH,CAAC;QAED,MAAM,IAAI,aAAa,CACrB,gBAAgB,UAAU,GAAG,CAAC,WAAW,EACzC,EAAE,SAAS,EAAE,SAAS,EAAE,OAAO,EAAE,CAClC,CAAC;IACJ,CAAC;IAED;;OAEG;IACO,aAAa,CAAC,QAAiB;QACvC,IAAI,CAAC;YACH,sBAAsB;YACtB,MAAM,OAAO,GAAG,QAAQ,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,OAAO,CAAC;YAEzD,IAAI,CAAC,OAAO,IAAI,OAAO,OAAO,KAAK,QAAQ,EAAE,CAAC;gBAC5C,MAAM,IAAI,aAAa,CACrB,qDAAqD,EACrD,EAAE,QAAQ,EAAE,CACb,CAAC;YACJ,CAAC;YAED,OAAO;gBACL,OAAO;gBACP,aAAa;gBACb,KAAK,EAAE,QAAQ,EAAE,KAAK;gBACtB,aAAa;gBACb,KAAK,EAAE,QAAQ,EAAE,KAAK;aACvB,CAAC;QACJ,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,CAAC,KAAK,CAAC,gCAAgC,EAAE,KAAK,CAAC,CAAC;YACtD,MAAM,IAAI,aAAa,CACrB,gCAAgC,EAChC,EAAE,QAAQ,EAAE,EACZ,KAAK,CACN,CAAC;QACJ,CAAC;IACH,CAAC;CACF"}
@@ -0,0 +1,15 @@
1
+ /**
2
+ * GLM-4.6V Adapter
3
+ *
4
+ * @description GLM-4.6V 模型适配器实现,支持智谱 AI 开放平台的视觉模型
5
+ */
6
+ import { BaseVisionModelAdapter } from './base-adapter.js';
7
+ import { ModelConfig } from '../config/model-config.js';
8
+ import { VisionModelResponse } from './base-adapter.js';
9
+ export declare class GLM4VisionAdapter extends BaseVisionModelAdapter {
10
+ constructor(config: ModelConfig);
11
+ analyze(imageData: string, prompt: string): Promise<string>;
12
+ analyzeWithResponse(imageData: string, prompt: string): Promise<VisionModelResponse>;
13
+ private callGLMAPI;
14
+ }
15
+ //# sourceMappingURL=glm-adapter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"glm-adapter.d.ts","sourceRoot":"","sources":["../../../src/adapters/glm-adapter.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,sBAAsB,EAAE,MAAM,mBAAmB,CAAC;AAC3D,OAAO,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAC;AAGxD,OAAO,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AAExD,qBAAa,iBAAkB,SAAQ,sBAAsB;gBAC/C,MAAM,EAAE,WAAW;IAazB,OAAO,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAuB3D,mBAAmB,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,mBAAmB,CAAC;YAwB5E,UAAU;CAgEzB"}
@@ -0,0 +1,116 @@
1
+ /**
2
+ * GLM-4.6V Adapter
3
+ *
4
+ * @description GLM-4.6V 模型适配器实现,支持智谱 AI 开放平台的视觉模型
5
+ */
6
+ import { BaseVisionModelAdapter } from './base-adapter.js';
7
+ import { ModelAPIError } from '../utils/errors.js';
8
+ import { logger } from '../utils/logger.js';
9
+ export class GLM4VisionAdapter extends BaseVisionModelAdapter {
10
+ constructor(config) {
11
+ super(config);
12
+ if (config.type !== 'glm-4.6v') {
13
+ throw new Error('Invalid model type. Expected: glm-4.6v');
14
+ }
15
+ logger.info('Initialized GLM-4.6V adapter', {
16
+ model: config.name,
17
+ baseUrl: config.baseUrl
18
+ });
19
+ }
20
+ async analyze(imageData, prompt) {
21
+ logger.logRequest('Analyzing image with GLM-4.6V', {
22
+ modelType: 'glm-4.6v',
23
+ imageLength: imageData.length
24
+ });
25
+ try {
26
+ return await this.withRetry(async (signal) => {
27
+ const response = await this.callGLMAPI(imageData, prompt, signal);
28
+ logger.logRequest('GLM-4.6V analysis completed', {
29
+ modelType: 'glm-4.6v',
30
+ responseLength: response.content.length
31
+ });
32
+ return response.content;
33
+ });
34
+ }
35
+ catch (error) {
36
+ logger.error('GLM-4.6V analysis failed', error);
37
+ throw error;
38
+ }
39
+ }
40
+ async analyzeWithResponse(imageData, prompt) {
41
+ logger.logRequest('Analyzing image with GLM-4.6V (full response)', {
42
+ modelType: 'glm-4.6v',
43
+ imageLength: imageData.length
44
+ });
45
+ try {
46
+ return await this.withRetry(async (signal) => {
47
+ const response = await this.callGLMAPI(imageData, prompt, signal);
48
+ logger.logRequest('GLM-4.6V analysis completed', {
49
+ modelType: 'glm-4.6v',
50
+ responseLength: response.content.length,
51
+ usage: response.usage
52
+ });
53
+ return response;
54
+ });
55
+ }
56
+ catch (error) {
57
+ logger.error('GLM-4.6V analysis failed', error);
58
+ throw error;
59
+ }
60
+ }
61
+ async callGLMAPI(imageData, prompt, signal) {
62
+ // 构建请求 URL
63
+ const apiUrl = `${this.config.baseUrl}/chat/completions`;
64
+ // 构建请求体
65
+ const requestBody = {
66
+ model: this.config.name,
67
+ messages: [
68
+ {
69
+ role: 'user',
70
+ content: [
71
+ {
72
+ type: 'text',
73
+ text: prompt
74
+ },
75
+ {
76
+ type: 'image_url',
77
+ image_url: {
78
+ url: imageData
79
+ }
80
+ }
81
+ ]
82
+ }
83
+ ],
84
+ ...(this.config.thinking && {
85
+ thinking: this.config.thinking
86
+ })
87
+ };
88
+ logger.debug('Calling GLM-4.6V API', {
89
+ apiUrl,
90
+ model: this.config.name,
91
+ hasThinking: !!this.config.thinking
92
+ });
93
+ const response = await fetch(apiUrl, {
94
+ method: 'POST',
95
+ headers: {
96
+ 'Authorization': `Bearer ${this.config.apiKey}`,
97
+ 'Content-Type': 'application/json',
98
+ 'Accept': 'application/json'
99
+ },
100
+ body: JSON.stringify(requestBody),
101
+ signal
102
+ });
103
+ if (!response.ok) {
104
+ const errorText = await response.text().catch(() => 'Failed to get error details');
105
+ throw new ModelAPIError(`GLM API request failed: ${response.status} ${response.statusText}`, {
106
+ status: response.status,
107
+ statusText: response.statusText,
108
+ errorDetails: errorText,
109
+ endpoint: apiUrl
110
+ });
111
+ }
112
+ const responseData = await response.json();
113
+ return this.parseResponse(responseData);
114
+ }
115
+ }
116
+ //# sourceMappingURL=glm-adapter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"glm-adapter.js","sourceRoot":"","sources":["../../../src/adapters/glm-adapter.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,21 @@
1
+ /**
2
+ * SiliconFlow Adapter
3
+ *
4
+ * @description SiliconFlow 模型适配器实现,支持多种视觉模型(Qwen2-VL、InternVL 等)
5
+ */
6
+ import { BaseVisionModelAdapter } from './base-adapter.js';
7
+ import { ModelConfig } from '../config/model-config.js';
8
+ import { VisionModelResponse } from './base-adapter.js';
9
+ export interface SiliconFlowAdapterOptions {
10
+ detail?: 'low' | 'high' | 'auto';
11
+ maxTokens?: number;
12
+ temperature?: number;
13
+ }
14
+ export declare class SiliconFlowAdapter extends BaseVisionModelAdapter {
15
+ private options;
16
+ constructor(config: ModelConfig, options?: SiliconFlowAdapterOptions);
17
+ analyze(imageData: string, prompt: string): Promise<string>;
18
+ analyzeWithResponse(imageData: string, prompt: string): Promise<VisionModelResponse>;
19
+ private callSiliconFlowAPI;
20
+ }
21
+ //# sourceMappingURL=siliconflow-adapter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"siliconflow-adapter.d.ts","sourceRoot":"","sources":["../../../src/adapters/siliconflow-adapter.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,sBAAsB,EAAE,MAAM,mBAAmB,CAAC;AAC3D,OAAO,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAC;AAGxD,OAAO,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AAExD,MAAM,WAAW,yBAAyB;IACxC,MAAM,CAAC,EAAE,KAAK,GAAG,MAAM,GAAG,MAAM,CAAC;IACjC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,qBAAa,kBAAmB,SAAQ,sBAAsB;IAC5D,OAAO,CAAC,OAAO,CAA4B;gBAE/B,MAAM,EAAE,WAAW,EAAE,OAAO,GAAE,yBAA8B;IAqBlE,OAAO,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAyB3D,mBAAmB,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,mBAAmB,CAAC;YA0B5E,kBAAkB;CAkEjC"}
@@ -0,0 +1,130 @@
1
+ /**
2
+ * SiliconFlow Adapter
3
+ *
4
+ * @description SiliconFlow 模型适配器实现,支持多种视觉模型(Qwen2-VL、InternVL 等)
5
+ */
6
+ import { BaseVisionModelAdapter } from './base-adapter.js';
7
+ import { ModelAPIError } from '../utils/errors.js';
8
+ import { logger } from '../utils/logger.js';
9
+ export class SiliconFlowAdapter extends BaseVisionModelAdapter {
10
+ options;
11
+ constructor(config, options = {}) {
12
+ super(config);
13
+ if (config.type !== 'siliconflow') {
14
+ throw new Error('Invalid model type. Expected: siliconflow');
15
+ }
16
+ this.options = {
17
+ detail: 'auto',
18
+ maxTokens: 2048,
19
+ temperature: 0.7,
20
+ ...options
21
+ };
22
+ logger.info('Initialized SiliconFlow adapter', {
23
+ model: config.name,
24
+ baseUrl: config.baseUrl,
25
+ options: this.options
26
+ });
27
+ }
28
+ async analyze(imageData, prompt) {
29
+ logger.logRequest('Analyzing image with SiliconFlow', {
30
+ modelType: 'siliconflow',
31
+ model: this.config.name,
32
+ imageLength: imageData.length
33
+ });
34
+ try {
35
+ return await this.withRetry(async (signal) => {
36
+ const response = await this.callSiliconFlowAPI(imageData, prompt, signal);
37
+ logger.logRequest('SiliconFlow analysis completed', {
38
+ modelType: 'siliconflow',
39
+ model: this.config.name,
40
+ responseLength: response.content.length
41
+ });
42
+ return response.content;
43
+ });
44
+ }
45
+ catch (error) {
46
+ logger.error('SiliconFlow analysis failed', error);
47
+ throw error;
48
+ }
49
+ }
50
+ async analyzeWithResponse(imageData, prompt) {
51
+ logger.logRequest('Analyzing image with SiliconFlow (full response)', {
52
+ modelType: 'siliconflow',
53
+ model: this.config.name,
54
+ imageLength: imageData.length
55
+ });
56
+ try {
57
+ return await this.withRetry(async (signal) => {
58
+ const response = await this.callSiliconFlowAPI(imageData, prompt, signal);
59
+ logger.logRequest('SiliconFlow analysis completed', {
60
+ modelType: 'siliconflow',
61
+ model: this.config.name,
62
+ responseLength: response.content.length,
63
+ usage: response.usage
64
+ });
65
+ return response;
66
+ });
67
+ }
68
+ catch (error) {
69
+ logger.error('SiliconFlow analysis failed', error);
70
+ throw error;
71
+ }
72
+ }
73
+ async callSiliconFlowAPI(imageData, prompt, signal) {
74
+ // 构建请求 URL
75
+ const apiUrl = `${this.config.baseUrl}/chat/completions`;
76
+ // 构建请求体(OpenAI 兼容格式)
77
+ const requestBody = {
78
+ model: this.config.name,
79
+ messages: [
80
+ {
81
+ role: 'user',
82
+ content: [
83
+ {
84
+ type: 'text',
85
+ text: prompt
86
+ },
87
+ {
88
+ type: 'image_url',
89
+ image_url: {
90
+ url: imageData,
91
+ detail: this.options.detail || 'auto'
92
+ }
93
+ }
94
+ ]
95
+ }
96
+ ],
97
+ max_tokens: this.options.maxTokens,
98
+ temperature: this.options.temperature
99
+ };
100
+ logger.debug('Calling SiliconFlow API', {
101
+ apiUrl,
102
+ model: this.config.name,
103
+ detail: this.options.detail,
104
+ maxTokens: this.options.maxTokens,
105
+ temperature: this.options.temperature
106
+ });
107
+ const response = await fetch(apiUrl, {
108
+ method: 'POST',
109
+ headers: {
110
+ 'Authorization': `Bearer ${this.config.apiKey}`,
111
+ 'Content-Type': 'application/json',
112
+ 'Accept': 'application/json'
113
+ },
114
+ body: JSON.stringify(requestBody),
115
+ signal
116
+ });
117
+ if (!response.ok) {
118
+ const errorText = await response.text().catch(() => 'Failed to get error details');
119
+ throw new ModelAPIError(`SiliconFlow API request failed: ${response.status} ${response.statusText}`, {
120
+ status: response.status,
121
+ statusText: response.statusText,
122
+ errorDetails: errorText,
123
+ endpoint: apiUrl
124
+ });
125
+ }
126
+ const responseData = await response.json();
127
+ return this.parseResponse(responseData);
128
+ }
129
+ }
130
+ //# sourceMappingURL=siliconflow-adapter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"siliconflow-adapter.js","sourceRoot":"","sources":["../../../src/adapters/siliconflow-adapter.ts"],"names":[],"mappings":"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"}