autosnippet 3.0.2 → 3.0.6
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 +85 -239
- package/bin/mcp-server.js +12 -1
- package/dashboard/dist/assets/{icons-Cdq22n2i.js → icons-eQ_rWCus.js} +97 -102
- package/dashboard/dist/assets/index-B3Nnkdxi.js +133 -0
- package/dashboard/dist/assets/index-BFNDAqh3.css +1 -0
- package/dashboard/dist/index.html +3 -3
- package/lib/cli/SetupService.js +9 -12
- package/lib/cli/UpgradeService.js +15 -17
- package/lib/core/AstAnalyzer.js +2 -2
- package/lib/core/ast/ensure-grammars.js +2 -0
- package/lib/core/ast/index.js +8 -0
- package/lib/core/ast/lang-rust.js +695 -0
- package/lib/core/discovery/PythonDiscoverer.js +3 -0
- package/lib/core/discovery/RustDiscoverer.js +467 -0
- package/lib/core/discovery/index.js +3 -0
- package/lib/core/enhancement/django-enhancement.js +169 -3
- package/lib/core/enhancement/fastapi-enhancement.js +149 -3
- package/lib/core/enhancement/go-grpc-enhancement.js +4 -0
- package/lib/core/enhancement/go-web-enhancement.js +6 -0
- package/lib/core/enhancement/index.js +5 -0
- package/lib/core/enhancement/langchain-enhancement.js +233 -0
- package/lib/core/enhancement/ml-enhancement.js +265 -0
- package/lib/core/enhancement/nextjs-enhancement.js +219 -0
- package/lib/core/enhancement/node-server-enhancement.js +178 -4
- package/lib/core/enhancement/react-enhancement.js +165 -4
- package/lib/core/enhancement/rust-tokio-enhancement.js +231 -0
- package/lib/core/enhancement/rust-web-enhancement.js +256 -0
- package/lib/core/enhancement/spring-enhancement.js +2 -0
- package/lib/core/enhancement/vue-enhancement.js +143 -2
- package/lib/external/ai/AiProvider.js +45 -6
- package/lib/external/mcp/handlers/bootstrap/skills.js +2 -0
- package/lib/external/mcp/handlers/bootstrap.js +33 -9
- package/lib/external/mcp/handlers/guard.js +42 -0
- package/lib/http/routes/candidates.js +7 -1
- package/lib/service/chat/ChatAgent.js +1 -0
- package/lib/service/chat/tools.js +5 -1
- package/lib/service/guard/ComplianceReporter.js +20 -7
- package/lib/service/guard/GuardCheckEngine.js +156 -5
- package/lib/service/guard/SourceFileCollector.js +15 -0
- package/package.json +28 -6
- package/scripts/install-vscode-copilot.js +32 -97
- package/scripts/setup-mcp-config.js +18 -36
- package/skills/autosnippet-coldstart/SKILL.md +4 -2
- package/skills/autosnippet-concepts/SKILL.md +5 -3
- package/skills/autosnippet-reference-rust/SKILL.md +401 -0
- package/skills/autosnippet-structure/SKILL.md +1 -1
- package/templates/recipes-setup/README.md +2 -2
- package/templates/recipes-setup/_template.md +1 -1
- package/dashboard/dist/assets/index-ClkyPkDX.js +0 -133
- package/dashboard/dist/assets/index-t4QrJwv1.css +0 -1
|
@@ -1,6 +1,15 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Django Enhancement Pack
|
|
3
3
|
* 条件: { languages: ['python'], frameworks: ['django'] }
|
|
4
|
+
*
|
|
5
|
+
* 覆盖 Django 全栈生态:
|
|
6
|
+
* - Model 字段/关系/Manager/QuerySet
|
|
7
|
+
* - DRF (Django REST Framework) Serializer/ViewSet
|
|
8
|
+
* - URL 路由约定
|
|
9
|
+
* - Signal (pre_save/post_save)
|
|
10
|
+
* - Middleware
|
|
11
|
+
* - Management Command
|
|
12
|
+
* - Celery Task 集成
|
|
4
13
|
*/
|
|
5
14
|
|
|
6
15
|
import { EnhancementPack } from './EnhancementPack.js';
|
|
@@ -10,7 +19,7 @@ class DjangoEnhancement extends EnhancementPack {
|
|
|
10
19
|
return 'django';
|
|
11
20
|
}
|
|
12
21
|
get displayName() {
|
|
13
|
-
return 'Django Enhancement';
|
|
22
|
+
return 'Django / DRF Enhancement';
|
|
14
23
|
}
|
|
15
24
|
get conditions() {
|
|
16
25
|
return { languages: ['python'], frameworks: ['django'] };
|
|
@@ -22,7 +31,7 @@ class DjangoEnhancement extends EnhancementPack {
|
|
|
22
31
|
id: 'django-model-scan',
|
|
23
32
|
label: 'Django Model 扫描',
|
|
24
33
|
guide:
|
|
25
|
-
'Model 字段与关系扫描(ForeignKey/ManyToMany/OneToOne)、Manager 自定义、QuerySet
|
|
34
|
+
'Model 字段与关系扫描(ForeignKey/ManyToMany/OneToOne)、Manager 自定义、QuerySet 链路、Meta 选项 (ordering/indexes/constraints)',
|
|
26
35
|
knowledgeTypes: ['architecture', 'code-pattern'],
|
|
27
36
|
skillWorthy: true,
|
|
28
37
|
dualOutput: true,
|
|
@@ -32,11 +41,82 @@ class DjangoEnhancement extends EnhancementPack {
|
|
|
32
41
|
'Django Model definitions, field relationships and custom managers (auto-generated by enhancement)',
|
|
33
42
|
},
|
|
34
43
|
},
|
|
44
|
+
{
|
|
45
|
+
id: 'django-drf-scan',
|
|
46
|
+
label: 'DRF API 分析',
|
|
47
|
+
guide:
|
|
48
|
+
'Django REST Framework 分析 — Serializer/ModelSerializer 字段映射、ViewSet/GenericAPIView 层级、Router 注册、Permission/Throttle 策略、Pagination 配置',
|
|
49
|
+
knowledgeTypes: ['architecture', 'code-pattern'],
|
|
50
|
+
skillWorthy: true,
|
|
51
|
+
dualOutput: true,
|
|
52
|
+
skillMeta: {
|
|
53
|
+
name: 'project-django-drf',
|
|
54
|
+
description:
|
|
55
|
+
'DRF serializers, viewsets, permissions and router configuration (auto-generated by enhancement)',
|
|
56
|
+
},
|
|
57
|
+
},
|
|
58
|
+
{
|
|
59
|
+
id: 'django-signal-middleware-scan',
|
|
60
|
+
label: 'Signal / Middleware 分析',
|
|
61
|
+
guide:
|
|
62
|
+
'Signal 分析 (pre_save/post_save/pre_delete/post_delete/m2m_changed 等) 及 Middleware 链路 (MIDDLEWARE 顺序)、自定义 Middleware 实现',
|
|
63
|
+
knowledgeTypes: ['architecture'],
|
|
64
|
+
skillWorthy: true,
|
|
65
|
+
dualOutput: true,
|
|
66
|
+
skillMeta: {
|
|
67
|
+
name: 'project-django-signals',
|
|
68
|
+
description:
|
|
69
|
+
'Django signal handlers, middleware chain ordering and custom middleware (auto-generated by enhancement)',
|
|
70
|
+
},
|
|
71
|
+
},
|
|
72
|
+
];
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
getGuardRules() {
|
|
76
|
+
return [
|
|
77
|
+
{
|
|
78
|
+
ruleId: 'django-n-plus-one',
|
|
79
|
+
category: 'performance',
|
|
80
|
+
dimension: 'file',
|
|
81
|
+
severity: 'warning',
|
|
82
|
+
languages: ['python'],
|
|
83
|
+
pattern: /\.objects\.(?:all|filter)\([^)]*\)[\s\S]*?for\s+\w+\s+in/,
|
|
84
|
+
message: 'QuerySet 在循环中可能触发 N+1 查询 — 使用 select_related() / prefetch_related() 优化',
|
|
85
|
+
},
|
|
86
|
+
{
|
|
87
|
+
ruleId: 'django-raw-sql',
|
|
88
|
+
category: 'safety',
|
|
89
|
+
dimension: 'file',
|
|
90
|
+
severity: 'warning',
|
|
91
|
+
languages: ['python'],
|
|
92
|
+
pattern: /\.raw\s*\(|cursor\.execute\s*\(/,
|
|
93
|
+
message: '使用 raw SQL 需确保参数化查询,防止 SQL 注入 — 优先使用 ORM QuerySet',
|
|
94
|
+
},
|
|
95
|
+
{
|
|
96
|
+
ruleId: 'django-no-null-charfield',
|
|
97
|
+
category: 'correctness',
|
|
98
|
+
dimension: 'file',
|
|
99
|
+
severity: 'info',
|
|
100
|
+
languages: ['python'],
|
|
101
|
+
pattern: /(?:CharField|TextField|SlugField|URLField|EmailField)\s*\([^)]*null\s*=\s*True/,
|
|
102
|
+
message: 'Django 约定: CharField/TextField 不应使用 null=True — 使用 blank=True + default="" 代替',
|
|
103
|
+
},
|
|
104
|
+
{
|
|
105
|
+
ruleId: 'django-model-str',
|
|
106
|
+
category: 'style',
|
|
107
|
+
dimension: 'file',
|
|
108
|
+
severity: 'info',
|
|
109
|
+
languages: ['python'],
|
|
110
|
+
pattern: /class\s+\w+\((?:models\.)?Model\):\s*\n(?:(?!\s*def\s+__str__)[\s\S])*?(?=\nclass\s|\Z)/,
|
|
111
|
+
message: 'Django Model 建议实现 __str__ 方法 — 便于 admin 和 shell 调试',
|
|
112
|
+
},
|
|
35
113
|
];
|
|
36
114
|
}
|
|
37
115
|
|
|
38
116
|
detectPatterns(astSummary) {
|
|
39
117
|
const patterns = [];
|
|
118
|
+
|
|
119
|
+
// ── Django Models ──
|
|
40
120
|
for (const cls of astSummary.classes || []) {
|
|
41
121
|
if (cls.superclass && /Model$/.test(cls.superclass)) {
|
|
42
122
|
patterns.push({
|
|
@@ -46,7 +126,11 @@ class DjangoEnhancement extends EnhancementPack {
|
|
|
46
126
|
confidence: 0.9,
|
|
47
127
|
});
|
|
48
128
|
}
|
|
49
|
-
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
// ── Django Views / ViewSets ──
|
|
132
|
+
for (const cls of astSummary.classes || []) {
|
|
133
|
+
if (cls.superclass && /View$|ViewSet$|APIView$|GenericAPIView/.test(cls.superclass)) {
|
|
50
134
|
patterns.push({
|
|
51
135
|
type: 'django-view',
|
|
52
136
|
className: cls.name,
|
|
@@ -54,6 +138,22 @@ class DjangoEnhancement extends EnhancementPack {
|
|
|
54
138
|
confidence: 0.85,
|
|
55
139
|
});
|
|
56
140
|
}
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
// ── DRF Serializers ──
|
|
144
|
+
for (const cls of astSummary.classes || []) {
|
|
145
|
+
if (cls.superclass && /Serializer$|ModelSerializer|HyperlinkedModelSerializer/.test(cls.superclass)) {
|
|
146
|
+
patterns.push({
|
|
147
|
+
type: 'drf-serializer',
|
|
148
|
+
className: cls.name,
|
|
149
|
+
line: cls.line,
|
|
150
|
+
confidence: 0.9,
|
|
151
|
+
});
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
// ── Django Management Commands ──
|
|
156
|
+
for (const cls of astSummary.classes || []) {
|
|
57
157
|
if (cls.superclass && /BaseCommand/.test(cls.superclass)) {
|
|
58
158
|
patterns.push({
|
|
59
159
|
type: 'django-management-command',
|
|
@@ -63,6 +163,72 @@ class DjangoEnhancement extends EnhancementPack {
|
|
|
63
163
|
});
|
|
64
164
|
}
|
|
65
165
|
}
|
|
166
|
+
|
|
167
|
+
// ── Django Middleware ──
|
|
168
|
+
for (const cls of astSummary.classes || []) {
|
|
169
|
+
const nameLower = cls.name?.toLowerCase() || '';
|
|
170
|
+
if (nameLower.includes('middleware')) {
|
|
171
|
+
patterns.push({
|
|
172
|
+
type: 'django-middleware',
|
|
173
|
+
className: cls.name,
|
|
174
|
+
line: cls.line,
|
|
175
|
+
confidence: 0.8,
|
|
176
|
+
});
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
// ── Django Admin ──
|
|
181
|
+
for (const cls of astSummary.classes || []) {
|
|
182
|
+
if (cls.superclass && /ModelAdmin|TabularInline|StackedInline/.test(cls.superclass)) {
|
|
183
|
+
patterns.push({
|
|
184
|
+
type: 'django-admin',
|
|
185
|
+
className: cls.name,
|
|
186
|
+
line: cls.line,
|
|
187
|
+
confidence: 0.9,
|
|
188
|
+
});
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
// ── Signal handler functions ──
|
|
193
|
+
for (const m of astSummary.methods || []) {
|
|
194
|
+
if (m.decorators?.some((d) => /receiver/.test(d))) {
|
|
195
|
+
patterns.push({
|
|
196
|
+
type: 'django-signal-handler',
|
|
197
|
+
methodName: m.name,
|
|
198
|
+
line: m.line,
|
|
199
|
+
confidence: 0.9,
|
|
200
|
+
});
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
// ── Celery tasks ──
|
|
205
|
+
for (const m of astSummary.methods || []) {
|
|
206
|
+
if (m.decorators?.some((d) => /@(?:shared_task|app\.task|task)/.test(d))) {
|
|
207
|
+
patterns.push({
|
|
208
|
+
type: 'django-celery-task',
|
|
209
|
+
methodName: m.name,
|
|
210
|
+
line: m.line,
|
|
211
|
+
confidence: 0.9,
|
|
212
|
+
});
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
// ── Django ecosystem imports ──
|
|
217
|
+
const djangoImports = (astSummary.imports || []).filter(
|
|
218
|
+
(imp) =>
|
|
219
|
+
imp.includes('django') ||
|
|
220
|
+
imp.includes('rest_framework') ||
|
|
221
|
+
imp.includes('celery') ||
|
|
222
|
+
imp.includes('django_filters')
|
|
223
|
+
);
|
|
224
|
+
if (djangoImports.length > 0) {
|
|
225
|
+
patterns.push({
|
|
226
|
+
type: 'django-ecosystem-usage',
|
|
227
|
+
importCount: djangoImports.length,
|
|
228
|
+
confidence: 0.85,
|
|
229
|
+
});
|
|
230
|
+
}
|
|
231
|
+
|
|
66
232
|
return patterns;
|
|
67
233
|
}
|
|
68
234
|
}
|
|
@@ -1,6 +1,13 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* FastAPI Enhancement Pack
|
|
3
3
|
* 条件: { languages: ['python'], frameworks: ['fastapi'] }
|
|
4
|
+
*
|
|
5
|
+
* 覆盖 FastAPI 全栈生态:
|
|
6
|
+
* - 路由装饰器 + Pydantic 模型
|
|
7
|
+
* - Depends() 依赖注入
|
|
8
|
+
* - Middleware / CORS / BackgroundTask
|
|
9
|
+
* - WebSocket
|
|
10
|
+
* - SQLAlchemy / Tortoise ORM 集成模式
|
|
4
11
|
*/
|
|
5
12
|
|
|
6
13
|
import { EnhancementPack } from './EnhancementPack.js';
|
|
@@ -21,7 +28,7 @@ class FastAPIEnhancement extends EnhancementPack {
|
|
|
21
28
|
{
|
|
22
29
|
id: 'fastapi-route-scan',
|
|
23
30
|
label: 'FastAPI 路由分析',
|
|
24
|
-
guide: 'Route 装饰器(@app.get/post/put/delete)、Pydantic Model/Schema、DI (Depends())',
|
|
31
|
+
guide: 'Route 装饰器(@app.get/post/put/delete)、APIRouter 分组、Pydantic Model/Schema、DI (Depends())、路由参数声明',
|
|
25
32
|
knowledgeTypes: ['architecture', 'code-pattern'],
|
|
26
33
|
skillWorthy: true,
|
|
27
34
|
dualOutput: true,
|
|
@@ -31,13 +38,84 @@ class FastAPIEnhancement extends EnhancementPack {
|
|
|
31
38
|
'FastAPI route definitions, Pydantic schemas and dependency injection (auto-generated by enhancement)',
|
|
32
39
|
},
|
|
33
40
|
},
|
|
41
|
+
{
|
|
42
|
+
id: 'fastapi-middleware-scan',
|
|
43
|
+
label: 'FastAPI 中间件分析',
|
|
44
|
+
guide:
|
|
45
|
+
'FastAPI Middleware 分析 — @app.middleware("http") 自定义中间件、CORS 配置、Trusted Host、GZip、BackgroundTasks 使用模式、Lifespan 事件 (startup/shutdown)',
|
|
46
|
+
knowledgeTypes: ['architecture', 'code-pattern'],
|
|
47
|
+
skillWorthy: true,
|
|
48
|
+
dualOutput: true,
|
|
49
|
+
skillMeta: {
|
|
50
|
+
name: 'project-fastapi-middleware',
|
|
51
|
+
description:
|
|
52
|
+
'FastAPI middleware stack, CORS config, lifespan events and background tasks (auto-generated by enhancement)',
|
|
53
|
+
},
|
|
54
|
+
},
|
|
55
|
+
{
|
|
56
|
+
id: 'fastapi-orm-scan',
|
|
57
|
+
label: 'ORM / DB 模式分析',
|
|
58
|
+
guide:
|
|
59
|
+
'ORM 集成分析 — SQLAlchemy 2.0 async session 模式 / Tortoise ORM model 定义、数据库迁移 (Alembic)、Repository Pattern、Session 生命周期管理 (get_db Depends)',
|
|
60
|
+
knowledgeTypes: ['architecture', 'code-pattern'],
|
|
61
|
+
skillWorthy: true,
|
|
62
|
+
dualOutput: true,
|
|
63
|
+
skillMeta: {
|
|
64
|
+
name: 'project-fastapi-orm',
|
|
65
|
+
description:
|
|
66
|
+
'FastAPI ORM integration — SQLAlchemy async sessions, Alembic migrations and repository patterns (auto-generated by enhancement)',
|
|
67
|
+
},
|
|
68
|
+
},
|
|
69
|
+
];
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
getGuardRules() {
|
|
73
|
+
return [
|
|
74
|
+
{
|
|
75
|
+
ruleId: 'fastapi-sync-in-async',
|
|
76
|
+
category: 'performance',
|
|
77
|
+
dimension: 'file',
|
|
78
|
+
severity: 'warning',
|
|
79
|
+
languages: ['python'],
|
|
80
|
+
pattern: /async\s+def\s+\w+[\s\S]*?(?:time\.sleep|open\(|os\.read|subprocess\.run)/,
|
|
81
|
+
message: 'async 路由中不应使用阻塞操作 (time.sleep/open/subprocess.run) — 使用 asyncio 版本或 run_in_executor',
|
|
82
|
+
},
|
|
83
|
+
{
|
|
84
|
+
ruleId: 'fastapi-no-response-model',
|
|
85
|
+
category: 'style',
|
|
86
|
+
dimension: 'file',
|
|
87
|
+
severity: 'info',
|
|
88
|
+
languages: ['python'],
|
|
89
|
+
pattern: /@(?:app|router)\.(?:get|post|put|delete|patch)\s*\([^)]*\)\s*\n\s*(?:async\s+)?def\s+\w+\([^)]*\)(?!\s*->)/,
|
|
90
|
+
message: 'FastAPI 路由建议声明 response_model 或返回类型注解 — 便于自动生成 OpenAPI 文档',
|
|
91
|
+
},
|
|
92
|
+
{
|
|
93
|
+
ruleId: 'fastapi-bare-except',
|
|
94
|
+
category: 'correctness',
|
|
95
|
+
dimension: 'file',
|
|
96
|
+
severity: 'warning',
|
|
97
|
+
languages: ['python'],
|
|
98
|
+
pattern: /except\s*:/,
|
|
99
|
+
message: '避免 bare except — 使用 except Exception 或具体异常类,否则会吞掉 KeyboardInterrupt/SystemExit',
|
|
100
|
+
},
|
|
101
|
+
{
|
|
102
|
+
ruleId: 'fastapi-no-star-import',
|
|
103
|
+
category: 'style',
|
|
104
|
+
dimension: 'file',
|
|
105
|
+
severity: 'warning',
|
|
106
|
+
languages: ['python'],
|
|
107
|
+
pattern: /from\s+\w+\s+import\s+\*/,
|
|
108
|
+
message: '避免 star import (from x import *) — 使用显式 import 以保证类型检查和 IDE 支持',
|
|
109
|
+
},
|
|
34
110
|
];
|
|
35
111
|
}
|
|
36
112
|
|
|
37
113
|
detectPatterns(astSummary) {
|
|
38
114
|
const patterns = [];
|
|
115
|
+
|
|
116
|
+
// ── Pydantic models ──
|
|
39
117
|
for (const cls of astSummary.classes || []) {
|
|
40
|
-
if (cls.superclass && /BaseModel/.test(cls.superclass)) {
|
|
118
|
+
if (cls.superclass && /BaseModel|BaseSettings/.test(cls.superclass)) {
|
|
41
119
|
patterns.push({
|
|
42
120
|
type: 'pydantic-model',
|
|
43
121
|
className: cls.name,
|
|
@@ -46,8 +124,10 @@ class FastAPIEnhancement extends EnhancementPack {
|
|
|
46
124
|
});
|
|
47
125
|
}
|
|
48
126
|
}
|
|
127
|
+
|
|
128
|
+
// ── FastAPI route handlers ──
|
|
49
129
|
for (const m of astSummary.methods || []) {
|
|
50
|
-
if (m.decorators?.some((d) => /@app\.(get|post|put|delete|patch)/.test(d))) {
|
|
130
|
+
if (m.decorators?.some((d) => /@(?:app|router)\.(?:get|post|put|delete|patch|options|head)/.test(d))) {
|
|
51
131
|
patterns.push({
|
|
52
132
|
type: 'fastapi-route',
|
|
53
133
|
methodName: m.name,
|
|
@@ -56,6 +136,72 @@ class FastAPIEnhancement extends EnhancementPack {
|
|
|
56
136
|
});
|
|
57
137
|
}
|
|
58
138
|
}
|
|
139
|
+
|
|
140
|
+
// ── Dependency injection functions ──
|
|
141
|
+
for (const m of astSummary.methods || []) {
|
|
142
|
+
if (!m.className) {
|
|
143
|
+
const nameLower = m.name?.toLowerCase() || '';
|
|
144
|
+
if (
|
|
145
|
+
nameLower.startsWith('get_') && (
|
|
146
|
+
nameLower.includes('db') ||
|
|
147
|
+
nameLower.includes('session') ||
|
|
148
|
+
nameLower.includes('current_user') ||
|
|
149
|
+
nameLower.includes('settings') ||
|
|
150
|
+
nameLower.includes('service')
|
|
151
|
+
)
|
|
152
|
+
) {
|
|
153
|
+
patterns.push({
|
|
154
|
+
type: 'fastapi-dependency',
|
|
155
|
+
methodName: m.name,
|
|
156
|
+
line: m.line,
|
|
157
|
+
confidence: 0.8,
|
|
158
|
+
});
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
// ── SQLAlchemy models ──
|
|
164
|
+
for (const cls of astSummary.classes || []) {
|
|
165
|
+
if (cls.superclass && /Base$|DeclarativeBase/.test(cls.superclass)) {
|
|
166
|
+
patterns.push({
|
|
167
|
+
type: 'sqlalchemy-model',
|
|
168
|
+
className: cls.name,
|
|
169
|
+
line: cls.line,
|
|
170
|
+
confidence: 0.85,
|
|
171
|
+
});
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
// ── Exception handlers ──
|
|
176
|
+
for (const cls of astSummary.classes || []) {
|
|
177
|
+
if (cls.superclass && /HTTPException|Exception/.test(cls.superclass)) {
|
|
178
|
+
patterns.push({
|
|
179
|
+
type: 'fastapi-exception',
|
|
180
|
+
className: cls.name,
|
|
181
|
+
line: cls.line,
|
|
182
|
+
confidence: 0.75,
|
|
183
|
+
});
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
// ── FastAPI ecosystem imports ──
|
|
188
|
+
const fastapiImports = (astSummary.imports || []).filter(
|
|
189
|
+
(imp) =>
|
|
190
|
+
imp.includes('fastapi') ||
|
|
191
|
+
imp.includes('pydantic') ||
|
|
192
|
+
imp.includes('sqlalchemy') ||
|
|
193
|
+
imp.includes('tortoise') ||
|
|
194
|
+
imp.includes('alembic') ||
|
|
195
|
+
imp.includes('uvicorn')
|
|
196
|
+
);
|
|
197
|
+
if (fastapiImports.length > 0) {
|
|
198
|
+
patterns.push({
|
|
199
|
+
type: 'fastapi-ecosystem-usage',
|
|
200
|
+
importCount: fastapiImports.length,
|
|
201
|
+
confidence: 0.85,
|
|
202
|
+
});
|
|
203
|
+
}
|
|
204
|
+
|
|
59
205
|
return patterns;
|
|
60
206
|
}
|
|
61
207
|
}
|
|
@@ -59,6 +59,8 @@ class GoGrpcEnhancement extends EnhancementPack {
|
|
|
59
59
|
return [
|
|
60
60
|
{
|
|
61
61
|
ruleId: 'go-grpc-unimplemented-embed',
|
|
62
|
+
category: 'correctness',
|
|
63
|
+
dimension: 'file',
|
|
62
64
|
severity: 'warning',
|
|
63
65
|
languages: ['go'],
|
|
64
66
|
pattern: /Unimplemented\w+Server\b/,
|
|
@@ -67,6 +69,8 @@ class GoGrpcEnhancement extends EnhancementPack {
|
|
|
67
69
|
},
|
|
68
70
|
{
|
|
69
71
|
ruleId: 'go-grpc-status-error',
|
|
72
|
+
category: 'correctness',
|
|
73
|
+
dimension: 'file',
|
|
70
74
|
severity: 'info',
|
|
71
75
|
languages: ['go'],
|
|
72
76
|
pattern: /fmt\.Errorf|errors\.New/,
|
|
@@ -59,6 +59,8 @@ class GoWebEnhancement extends EnhancementPack {
|
|
|
59
59
|
return [
|
|
60
60
|
{
|
|
61
61
|
ruleId: 'go-handler-abort-return',
|
|
62
|
+
category: 'correctness',
|
|
63
|
+
dimension: 'file',
|
|
62
64
|
severity: 'warning',
|
|
63
65
|
languages: ['go'],
|
|
64
66
|
pattern: /\.Abort\w*\([^)]*\)[^}]*\n\s*[^}\s/]/,
|
|
@@ -66,6 +68,8 @@ class GoWebEnhancement extends EnhancementPack {
|
|
|
66
68
|
},
|
|
67
69
|
{
|
|
68
70
|
ruleId: 'go-no-naked-goroutine',
|
|
71
|
+
category: 'correctness',
|
|
72
|
+
dimension: 'file',
|
|
69
73
|
severity: 'warning',
|
|
70
74
|
languages: ['go'],
|
|
71
75
|
pattern: /go\s+func\s*\(/,
|
|
@@ -74,6 +78,8 @@ class GoWebEnhancement extends EnhancementPack {
|
|
|
74
78
|
},
|
|
75
79
|
{
|
|
76
80
|
ruleId: 'go-context-first-param',
|
|
81
|
+
category: 'style',
|
|
82
|
+
dimension: 'file',
|
|
77
83
|
severity: 'info',
|
|
78
84
|
languages: ['go'],
|
|
79
85
|
pattern:
|
|
@@ -40,14 +40,19 @@ export async function initEnhancementRegistry() {
|
|
|
40
40
|
|
|
41
41
|
const packImports = [
|
|
42
42
|
import('./react-enhancement.js'),
|
|
43
|
+
import('./nextjs-enhancement.js'),
|
|
43
44
|
import('./vue-enhancement.js'),
|
|
44
45
|
import('./node-server-enhancement.js'),
|
|
45
46
|
import('./django-enhancement.js'),
|
|
46
47
|
import('./fastapi-enhancement.js'),
|
|
48
|
+
import('./ml-enhancement.js'),
|
|
49
|
+
import('./langchain-enhancement.js'),
|
|
47
50
|
import('./spring-enhancement.js'),
|
|
48
51
|
import('./android-enhancement.js'),
|
|
49
52
|
import('./go-web-enhancement.js'),
|
|
50
53
|
import('./go-grpc-enhancement.js'),
|
|
54
|
+
import('./rust-web-enhancement.js'),
|
|
55
|
+
import('./rust-tokio-enhancement.js'),
|
|
51
56
|
];
|
|
52
57
|
|
|
53
58
|
const results = await Promise.allSettled(packImports);
|