sloth-d2c-mcp 1.0.4-beta100

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 (34) hide show
  1. package/README.md +83 -0
  2. package/cli/run.js +328 -0
  3. package/cli/sloth-server.log +1622 -0
  4. package/dist/build/config-manager/index.js +240 -0
  5. package/dist/build/core/prompt-builder.js +366 -0
  6. package/dist/build/core/sampling.js +375 -0
  7. package/dist/build/core/types.js +1 -0
  8. package/dist/build/index.js +852 -0
  9. package/dist/build/interceptor/client.js +142 -0
  10. package/dist/build/interceptor/vscode.js +143 -0
  11. package/dist/build/interceptor/web.js +28 -0
  12. package/dist/build/plugin/index.js +4 -0
  13. package/dist/build/plugin/loader.js +349 -0
  14. package/dist/build/plugin/manager.js +129 -0
  15. package/dist/build/plugin/types.js +6 -0
  16. package/dist/build/server.js +2116 -0
  17. package/dist/build/socket-client.js +166 -0
  18. package/dist/build/socket-server.js +260 -0
  19. package/dist/build/utils/client-capabilities.js +143 -0
  20. package/dist/build/utils/extract.js +168 -0
  21. package/dist/build/utils/file-manager.js +868 -0
  22. package/dist/build/utils/image-matcher.js +154 -0
  23. package/dist/build/utils/logger.js +90 -0
  24. package/dist/build/utils/opencv-loader.js +70 -0
  25. package/dist/build/utils/prompt-parser.js +46 -0
  26. package/dist/build/utils/tj.js +139 -0
  27. package/dist/build/utils/update.js +100 -0
  28. package/dist/build/utils/utils.js +184 -0
  29. package/dist/build/utils/vscode-logger.js +133 -0
  30. package/dist/build/utils/webpack-substitutions.js +196 -0
  31. package/dist/interceptor-web/dist/build-report.json +18 -0
  32. package/dist/interceptor-web/dist/detail.html +1 -0
  33. package/dist/interceptor-web/dist/index.html +1 -0
  34. package/package.json +96 -0
@@ -0,0 +1,168 @@
1
+ /**
2
+ * 从LLM的文本输出中提取JSON代码块
3
+ * @param text LLM返回的文本内容
4
+ * @returns 提取到的JSON对象和解析状态
5
+ */
6
+ export function extractJson(text) {
7
+ try {
8
+ // 移除文本前后的空白字符
9
+ const trimmedText = text.trim();
10
+ // 正则表达式匹配 ```json 代码块
11
+ const jsonBlockRegex = /```json\s*\n([\s\S]*?)\n\s*```/gi;
12
+ const matches = Array.from(trimmedText.matchAll(jsonBlockRegex));
13
+ if (matches.length > 0) {
14
+ // 取最后一个匹配的JSON代码块
15
+ const jsonContent = matches[matches.length - 1][1].trim();
16
+ try {
17
+ const parsed = JSON.parse(jsonContent);
18
+ return { state: 'successful-parse', value: parsed };
19
+ }
20
+ catch (parseError) {
21
+ return {
22
+ state: 'failed-parse',
23
+ error: `JSON解析失败: ${parseError instanceof Error ? parseError.message : String(parseError)}`
24
+ };
25
+ }
26
+ }
27
+ // 如果没有找到 ```json 代码块,尝试直接解析整个文本
28
+ // 寻找可能的JSON对象(以 { 开始,以 } 结束)
29
+ const jsonObjectRegex = /\{[\s\S]*\}/;
30
+ const jsonMatch = trimmedText.match(jsonObjectRegex);
31
+ if (jsonMatch) {
32
+ try {
33
+ const parsed = JSON.parse(jsonMatch[0]);
34
+ return { state: 'successful-parse', value: parsed };
35
+ }
36
+ catch (parseError) {
37
+ return {
38
+ state: 'failed-parse',
39
+ error: `JSON对象解析失败: ${parseError instanceof Error ? parseError.message : String(parseError)}`
40
+ };
41
+ }
42
+ }
43
+ // 尝试寻找数组格式的JSON(以 [ 开始,以 ] 结束)
44
+ const jsonArrayRegex = /\[[\s\S]*\]/;
45
+ const arrayMatch = trimmedText.match(jsonArrayRegex);
46
+ if (arrayMatch) {
47
+ try {
48
+ const parsed = JSON.parse(arrayMatch[0]);
49
+ return { state: 'successful-parse', value: parsed };
50
+ }
51
+ catch (parseError) {
52
+ return {
53
+ state: 'failed-parse',
54
+ error: `JSON数组解析失败: ${parseError instanceof Error ? parseError.message : String(parseError)}`
55
+ };
56
+ }
57
+ }
58
+ return {
59
+ state: 'failed-parse',
60
+ error: '未找到有效的JSON内容。请确保响应包含 ```json 代码块或有效的JSON对象/数组。'
61
+ };
62
+ }
63
+ catch (error) {
64
+ return {
65
+ state: 'failed-parse',
66
+ error: `提取JSON时发生错误: ${error instanceof Error ? error.message : String(error)}`
67
+ };
68
+ }
69
+ }
70
+ /**
71
+ * 从 markdown 文本中提取代码块
72
+ * 遵循 CommonMark 规范,使用三个反引号包围的代码块格式
73
+ * 支持从代码块 info string 中提取组件名,格式:```language:ComponentName
74
+ * @param text 包含 markdown 代码块的文本
75
+ * @returns 提取到的代码块数组
76
+ */
77
+ export function extractCodeBlocks(text) {
78
+ const trimmedText = text.trim();
79
+ // 匹配带有组件名的代码块
80
+ // 格式: ```language:ComponentName\ncode\n```
81
+ // 组件名是可选的,通过冒号分隔
82
+ // 示例: ```tsx:UserCard 或 ```vue:ProductList
83
+ const codeBlockRegex = /```([\w-]+)(?::([A-Z][a-zA-Z0-9]*))?\s*\r?\n([\s\S]*?)\r?\n?\s*```/g;
84
+ const codeBlocks = [];
85
+ let match;
86
+ while ((match = codeBlockRegex.exec(trimmedText)) !== null) {
87
+ const language = match[1];
88
+ const declaredComponentName = match[2]; // 从 info string 中提取的组件名(可能为 undefined)
89
+ const code = match[3].trim();
90
+ if (code) {
91
+ // 优先使用声明的组件名,否则降级到正则提取
92
+ const componentName = declaredComponentName || extractComponentName(code, language);
93
+ codeBlocks.push({
94
+ language,
95
+ code,
96
+ componentName
97
+ });
98
+ }
99
+ }
100
+ return codeBlocks;
101
+ }
102
+ /**
103
+ * @deprecated: 为支持跨框架已废弃,改为从模型返回中提取
104
+ * 从代码中提取组件名
105
+ * 支持多种常见的组件定义模式
106
+ * @param code 代码内容
107
+ * @param language 编程语言
108
+ * @returns 组件名或 undefined
109
+ */
110
+ export function extractComponentName(code, language) {
111
+ // 移除注释和空白字符
112
+ const cleanCode = code.trim();
113
+ // React 函数组件模式
114
+ const patterns = [
115
+ // export default function ComponentName / export default async function ComponentName
116
+ /export\s+default\s+(?:async\s+)?function\s+([A-Z][a-zA-Z0-9]*)/,
117
+ // export async function ComponentName / export function ComponentName
118
+ /export\s+(?:async\s+)?function\s+([A-Z][a-zA-Z0-9]*)/,
119
+ // function ComponentName
120
+ /^function\s+([A-Z][a-zA-Z0-9]*)/m,
121
+ // export default memo(function ComponentName ...) / React.memo
122
+ /export\s+default\s+(?:React\.)?memo\(\s*function\s+([A-Z][a-zA-Z0-9]*)/,
123
+ // export default forwardRef(..., function ComponentName ...) / React.forwardRef
124
+ /export\s+default\s+(?:React\.)?forwardRef\([^,]*,\s*function\s+([A-Z][a-zA-Z0-9]*)/,
125
+ // export default NamedComponent
126
+ /export\s+default\s+([A-Z][a-zA-Z0-9]*)/,
127
+ // export const ComponentName: Type = ... (可选类型注解)
128
+ /export\s+const\s+([A-Z][a-zA-Z0-9]*)\s*(?::[^=]+)?\s*=/,
129
+ // const ComponentName: Type = ... (可选类型注解)
130
+ /const\s+([A-Z][a-zA-Z0-9]*)\s*(?::[^=]+)?\s*=/,
131
+ // class ComponentName / export default class ComponentName
132
+ /export\s+default\s+class\s+([A-Z][a-zA-Z0-9]*)/,
133
+ /class\s+([A-Z][a-zA-Z0-9]*)/,
134
+ // export { ComponentName } / export { ComponentName as default }
135
+ /export\s*\{\s*([A-Z][a-zA-Z0-9]*)\s*(?:as\s*default)?\s*\}/,
136
+ // interface ComponentNameProps / type ComponentNameProps (用于推断组件名)
137
+ /interface\s+([A-Z][a-zA-Z0-9]*)Props/,
138
+ /type\s+([A-Z][a-zA-Z0-9]*)Props/
139
+ ];
140
+ for (const pattern of patterns) {
141
+ const match = cleanCode.match(pattern);
142
+ if (match && match[1]) {
143
+ let componentName = match[1];
144
+ // 如果是 Props 接口,移除 Props 后缀
145
+ if (componentName.endsWith('Props')) {
146
+ componentName = componentName.slice(0, -5);
147
+ }
148
+ // 验证组件名符合 PascalCase 规范
149
+ if (/^[A-Z][a-zA-Z0-9]*$/.test(componentName)) {
150
+ return componentName;
151
+ }
152
+ }
153
+ }
154
+ return undefined;
155
+ }
156
+ /**
157
+ * 从文本中提取所有代码块并获取组件信息
158
+ * @param text 包含代码块的文本
159
+ * @returns 包含代码和组件名的信息数组
160
+ */
161
+ export function extractCodeAndComponents(text) {
162
+ const codeBlocks = extractCodeBlocks(text);
163
+ return codeBlocks.map(block => ({
164
+ code: block.code,
165
+ componentName: block.componentName,
166
+ language: block.language
167
+ }));
168
+ }