codesift-mcp 0.4.0 → 0.5.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 +94 -25
- package/dist/cli/help.d.ts.map +1 -1
- package/dist/cli/help.js +8 -6
- package/dist/cli/help.js.map +1 -1
- package/dist/cli/platform.d.ts.map +1 -1
- package/dist/cli/platform.js +12 -14
- package/dist/cli/platform.js.map +1 -1
- package/dist/cli/setup.d.ts +1 -1
- package/dist/cli/setup.d.ts.map +1 -1
- package/dist/cli/setup.js +10 -1
- package/dist/cli/setup.js.map +1 -1
- package/dist/formatters.d.ts +2 -2
- package/dist/formatters.d.ts.map +1 -1
- package/dist/formatters.js +23 -0
- package/dist/formatters.js.map +1 -1
- package/dist/instructions.d.ts +1 -1
- package/dist/instructions.d.ts.map +1 -1
- package/dist/instructions.js +21 -21
- package/dist/parser/extractors/php.d.ts.map +1 -1
- package/dist/parser/extractors/php.js +37 -29
- package/dist/parser/extractors/php.js.map +1 -1
- package/dist/parser/extractors/typescript.d.ts.map +1 -1
- package/dist/parser/extractors/typescript.js +43 -0
- package/dist/parser/extractors/typescript.js.map +1 -1
- package/dist/parser/parse-cache.d.ts +39 -0
- package/dist/parser/parse-cache.d.ts.map +1 -0
- package/dist/parser/parse-cache.js +87 -0
- package/dist/parser/parse-cache.js.map +1 -0
- package/dist/parser/parser-manager.d.ts.map +1 -1
- package/dist/parser/parser-manager.js +12 -1
- package/dist/parser/parser-manager.js.map +1 -1
- package/dist/register-tools.d.ts +2 -2
- package/dist/register-tools.d.ts.map +1 -1
- package/dist/register-tools.js +353 -570
- package/dist/register-tools.js.map +1 -1
- package/dist/search/tool-ranker.d.ts +90 -0
- package/dist/search/tool-ranker.d.ts.map +1 -0
- package/dist/search/tool-ranker.js +420 -0
- package/dist/search/tool-ranker.js.map +1 -0
- package/dist/server.js +19 -13
- package/dist/server.js.map +1 -1
- package/dist/storage/usage-tracker.d.ts.map +1 -1
- package/dist/storage/usage-tracker.js +4 -1
- package/dist/storage/usage-tracker.js.map +1 -1
- package/dist/tools/astro-actions.d.ts +54 -0
- package/dist/tools/astro-actions.d.ts.map +1 -0
- package/dist/tools/astro-actions.js +561 -0
- package/dist/tools/astro-actions.js.map +1 -0
- package/dist/tools/astro-audit.d.ts +87 -0
- package/dist/tools/astro-audit.d.ts.map +1 -0
- package/dist/tools/astro-audit.js +345 -0
- package/dist/tools/astro-audit.js.map +1 -0
- package/dist/tools/astro-content-collections.d.ts +44 -0
- package/dist/tools/astro-content-collections.d.ts.map +1 -0
- package/dist/tools/astro-content-collections.js +630 -0
- package/dist/tools/astro-content-collections.js.map +1 -0
- package/dist/tools/astro-islands.d.ts +3 -1
- package/dist/tools/astro-islands.d.ts.map +1 -1
- package/dist/tools/astro-islands.js +19 -4
- package/dist/tools/astro-islands.js.map +1 -1
- package/dist/tools/astro-migration.d.ts +31 -0
- package/dist/tools/astro-migration.d.ts.map +1 -0
- package/dist/tools/astro-migration.js +378 -0
- package/dist/tools/astro-migration.js.map +1 -0
- package/dist/tools/async-correctness.d.ts +26 -0
- package/dist/tools/async-correctness.d.ts.map +1 -0
- package/dist/tools/async-correctness.js +166 -0
- package/dist/tools/async-correctness.js.map +1 -0
- package/dist/tools/django-view-security-tools.d.ts +32 -0
- package/dist/tools/django-view-security-tools.d.ts.map +1 -0
- package/dist/tools/django-view-security-tools.js +184 -0
- package/dist/tools/django-view-security-tools.js.map +1 -0
- package/dist/tools/fastapi-depends.d.ts +63 -0
- package/dist/tools/fastapi-depends.d.ts.map +1 -0
- package/dist/tools/fastapi-depends.js +191 -0
- package/dist/tools/fastapi-depends.js.map +1 -0
- package/dist/tools/hono-analyze-app.js +1 -9
- package/dist/tools/hono-analyze-app.js.map +1 -1
- package/dist/tools/hono-api-contract.d.ts.map +1 -1
- package/dist/tools/hono-api-contract.js +41 -9
- package/dist/tools/hono-api-contract.js.map +1 -1
- package/dist/tools/hono-context-flow.js +1 -9
- package/dist/tools/hono-context-flow.js.map +1 -1
- package/dist/tools/hono-dead-routes.d.ts.map +1 -1
- package/dist/tools/hono-dead-routes.js +2 -9
- package/dist/tools/hono-dead-routes.js.map +1 -1
- package/dist/tools/hono-entry-resolver.d.ts +27 -0
- package/dist/tools/hono-entry-resolver.d.ts.map +1 -0
- package/dist/tools/hono-entry-resolver.js +31 -0
- package/dist/tools/hono-entry-resolver.js.map +1 -0
- package/dist/tools/hono-inline-analyze.js +1 -9
- package/dist/tools/hono-inline-analyze.js.map +1 -1
- package/dist/tools/hono-middleware-chain.d.ts +24 -6
- package/dist/tools/hono-middleware-chain.d.ts.map +1 -1
- package/dist/tools/hono-middleware-chain.js +77 -40
- package/dist/tools/hono-middleware-chain.js.map +1 -1
- package/dist/tools/hono-modules.js +1 -9
- package/dist/tools/hono-modules.js.map +1 -1
- package/dist/tools/hono-response-types.js +1 -9
- package/dist/tools/hono-response-types.js.map +1 -1
- package/dist/tools/hono-rpc-types.js +1 -9
- package/dist/tools/hono-rpc-types.js.map +1 -1
- package/dist/tools/hono-security.d.ts +14 -4
- package/dist/tools/hono-security.d.ts.map +1 -1
- package/dist/tools/hono-security.js +185 -14
- package/dist/tools/hono-security.js.map +1 -1
- package/dist/tools/hono-visualize.js +1 -9
- package/dist/tools/hono-visualize.js.map +1 -1
- package/dist/tools/nest-ext-tools.d.ts +115 -0
- package/dist/tools/nest-ext-tools.d.ts.map +1 -1
- package/dist/tools/nest-ext-tools.js +393 -0
- package/dist/tools/nest-ext-tools.js.map +1 -1
- package/dist/tools/nest-tools.d.ts +27 -0
- package/dist/tools/nest-tools.d.ts.map +1 -1
- package/dist/tools/nest-tools.js +137 -37
- package/dist/tools/nest-tools.js.map +1 -1
- package/dist/tools/nextjs-component-readers.d.ts +101 -0
- package/dist/tools/nextjs-component-readers.d.ts.map +1 -0
- package/dist/tools/nextjs-component-readers.js +287 -0
- package/dist/tools/nextjs-component-readers.js.map +1 -0
- package/dist/tools/nextjs-component-tools.d.ts +8 -78
- package/dist/tools/nextjs-component-tools.d.ts.map +1 -1
- package/dist/tools/nextjs-component-tools.js +9 -257
- package/dist/tools/nextjs-component-tools.js.map +1 -1
- package/dist/tools/nextjs-framework-audit-tools.d.ts +24 -1
- package/dist/tools/nextjs-framework-audit-tools.d.ts.map +1 -1
- package/dist/tools/nextjs-framework-audit-tools.js +184 -1
- package/dist/tools/nextjs-framework-audit-tools.js.map +1 -1
- package/dist/tools/nextjs-route-readers.d.ts +81 -0
- package/dist/tools/nextjs-route-readers.d.ts.map +1 -0
- package/dist/tools/nextjs-route-readers.js +340 -0
- package/dist/tools/nextjs-route-readers.js.map +1 -0
- package/dist/tools/nextjs-route-tools.d.ts +7 -71
- package/dist/tools/nextjs-route-tools.d.ts.map +1 -1
- package/dist/tools/nextjs-route-tools.js +9 -327
- package/dist/tools/nextjs-route-tools.js.map +1 -1
- package/dist/tools/pattern-tools.d.ts.map +1 -1
- package/dist/tools/pattern-tools.js +92 -2
- package/dist/tools/pattern-tools.js.map +1 -1
- package/dist/tools/php-tools.d.ts +14 -5
- package/dist/tools/php-tools.d.ts.map +1 -1
- package/dist/tools/php-tools.js +166 -64
- package/dist/tools/php-tools.js.map +1 -1
- package/dist/tools/plan-turn-tools.d.ts +89 -0
- package/dist/tools/plan-turn-tools.d.ts.map +1 -0
- package/dist/tools/plan-turn-tools.js +508 -0
- package/dist/tools/plan-turn-tools.js.map +1 -0
- package/dist/tools/project-tools.d.ts +1 -1
- package/dist/tools/project-tools.js +1 -1
- package/dist/tools/project-tools.js.map +1 -1
- package/dist/tools/pydantic-models.d.ts +46 -0
- package/dist/tools/pydantic-models.d.ts.map +1 -0
- package/dist/tools/pydantic-models.js +249 -0
- package/dist/tools/pydantic-models.js.map +1 -0
- package/dist/tools/python-audit.d.ts +40 -0
- package/dist/tools/python-audit.d.ts.map +1 -0
- package/dist/tools/python-audit.js +244 -0
- package/dist/tools/python-audit.js.map +1 -0
- package/dist/tools/python-constants-tools.d.ts +44 -0
- package/dist/tools/python-constants-tools.d.ts.map +1 -0
- package/dist/tools/python-constants-tools.js +525 -0
- package/dist/tools/python-constants-tools.js.map +1 -0
- package/dist/tools/react-tools.d.ts +46 -1
- package/dist/tools/react-tools.d.ts.map +1 -1
- package/dist/tools/react-tools.js +126 -1
- package/dist/tools/react-tools.js.map +1 -1
- package/dist/tools/review-diff-tools.d.ts +5 -0
- package/dist/tools/review-diff-tools.d.ts.map +1 -1
- package/dist/tools/review-diff-tools.js +109 -3
- package/dist/tools/review-diff-tools.js.map +1 -1
- package/dist/tools/search-tools.d.ts +3 -2
- package/dist/tools/search-tools.d.ts.map +1 -1
- package/dist/tools/search-tools.js +16 -3
- package/dist/tools/search-tools.js.map +1 -1
- package/dist/tools/sql-tools.d.ts +40 -0
- package/dist/tools/sql-tools.d.ts.map +1 -1
- package/dist/tools/sql-tools.js +123 -0
- package/dist/tools/sql-tools.js.map +1 -1
- package/dist/tools/symbol-tools.d.ts.map +1 -1
- package/dist/tools/symbol-tools.js +7 -10
- package/dist/tools/symbol-tools.js.map +1 -1
- package/dist/tools/taint-tools.d.ts +43 -0
- package/dist/tools/taint-tools.d.ts.map +1 -0
- package/dist/tools/taint-tools.js +922 -0
- package/dist/tools/taint-tools.js.map +1 -0
- package/dist/utils/import-graph.d.ts +6 -0
- package/dist/utils/import-graph.d.ts.map +1 -1
- package/dist/utils/import-graph.js +43 -7
- package/dist/utils/import-graph.js.map +1 -1
- package/package.json +2 -2
- package/rules/codesift.md +51 -13
- package/rules/codesift.mdc +51 -13
- package/rules/codex.md +51 -13
- package/rules/gemini.md +51 -13
package/dist/register-tools.js
CHANGED
|
@@ -9,7 +9,7 @@ import { searchSymbols, searchText, semanticSearch } from "./tools/search-tools.
|
|
|
9
9
|
import { getFileTree, getFileOutline, getRepoOutline, suggestQueries } from "./tools/outline-tools.js";
|
|
10
10
|
import { getSymbol, getSymbols, findAndShow, findReferences, findReferencesBatch, findDeadCode, getContextBundle, formatRefsCompact, formatSymbolCompact, formatSymbolsCompact, formatBundleCompact } from "./tools/symbol-tools.js";
|
|
11
11
|
import { traceCallChain } from "./tools/graph-tools.js";
|
|
12
|
-
import { traceComponentTree, analyzeHooks, analyzeRenders, buildContextGraph, auditCompilerReadiness } from "./tools/react-tools.js";
|
|
12
|
+
import { traceComponentTree, analyzeHooks, analyzeRenders, buildContextGraph, auditCompilerReadiness, reactQuickstart } from "./tools/react-tools.js";
|
|
13
13
|
import { impactAnalysis } from "./tools/impact-tools.js";
|
|
14
14
|
import { traceRoute } from "./tools/route-tools.js";
|
|
15
15
|
import { detectCommunities } from "./tools/community-tools.js";
|
|
@@ -27,7 +27,7 @@ import { getUsageStats, formatUsageReport } from "./storage/usage-stats.js";
|
|
|
27
27
|
import { goToDefinition, getTypeInfo, renameSymbol, getCallHierarchy } from "./lsp/lsp-tools.js";
|
|
28
28
|
import { indexConversations, searchConversations, searchAllConversations, findConversationsForSymbol } from "./tools/conversation-tools.js";
|
|
29
29
|
import { scanSecrets } from "./tools/secret-tools.js";
|
|
30
|
-
import { resolvePhpNamespace,
|
|
30
|
+
import { resolvePhpNamespace, tracePhpEvent, findPhpViews, resolvePhpService, phpSecurityScan, phpProjectAudit, } from "./tools/php-tools.js";
|
|
31
31
|
import { consolidateMemories, readMemory } from "./tools/memory-tools.js";
|
|
32
32
|
import { createAnalysisPlan, writeScratchpad, readScratchpad, listScratchpad, updateStepStatus, getPlan, listPlans } from "./tools/coordinator-tools.js";
|
|
33
33
|
import { frequencyAnalysis } from "./tools/frequency-tools.js";
|
|
@@ -38,29 +38,30 @@ import { traceRoomSchema } from "./tools/room-tools.js";
|
|
|
38
38
|
import { extractKotlinSerializationContract } from "./tools/serialization-tools.js";
|
|
39
39
|
import { astroAnalyzeIslands, astroHydrationAudit } from "./tools/astro-islands.js";
|
|
40
40
|
import { astroRouteMap } from "./tools/astro-routes.js";
|
|
41
|
-
import {
|
|
41
|
+
import { astroActionsAudit } from "./tools/astro-actions.js";
|
|
42
|
+
import { astroAudit } from "./tools/astro-audit.js";
|
|
42
43
|
import { nextjsRouteMap } from "./tools/nextjs-route-tools.js";
|
|
43
44
|
import { nextjsMetadataAudit } from "./tools/nextjs-metadata-tools.js";
|
|
44
|
-
import { nextjsAuditServerActions } from "./tools/nextjs-security-tools.js";
|
|
45
|
-
import { nextjsApiContract } from "./tools/nextjs-api-contract-tools.js";
|
|
46
|
-
import { nextjsBoundaryAnalyzer } from "./tools/nextjs-boundary-tools.js";
|
|
47
|
-
import { nextjsLinkIntegrity } from "./tools/nextjs-link-tools.js";
|
|
48
|
-
import { nextjsDataFlow } from "./tools/nextjs-data-flow-tools.js";
|
|
49
|
-
import { nextjsMiddlewareCoverage } from "./tools/nextjs-middleware-coverage-tools.js";
|
|
50
45
|
import { frameworkAudit } from "./tools/nextjs-framework-audit-tools.js";
|
|
51
46
|
import { astroConfigAnalyze } from "./tools/astro-config.js";
|
|
47
|
+
import { astroContentCollections } from "./tools/astro-content-collections.js";
|
|
52
48
|
import { analyzeProject, getExtractorVersions } from "./tools/project-tools.js";
|
|
53
49
|
import { getModelGraph } from "./tools/model-tools.js";
|
|
54
50
|
import { getTestFixtures } from "./tools/pytest-tools.js";
|
|
55
51
|
import { findFrameworkWiring } from "./tools/wiring-tools.js";
|
|
56
52
|
import { runRuff } from "./tools/ruff-tools.js";
|
|
57
53
|
import { parsePyproject } from "./tools/pyproject-tools.js";
|
|
54
|
+
import { resolveConstantValue } from "./tools/python-constants-tools.js";
|
|
55
|
+
import { effectiveDjangoViewSecurity } from "./tools/django-view-security-tools.js";
|
|
58
56
|
import { findPythonCallers } from "./tools/python-callers.js";
|
|
57
|
+
import { taintTrace } from "./tools/taint-tools.js";
|
|
59
58
|
import { analyzeDjangoSettings } from "./tools/django-settings.js";
|
|
60
|
-
import { traceCeleryChain } from "./tools/celery-tools.js";
|
|
61
59
|
import { runMypy, runPyright } from "./tools/typecheck-tools.js";
|
|
62
60
|
import { analyzePythonDeps } from "./tools/python-deps-analyzer.js";
|
|
63
|
-
import {
|
|
61
|
+
import { pythonAudit } from "./tools/python-audit.js";
|
|
62
|
+
import { traceFastAPIDepends } from "./tools/fastapi-depends.js";
|
|
63
|
+
import { analyzeAsyncCorrectness } from "./tools/async-correctness.js";
|
|
64
|
+
import { getPydanticModels } from "./tools/pydantic-models.js";
|
|
64
65
|
import { reviewDiff } from "./tools/review-diff-tools.js";
|
|
65
66
|
import { auditScan } from "./tools/audit-tools.js";
|
|
66
67
|
import { indexStatus } from "./tools/status-tools.js";
|
|
@@ -68,17 +69,18 @@ import { auditAgentConfig } from "./tools/agent-config-tools.js";
|
|
|
68
69
|
import { testImpactAnalysis } from "./tools/test-impact-tools.js";
|
|
69
70
|
import { dependencyAudit } from "./tools/dependency-audit-tools.js";
|
|
70
71
|
import { migrationLint } from "./tools/migration-lint-tools.js";
|
|
72
|
+
import { planTurn, formatPlanTurnResult } from "./tools/plan-turn-tools.js";
|
|
73
|
+
import { astroMigrationCheck } from "./tools/astro-migration.js";
|
|
71
74
|
import { analyzePrismaSchema } from "./tools/prisma-schema-tools.js";
|
|
72
75
|
import { findPerfHotspots } from "./tools/perf-tools.js";
|
|
73
76
|
import { fanInFanOut, coChangeAnalysis } from "./tools/coupling-tools.js";
|
|
74
77
|
import { architectureSummary } from "./tools/architecture-tools.js";
|
|
75
|
-
import {
|
|
76
|
-
import { nestGraphQLMap, nestWebSocketMap, nestScheduleMap, nestTypeOrmMap, nestMicroserviceMap } from "./tools/nest-ext-tools.js";
|
|
78
|
+
import { nestAudit } from "./tools/nest-tools.js";
|
|
77
79
|
import { explainQuery } from "./tools/query-tools.js";
|
|
78
80
|
import { formatSnapshot, getContext, getSessionState } from "./storage/session-state.js";
|
|
79
81
|
import { formatComplexityCompact, formatComplexityCounts, formatClonesCompact, formatClonesCounts, formatHotspotsCompact, formatHotspotsCounts, formatTraceRouteCompact, formatTraceRouteCounts } from "./formatters-shortening.js";
|
|
80
|
-
import { formatSearchSymbols, formatFileTree, formatFileOutline, formatSearchPatterns, formatDeadCode, formatComplexity, formatClones, formatHotspots, formatRepoOutline, formatSuggestQueries, formatSecrets, formatConversations, formatRoles, formatAssembleContext, formatCommunities, formatCallTree, formatTraceRoute, formatKnowledgeMap, formatImpactAnalysis, formatDiffOutline, formatChangedSymbols, formatReviewDiff, formatPerfHotspots, formatFanInFanOut, formatCoChange, formatArchitectureSummary,
|
|
81
|
-
import { formatNextjsRouteMapCompact, formatNextjsRouteMapCounts, formatNextjsMetadataAuditCompact, formatNextjsMetadataAuditCounts, formatFrameworkAuditCompact, formatFrameworkAuditCounts
|
|
82
|
+
import { formatSearchSymbols, formatFileTree, formatFileOutline, formatSearchPatterns, formatDeadCode, formatComplexity, formatClones, formatHotspots, formatRepoOutline, formatSuggestQueries, formatSecrets, formatConversations, formatRoles, formatAssembleContext, formatCommunities, formatCallTree, formatTraceRoute, formatKnowledgeMap, formatImpactAnalysis, formatDiffOutline, formatChangedSymbols, formatReviewDiff, formatPerfHotspots, formatFanInFanOut, formatCoChange, formatArchitectureSummary, formatNextjsRouteMap, formatNextjsMetadataAudit, formatFrameworkAudit } from "./formatters.js";
|
|
83
|
+
import { formatNextjsRouteMapCompact, formatNextjsRouteMapCounts, formatNextjsMetadataAuditCompact, formatNextjsMetadataAuditCounts, formatFrameworkAuditCompact, formatFrameworkAuditCounts } from "./formatters-shortening.js";
|
|
82
84
|
const zFiniteNumber = z.number().finite();
|
|
83
85
|
/** Coerce string→number for numeric params while rejecting NaN/empty strings. */
|
|
84
86
|
export const zNum = () => z.union([
|
|
@@ -167,19 +169,7 @@ export function getToolHandle(name) {
|
|
|
167
169
|
/** Framework-specific tool bundles — auto-enabled when the framework is detected in an indexed repo */
|
|
168
170
|
const FRAMEWORK_TOOL_BUNDLES = {
|
|
169
171
|
nestjs: [
|
|
170
|
-
|
|
171
|
-
"nest_lifecycle_map",
|
|
172
|
-
"nest_module_graph",
|
|
173
|
-
"nest_di_graph",
|
|
174
|
-
"nest_guard_chain",
|
|
175
|
-
"nest_route_inventory",
|
|
176
|
-
// Wave 2
|
|
177
|
-
"nest_graphql_map",
|
|
178
|
-
"nest_websocket_map",
|
|
179
|
-
"nest_schedule_map",
|
|
180
|
-
"nest_typeorm_map",
|
|
181
|
-
"nest_microservice_map",
|
|
182
|
-
// nest_audit is already core — always visible
|
|
172
|
+
// All NestJS sub-tools absorbed into nest_audit
|
|
183
173
|
],
|
|
184
174
|
};
|
|
185
175
|
/** Track which framework bundles have been auto-enabled this session (avoid repeat work) */
|
|
@@ -217,14 +207,12 @@ const FRAMEWORK_TOOL_GROUPS = {
|
|
|
217
207
|
// PHP / Yii2 / Laravel — detected by composer.json
|
|
218
208
|
"composer.json": [
|
|
219
209
|
"resolve_php_namespace",
|
|
220
|
-
|
|
210
|
+
// analyze_activerecord, find_php_n_plus_one, find_php_god_model absorbed into php_project_audit
|
|
221
211
|
"trace_php_event",
|
|
222
212
|
"find_php_views",
|
|
223
213
|
"resolve_php_service",
|
|
224
214
|
"php_security_scan",
|
|
225
215
|
"php_project_audit",
|
|
226
|
-
"find_php_n_plus_one",
|
|
227
|
-
"find_php_god_model",
|
|
228
216
|
],
|
|
229
217
|
// Kotlin / Android / Gradle — detected by build.gradle.kts or settings.gradle.kts
|
|
230
218
|
"build.gradle.kts": [
|
|
@@ -277,6 +265,7 @@ const REACT_TOOLS = [
|
|
|
277
265
|
"analyze_renders",
|
|
278
266
|
"analyze_context_graph",
|
|
279
267
|
"audit_compiler_readiness",
|
|
268
|
+
"react_quickstart",
|
|
280
269
|
];
|
|
281
270
|
/**
|
|
282
271
|
* Hono-specific tools — auto-enabled when a Hono project is detected.
|
|
@@ -287,20 +276,6 @@ const REACT_TOOLS = [
|
|
|
287
276
|
* Detection: package.json with "hono" OR "@hono/zod-openapi" dep.
|
|
288
277
|
* Content-based (not filename), so lives outside FRAMEWORK_TOOL_GROUPS.
|
|
289
278
|
*/
|
|
290
|
-
/**
|
|
291
|
-
* Next.js Tier-1 tools — auto-enabled when 'next' is in package.json deps.
|
|
292
|
-
* These are the 7 hidden tools; the 3 core tools (nextjs_route_map,
|
|
293
|
-
* nextjs_metadata_audit, framework_audit) are always visible.
|
|
294
|
-
*/
|
|
295
|
-
const NEXTJS_TOOLS = [
|
|
296
|
-
"analyze_nextjs_components",
|
|
297
|
-
"nextjs_audit_server_actions",
|
|
298
|
-
"nextjs_api_contract",
|
|
299
|
-
"nextjs_boundary_analyzer",
|
|
300
|
-
"nextjs_link_integrity",
|
|
301
|
-
"nextjs_data_flow",
|
|
302
|
-
"nextjs_middleware_coverage",
|
|
303
|
-
];
|
|
304
279
|
const HONO_TOOLS = [
|
|
305
280
|
"trace_context_flow",
|
|
306
281
|
"extract_api_contract",
|
|
@@ -308,10 +283,8 @@ const HONO_TOOLS = [
|
|
|
308
283
|
"audit_hono_security",
|
|
309
284
|
"visualize_hono_routes",
|
|
310
285
|
// Phase 2 additions — closes blog-API demo gaps + GitHub issues #3587/#4121/#4270
|
|
311
|
-
"trace_conditional_middleware",
|
|
312
286
|
"analyze_inline_handler",
|
|
313
287
|
"extract_response_types",
|
|
314
|
-
"detect_middleware_env_regression",
|
|
315
288
|
"detect_hono_modules",
|
|
316
289
|
"find_dead_hono_routes",
|
|
317
290
|
];
|
|
@@ -351,11 +324,6 @@ export async function detectAutoLoadTools(cwd) {
|
|
|
351
324
|
if (hasHono) {
|
|
352
325
|
toEnable.push(...HONO_TOOLS);
|
|
353
326
|
}
|
|
354
|
-
// Next.js: auto-enable hidden tools when next dep is present
|
|
355
|
-
const hasNext = !!allDeps["next"];
|
|
356
|
-
if (hasNext) {
|
|
357
|
-
toEnable.push(...NEXTJS_TOOLS);
|
|
358
|
-
}
|
|
359
327
|
}
|
|
360
328
|
catch { /* malformed package.json */ }
|
|
361
329
|
}
|
|
@@ -504,15 +472,20 @@ export const CORE_TOOL_NAMES = new Set([
|
|
|
504
472
|
"index_folder", // repo onboarding
|
|
505
473
|
"discover_tools", // meta: discovers remaining hidden tools
|
|
506
474
|
"describe_tools", // meta: full schema for hidden tools
|
|
475
|
+
"plan_turn", // meta: route query to best tools/symbols/files
|
|
507
476
|
"get_session_snapshot", // session: compaction survival
|
|
508
477
|
"analyze_project", // project profile
|
|
509
478
|
"get_extractor_versions", // cache invalidation
|
|
510
479
|
"index_status", // meta: check if repo is indexed
|
|
511
|
-
// --- Astro tools ---
|
|
480
|
+
// --- Astro tools (7 core) ---
|
|
512
481
|
"astro_analyze_islands",
|
|
513
|
-
|
|
482
|
+
// astro_hydration_audit: discoverable — use astro_audit for full check or call directly
|
|
514
483
|
"astro_route_map",
|
|
515
484
|
"astro_config_analyze",
|
|
485
|
+
"astro_actions_audit",
|
|
486
|
+
"astro_migration_check",
|
|
487
|
+
"astro_content_collections",
|
|
488
|
+
"astro_audit",
|
|
516
489
|
// --- Hono tools (Task 23) ---
|
|
517
490
|
"trace_middleware_chain", // core: top Hono pain point (Discussion #4255)
|
|
518
491
|
"analyze_hono_app", // core: meta-tool, first call for any Hono project
|
|
@@ -605,12 +578,13 @@ const TOOL_DEFINITIONS = [
|
|
|
605
578
|
category: "search",
|
|
606
579
|
searchHint: "search find symbols functions classes types methods by name signature",
|
|
607
580
|
outputSchema: OutputSchemas.searchResults,
|
|
608
|
-
description: "Search symbols by name/signature. detail_level: compact (~15 tok), standard (default), full.",
|
|
581
|
+
description: "Search symbols by name/signature. Supports kind, file, and decorator filters. detail_level: compact (~15 tok), standard (default), full.",
|
|
609
582
|
schema: {
|
|
610
583
|
repo: z.string().optional().describe("Repository identifier (default: auto-detected from CWD)"),
|
|
611
584
|
query: z.string().describe("Search query string"),
|
|
612
585
|
kind: z.string().optional().describe("Filter by symbol kind (function, class, etc.)"),
|
|
613
586
|
file_pattern: z.string().optional().describe("Glob pattern to filter files"),
|
|
587
|
+
decorator: z.string().optional().describe("Filter by decorator metadata, e.g. login_required, @dataclass, router.get"),
|
|
614
588
|
include_source: zBool().describe("Include full source code of each symbol"),
|
|
615
589
|
top_k: zNum().describe("Maximum number of results to return (default 50)"),
|
|
616
590
|
source_chars: zNum().describe("Truncate each symbol's source to N characters (reduces output size)"),
|
|
@@ -622,6 +596,7 @@ const TOOL_DEFINITIONS = [
|
|
|
622
596
|
const results = await searchSymbols(args.repo, args.query, {
|
|
623
597
|
kind: args.kind,
|
|
624
598
|
file_pattern: args.file_pattern,
|
|
599
|
+
decorator: args.decorator,
|
|
625
600
|
include_source: args.include_source,
|
|
626
601
|
top_k: args.top_k,
|
|
627
602
|
source_chars: args.source_chars,
|
|
@@ -1039,6 +1014,19 @@ const TOOL_DEFINITIONS = [
|
|
|
1039
1014
|
return JSON.stringify(result, null, 2);
|
|
1040
1015
|
},
|
|
1041
1016
|
},
|
|
1017
|
+
{
|
|
1018
|
+
name: "react_quickstart",
|
|
1019
|
+
category: "analysis",
|
|
1020
|
+
searchHint: "react onboarding day-1 overview stack inventory components hooks critical issues",
|
|
1021
|
+
description: "Day-1 onboarding composite for React projects. Single call returns: component/hook inventory, stack detection (state mgmt, routing, UI lib, form lib, build tool), critical pattern scan (XSS, Rule of Hooks, memory leaks), top hook usage, and suggested next queries. Replaces 5-6 manual tool calls. First tool to run on an unfamiliar React codebase.",
|
|
1022
|
+
schema: {
|
|
1023
|
+
repo: z.string().optional().describe("Repository identifier (default: auto-detected from CWD)"),
|
|
1024
|
+
},
|
|
1025
|
+
handler: async (args) => {
|
|
1026
|
+
const result = await reactQuickstart(args.repo);
|
|
1027
|
+
return JSON.stringify(result, null, 2);
|
|
1028
|
+
},
|
|
1029
|
+
},
|
|
1042
1030
|
{
|
|
1043
1031
|
name: "trace_route",
|
|
1044
1032
|
category: "graph",
|
|
@@ -1886,6 +1874,87 @@ const TOOL_DEFINITIONS = [
|
|
|
1886
1874
|
schema: { repo: z.string().optional().describe("Repository identifier (default: auto-detected from CWD)") },
|
|
1887
1875
|
handler: async (args) => { return await parsePyproject(args.repo); },
|
|
1888
1876
|
},
|
|
1877
|
+
{
|
|
1878
|
+
name: "resolve_constant_value",
|
|
1879
|
+
category: "analysis",
|
|
1880
|
+
searchHint: "python typescript nestjs resolve constant value literal alias import default parameter propagation",
|
|
1881
|
+
description: "Resolve Python or TypeScript constants and function default values through simple aliases and import chains. Returns literals or explicit unresolved reasons.",
|
|
1882
|
+
schema: {
|
|
1883
|
+
repo: z.string().optional().describe("Repository identifier (default: auto-detected from CWD)"),
|
|
1884
|
+
symbol_name: z.string().describe("Constant, function, or method name to resolve"),
|
|
1885
|
+
file_pattern: z.string().optional().describe("Filter candidate symbols by file path substring"),
|
|
1886
|
+
language: z.enum(["python", "typescript"]).optional().describe("Force resolver language instead of auto-inference"),
|
|
1887
|
+
max_depth: zFiniteNumber.optional().describe("Maximum alias/import resolution depth (default: 8)"),
|
|
1888
|
+
},
|
|
1889
|
+
handler: async (args) => {
|
|
1890
|
+
const opts = {};
|
|
1891
|
+
if (args.file_pattern != null)
|
|
1892
|
+
opts.file_pattern = args.file_pattern;
|
|
1893
|
+
if (args.language != null)
|
|
1894
|
+
opts.language = args.language;
|
|
1895
|
+
if (args.max_depth != null)
|
|
1896
|
+
opts.max_depth = args.max_depth;
|
|
1897
|
+
return await resolveConstantValue(args.repo, args.symbol_name, opts);
|
|
1898
|
+
},
|
|
1899
|
+
},
|
|
1900
|
+
{
|
|
1901
|
+
name: "effective_django_view_security",
|
|
1902
|
+
category: "security",
|
|
1903
|
+
requiresLanguage: "python",
|
|
1904
|
+
searchHint: "python django view auth csrf login_required middleware mixin route security posture",
|
|
1905
|
+
description: "Assess effective Django view security from decorators, mixins, settings middleware, and optional route resolution.",
|
|
1906
|
+
schema: {
|
|
1907
|
+
repo: z.string().optional().describe("Repository identifier (default: auto-detected from CWD)"),
|
|
1908
|
+
path: z.string().optional().describe("Django route path to resolve first, e.g. /settings/"),
|
|
1909
|
+
symbol_name: z.string().optional().describe("View function/class/method name when you already know the symbol"),
|
|
1910
|
+
file_pattern: z.string().optional().describe("Filter candidate symbols by file path substring"),
|
|
1911
|
+
settings_file: z.string().optional().describe("Explicit Django settings file path (auto-detects if omitted)"),
|
|
1912
|
+
},
|
|
1913
|
+
handler: async (args) => {
|
|
1914
|
+
const opts = {};
|
|
1915
|
+
if (args.path != null)
|
|
1916
|
+
opts.path = args.path;
|
|
1917
|
+
if (args.symbol_name != null)
|
|
1918
|
+
opts.symbol_name = args.symbol_name;
|
|
1919
|
+
if (args.file_pattern != null)
|
|
1920
|
+
opts.file_pattern = args.file_pattern;
|
|
1921
|
+
if (args.settings_file != null)
|
|
1922
|
+
opts.settings_file = args.settings_file;
|
|
1923
|
+
return await effectiveDjangoViewSecurity(args.repo, opts);
|
|
1924
|
+
},
|
|
1925
|
+
},
|
|
1926
|
+
{
|
|
1927
|
+
name: "taint_trace",
|
|
1928
|
+
category: "security",
|
|
1929
|
+
requiresLanguage: "python",
|
|
1930
|
+
searchHint: "python django taint data flow source sink request get post redirect mark_safe cursor execute subprocess session trace",
|
|
1931
|
+
description: "Trace Python/Django user-controlled data from request sources to security sinks like redirect, mark_safe, cursor.execute, subprocess, requests/httpx, open, or session writes.",
|
|
1932
|
+
schema: {
|
|
1933
|
+
repo: z.string().optional().describe("Repository identifier (default: auto-detected from CWD)"),
|
|
1934
|
+
framework: z.enum(["python-django"]).optional().describe("Currently only python-django is implemented"),
|
|
1935
|
+
file_pattern: z.string().optional().describe("Restrict analysis to matching Python files"),
|
|
1936
|
+
source_patterns: z.array(z.string()).optional().describe("Optional source pattern allowlist (defaults to request.* presets)"),
|
|
1937
|
+
sink_patterns: z.array(z.string()).optional().describe("Optional sink pattern allowlist (defaults to built-in security sinks)"),
|
|
1938
|
+
max_depth: zFiniteNumber.optional().describe("Maximum interprocedural helper depth (default: 4)"),
|
|
1939
|
+
max_traces: zFiniteNumber.optional().describe("Maximum traces to return before truncation (default: 50)"),
|
|
1940
|
+
},
|
|
1941
|
+
handler: async (args) => {
|
|
1942
|
+
const opts = {};
|
|
1943
|
+
if (args.framework != null)
|
|
1944
|
+
opts.framework = args.framework;
|
|
1945
|
+
if (args.file_pattern != null)
|
|
1946
|
+
opts.file_pattern = args.file_pattern;
|
|
1947
|
+
if (args.source_patterns != null)
|
|
1948
|
+
opts.source_patterns = args.source_patterns;
|
|
1949
|
+
if (args.sink_patterns != null)
|
|
1950
|
+
opts.sink_patterns = args.sink_patterns;
|
|
1951
|
+
if (args.max_depth != null)
|
|
1952
|
+
opts.max_depth = args.max_depth;
|
|
1953
|
+
if (args.max_traces != null)
|
|
1954
|
+
opts.max_traces = args.max_traces;
|
|
1955
|
+
return await taintTrace(args.repo, opts);
|
|
1956
|
+
},
|
|
1957
|
+
},
|
|
1889
1958
|
{
|
|
1890
1959
|
name: "find_python_callers",
|
|
1891
1960
|
category: "analysis",
|
|
@@ -1927,26 +1996,6 @@ const TOOL_DEFINITIONS = [
|
|
|
1927
1996
|
return await analyzeDjangoSettings(args.repo, opts);
|
|
1928
1997
|
},
|
|
1929
1998
|
},
|
|
1930
|
-
{
|
|
1931
|
-
name: "trace_celery_chain",
|
|
1932
|
-
category: "analysis",
|
|
1933
|
-
requiresLanguage: "python",
|
|
1934
|
-
searchHint: "python celery task shared_task delay apply_async chain group chord canvas retry orphan queue",
|
|
1935
|
-
description: "Celery task tracing: tasks with policies (bind, retries, queue), .delay() call sites, canvas operators (chain/group/chord), orphan tasks.",
|
|
1936
|
-
schema: {
|
|
1937
|
-
repo: z.string().optional().describe("Repository identifier (default: auto-detected from CWD)"),
|
|
1938
|
-
file_pattern: z.string().optional().describe("Filter by file path substring"),
|
|
1939
|
-
task_name: z.string().optional().describe("Focus on a specific task by name"),
|
|
1940
|
-
},
|
|
1941
|
-
handler: async (args) => {
|
|
1942
|
-
const opts = {};
|
|
1943
|
-
if (args.file_pattern != null)
|
|
1944
|
-
opts.file_pattern = args.file_pattern;
|
|
1945
|
-
if (args.task_name != null)
|
|
1946
|
-
opts.task_name = args.task_name;
|
|
1947
|
-
return await traceCeleryChain(args.repo, opts);
|
|
1948
|
-
},
|
|
1949
|
-
},
|
|
1950
1999
|
{
|
|
1951
2000
|
name: "run_mypy",
|
|
1952
2001
|
category: "analysis",
|
|
@@ -2014,58 +2063,104 @@ const TOOL_DEFINITIONS = [
|
|
|
2014
2063
|
},
|
|
2015
2064
|
},
|
|
2016
2065
|
{
|
|
2017
|
-
name: "
|
|
2066
|
+
name: "trace_fastapi_depends",
|
|
2018
2067
|
category: "analysis",
|
|
2019
2068
|
requiresLanguage: "python",
|
|
2020
|
-
searchHint: "python
|
|
2021
|
-
description: "
|
|
2069
|
+
searchHint: "python fastapi depends dependency injection security scopes oauth2 authentication auth endpoint",
|
|
2070
|
+
description: "Trace FastAPI Depends()/Security() dependency injection chains recursively from route handlers. Detects yield deps (resource cleanup), Security() with scopes, shared deps across endpoints, endpoints without auth.",
|
|
2022
2071
|
schema: {
|
|
2023
2072
|
repo: z.string().optional().describe("Repository identifier (default: auto-detected from CWD)"),
|
|
2024
2073
|
file_pattern: z.string().optional().describe("Filter by file path substring"),
|
|
2025
|
-
|
|
2074
|
+
endpoint: z.string().optional().describe("Focus on a specific endpoint function name"),
|
|
2075
|
+
max_depth: zFiniteNumber.optional().describe("Max dependency tree depth (default: 5)"),
|
|
2026
2076
|
},
|
|
2027
2077
|
handler: async (args) => {
|
|
2028
2078
|
const opts = {};
|
|
2029
2079
|
if (args.file_pattern != null)
|
|
2030
2080
|
opts.file_pattern = args.file_pattern;
|
|
2031
|
-
if (args.
|
|
2032
|
-
opts.
|
|
2033
|
-
|
|
2081
|
+
if (args.endpoint != null)
|
|
2082
|
+
opts.endpoint = args.endpoint;
|
|
2083
|
+
if (args.max_depth != null)
|
|
2084
|
+
opts.max_depth = args.max_depth;
|
|
2085
|
+
return await traceFastAPIDepends(args.repo, opts);
|
|
2034
2086
|
},
|
|
2035
2087
|
},
|
|
2036
|
-
// --- PHP / Yii2 tools (all discoverable via discover_tools(query="php")) ---
|
|
2037
2088
|
{
|
|
2038
|
-
name: "
|
|
2089
|
+
name: "analyze_async_correctness",
|
|
2039
2090
|
category: "analysis",
|
|
2040
|
-
requiresLanguage: "
|
|
2041
|
-
searchHint: "
|
|
2042
|
-
description: "
|
|
2091
|
+
requiresLanguage: "python",
|
|
2092
|
+
searchHint: "python async await asyncio blocking sync requests sleep subprocess django sqlalchemy ORM coroutine fastapi",
|
|
2093
|
+
description: "Detect 8 asyncio pitfalls in async def: blocking requests/sleep/IO/subprocess, sync SQLAlchemy/Django ORM in async views, async without await, asyncio.create_task without ref storage.",
|
|
2043
2094
|
schema: {
|
|
2044
2095
|
repo: z.string().optional().describe("Repository identifier (default: auto-detected from CWD)"),
|
|
2045
|
-
|
|
2096
|
+
file_pattern: z.string().optional().describe("Filter by file path substring"),
|
|
2097
|
+
rules: z.array(z.string()).optional().describe("Subset of rules to run"),
|
|
2098
|
+
max_results: zFiniteNumber.optional().describe("Max findings (default: 200)"),
|
|
2046
2099
|
},
|
|
2047
2100
|
handler: async (args) => {
|
|
2048
|
-
|
|
2101
|
+
const opts = {};
|
|
2102
|
+
if (args.file_pattern != null)
|
|
2103
|
+
opts.file_pattern = args.file_pattern;
|
|
2104
|
+
if (args.rules != null)
|
|
2105
|
+
opts.rules = args.rules;
|
|
2106
|
+
if (args.max_results != null)
|
|
2107
|
+
opts.max_results = args.max_results;
|
|
2108
|
+
return await analyzeAsyncCorrectness(args.repo, opts);
|
|
2049
2109
|
},
|
|
2050
2110
|
},
|
|
2051
2111
|
{
|
|
2052
|
-
name: "
|
|
2112
|
+
name: "get_pydantic_models",
|
|
2053
2113
|
category: "analysis",
|
|
2054
|
-
requiresLanguage: "
|
|
2055
|
-
searchHint: "
|
|
2056
|
-
description: "Extract
|
|
2114
|
+
requiresLanguage: "python",
|
|
2115
|
+
searchHint: "python pydantic basemodel fastapi schema request response contract validator field constraint type classdiagram",
|
|
2116
|
+
description: "Extract Pydantic models: fields with types, validators, Field() constraints, model_config, cross-model references (list[X], Optional[Y]), inheritance. JSON or mermaid classDiagram.",
|
|
2057
2117
|
schema: {
|
|
2058
2118
|
repo: z.string().optional().describe("Repository identifier (default: auto-detected from CWD)"),
|
|
2059
|
-
model_name: z.string().optional().describe("Filter by specific model class name"),
|
|
2060
2119
|
file_pattern: z.string().optional().describe("Filter by file path substring"),
|
|
2120
|
+
output_format: z.enum(["json", "mermaid"]).optional().describe("Output as structured JSON or mermaid classDiagram"),
|
|
2061
2121
|
},
|
|
2062
2122
|
handler: async (args) => {
|
|
2063
2123
|
const opts = {};
|
|
2064
|
-
if (
|
|
2065
|
-
opts.model_name = args.model_name;
|
|
2066
|
-
if (typeof args.file_pattern === "string")
|
|
2124
|
+
if (args.file_pattern != null)
|
|
2067
2125
|
opts.file_pattern = args.file_pattern;
|
|
2068
|
-
|
|
2126
|
+
if (args.output_format != null)
|
|
2127
|
+
opts.output_format = args.output_format;
|
|
2128
|
+
return await getPydanticModels(args.repo, opts);
|
|
2129
|
+
},
|
|
2130
|
+
},
|
|
2131
|
+
{
|
|
2132
|
+
name: "python_audit",
|
|
2133
|
+
category: "analysis",
|
|
2134
|
+
requiresLanguage: "python",
|
|
2135
|
+
searchHint: "python audit health score compound project review django security circular patterns celery dependencies dead code task shared_task delay apply_async chain group chord canvas retry orphan queue import cycle ImportError TYPE_CHECKING DFS",
|
|
2136
|
+
description: "Compound Python project health audit: circular imports + Django settings + anti-patterns (17) + framework wiring + Celery orphans + pytest fixtures + deps + dead code. Runs in parallel, returns unified health score (0-100) + severity counts + prioritized top_risks list.",
|
|
2137
|
+
schema: {
|
|
2138
|
+
repo: z.string().optional().describe("Repository identifier (default: auto-detected from CWD)"),
|
|
2139
|
+
file_pattern: z.string().optional().describe("Filter by file path substring"),
|
|
2140
|
+
checks: z.array(z.string()).optional().describe("Subset of checks: circular_imports, django_settings, anti_patterns, framework_wiring, celery, pytest_fixtures, dependencies, dead_code"),
|
|
2141
|
+
},
|
|
2142
|
+
handler: async (args) => {
|
|
2143
|
+
const opts = {};
|
|
2144
|
+
if (args.file_pattern != null)
|
|
2145
|
+
opts.file_pattern = args.file_pattern;
|
|
2146
|
+
if (args.checks != null)
|
|
2147
|
+
opts.checks = args.checks;
|
|
2148
|
+
return await pythonAudit(args.repo, opts);
|
|
2149
|
+
},
|
|
2150
|
+
},
|
|
2151
|
+
// --- PHP / Yii2 tools (all discoverable via discover_tools(query="php")) ---
|
|
2152
|
+
{
|
|
2153
|
+
name: "resolve_php_namespace",
|
|
2154
|
+
category: "analysis",
|
|
2155
|
+
requiresLanguage: "php",
|
|
2156
|
+
searchHint: "php namespace resolve PSR-4 autoload composer class file path yii2 laravel symfony",
|
|
2157
|
+
description: "Resolve a PHP FQCN to file path via composer.json PSR-4 autoload mapping.",
|
|
2158
|
+
schema: {
|
|
2159
|
+
repo: z.string().optional().describe("Repository identifier (default: auto-detected from CWD)"),
|
|
2160
|
+
class_name: z.string().describe("Fully-qualified class name, e.g. 'App\\\\Models\\\\User'"),
|
|
2161
|
+
},
|
|
2162
|
+
handler: async (args) => {
|
|
2163
|
+
return await resolvePhpNamespace(args.repo, args.class_name);
|
|
2069
2164
|
},
|
|
2070
2165
|
},
|
|
2071
2166
|
{
|
|
@@ -2143,62 +2238,23 @@ const TOOL_DEFINITIONS = [
|
|
|
2143
2238
|
name: "php_project_audit",
|
|
2144
2239
|
category: "analysis",
|
|
2145
2240
|
requiresLanguage: "php",
|
|
2146
|
-
searchHint: "php project audit health quality technical debt code review comprehensive yii2 laravel",
|
|
2147
|
-
description: "Compound PHP project audit: security scan + ActiveRecord analysis + health score. Runs checks in parallel.",
|
|
2241
|
+
searchHint: "php project audit health quality technical debt code review comprehensive yii2 laravel activerecord eloquent model schema relations rules behaviors table orm n+1 query foreach eager loading relation god class anti-pattern too many methods oversized",
|
|
2242
|
+
description: "Compound PHP project audit: security scan + ActiveRecord analysis + N+1 detection + god model detection + health score. Runs checks in parallel.",
|
|
2148
2243
|
schema: {
|
|
2149
2244
|
repo: z.string().optional().describe("Repository identifier (default: auto-detected from CWD)"),
|
|
2150
2245
|
file_pattern: z.string().optional().describe("Glob pattern to filter analyzed files"),
|
|
2246
|
+
checks: z.string().optional().describe("Comma-separated checks: n_plus_one, god_model, activerecord, security, events, views, services, namespace. Default: all"),
|
|
2151
2247
|
},
|
|
2152
2248
|
handler: async (args) => {
|
|
2153
2249
|
const opts = {};
|
|
2154
2250
|
if (typeof args.file_pattern === "string")
|
|
2155
2251
|
opts.file_pattern = args.file_pattern;
|
|
2252
|
+
if (typeof args.checks === "string" && args.checks.trim()) {
|
|
2253
|
+
opts.checks = args.checks.split(",").map((c) => c.trim()).filter(Boolean);
|
|
2254
|
+
}
|
|
2156
2255
|
return await phpProjectAudit(args.repo, opts);
|
|
2157
2256
|
},
|
|
2158
2257
|
},
|
|
2159
|
-
{
|
|
2160
|
-
name: "find_php_n_plus_one",
|
|
2161
|
-
category: "analysis",
|
|
2162
|
-
requiresLanguage: "php",
|
|
2163
|
-
searchHint: "php n+1 query foreach activerecord with eager loading yii2 eloquent relation",
|
|
2164
|
-
description: "Detect N+1 query patterns in PHP: foreach loops accessing ActiveRecord relations without eager loading via ->with(). Yii2/Laravel aware.",
|
|
2165
|
-
schema: {
|
|
2166
|
-
repo: z.string().optional().describe("Repository identifier (default: auto-detected from CWD)"),
|
|
2167
|
-
limit: z.number().optional().describe("Max findings to return (default: 100)"),
|
|
2168
|
-
file_pattern: z.string().optional().describe("Substring filter on file paths (e.g. 'controllers/')"),
|
|
2169
|
-
},
|
|
2170
|
-
handler: async (args) => {
|
|
2171
|
-
const opts = {};
|
|
2172
|
-
if (typeof args.limit === "number")
|
|
2173
|
-
opts.limit = args.limit;
|
|
2174
|
-
if (typeof args.file_pattern === "string")
|
|
2175
|
-
opts.file_pattern = args.file_pattern;
|
|
2176
|
-
return await findPhpNPlusOne(args.repo, opts);
|
|
2177
|
-
},
|
|
2178
|
-
},
|
|
2179
|
-
{
|
|
2180
|
-
name: "find_php_god_model",
|
|
2181
|
-
category: "analysis",
|
|
2182
|
-
requiresLanguage: "php",
|
|
2183
|
-
searchHint: "php god model god class anti-pattern too many methods relations oversized yii2 activerecord",
|
|
2184
|
-
description: "Find oversized ActiveRecord models (god classes) with configurable thresholds for method, relation, and line counts. Reports reasons per model.",
|
|
2185
|
-
schema: {
|
|
2186
|
-
repo: z.string().optional().describe("Repository identifier (default: auto-detected from CWD)"),
|
|
2187
|
-
min_methods: z.number().optional().describe("Method count threshold (default: 50)"),
|
|
2188
|
-
min_relations: z.number().optional().describe("Relation count threshold (default: 15)"),
|
|
2189
|
-
min_lines: z.number().optional().describe("Line count threshold (default: 500)"),
|
|
2190
|
-
},
|
|
2191
|
-
handler: async (args) => {
|
|
2192
|
-
const opts = {};
|
|
2193
|
-
if (typeof args.min_methods === "number")
|
|
2194
|
-
opts.min_methods = args.min_methods;
|
|
2195
|
-
if (typeof args.min_relations === "number")
|
|
2196
|
-
opts.min_relations = args.min_relations;
|
|
2197
|
-
if (typeof args.min_lines === "number")
|
|
2198
|
-
opts.min_lines = args.min_lines;
|
|
2199
|
-
return await findPhpGodModel(args.repo, opts);
|
|
2200
|
-
},
|
|
2201
|
-
},
|
|
2202
2258
|
// --- Memory consolidation ---
|
|
2203
2259
|
{
|
|
2204
2260
|
name: "consolidate_memories",
|
|
@@ -2635,66 +2691,11 @@ const TOOL_DEFINITIONS = [
|
|
|
2635
2691
|
return parts.join("\n");
|
|
2636
2692
|
},
|
|
2637
2693
|
},
|
|
2638
|
-
// --- NestJS analysis tools ---
|
|
2639
|
-
{
|
|
2640
|
-
name: "nest_lifecycle_map",
|
|
2641
|
-
category: "nestjs",
|
|
2642
|
-
searchHint: "nestjs lifecycle hook onModuleInit onApplicationBootstrap shutdown",
|
|
2643
|
-
description: "Map NestJS lifecycle hooks across the codebase — onModuleInit, onModuleDestroy, etc.",
|
|
2644
|
-
schema: { repo: z.string().optional().describe("Repository identifier (default: auto-detected from CWD)") },
|
|
2645
|
-
handler: async (args) => nestLifecycleMap(args.repo ?? ""),
|
|
2646
|
-
},
|
|
2647
|
-
{
|
|
2648
|
-
name: "nest_module_graph",
|
|
2649
|
-
category: "nestjs",
|
|
2650
|
-
searchHint: "nestjs module dependency graph circular import boundary",
|
|
2651
|
-
description: "Build NestJS module dependency graph with circular dependency detection and boundary analysis.",
|
|
2652
|
-
schema: {
|
|
2653
|
-
repo: z.string().optional().describe("Repository identifier (default: auto-detected from CWD)"),
|
|
2654
|
-
max_modules: z.number().optional().describe("Max modules to process (default: 200)"),
|
|
2655
|
-
output_format: z.enum(["json", "mermaid"]).optional().describe("Output format: json (default) or mermaid"),
|
|
2656
|
-
},
|
|
2657
|
-
handler: async (args) => nestModuleGraph(args.repo ?? "", args),
|
|
2658
|
-
},
|
|
2659
|
-
{
|
|
2660
|
-
name: "nest_di_graph",
|
|
2661
|
-
category: "nestjs",
|
|
2662
|
-
searchHint: "nestjs dependency injection provider constructor inject graph cycle",
|
|
2663
|
-
description: "Build NestJS provider DI graph with constructor injection tracking and cycle detection.",
|
|
2664
|
-
schema: {
|
|
2665
|
-
repo: z.string().optional().describe("Repository identifier (default: auto-detected from CWD)"),
|
|
2666
|
-
max_nodes: z.number().optional().describe("Max provider nodes (default: 200)"),
|
|
2667
|
-
focus: z.string().optional().describe("Path substring to filter files"),
|
|
2668
|
-
},
|
|
2669
|
-
handler: async (args) => nestDIGraph(args.repo ?? "", args),
|
|
2670
|
-
},
|
|
2671
|
-
{
|
|
2672
|
-
name: "nest_guard_chain",
|
|
2673
|
-
category: "nestjs",
|
|
2674
|
-
searchHint: "nestjs guard interceptor pipe filter middleware chain route security",
|
|
2675
|
-
description: "Show guard/interceptor/pipe/filter execution chain per NestJS route (global → controller → method).",
|
|
2676
|
-
schema: {
|
|
2677
|
-
repo: z.string().optional().describe("Repository identifier (default: auto-detected from CWD)"),
|
|
2678
|
-
path: z.string().optional().describe("Filter to specific route path"),
|
|
2679
|
-
max_routes: z.number().optional().describe("Max routes (default: 300)"),
|
|
2680
|
-
},
|
|
2681
|
-
handler: async (args) => nestGuardChain(args.repo ?? "", args),
|
|
2682
|
-
},
|
|
2683
|
-
{
|
|
2684
|
-
name: "nest_route_inventory",
|
|
2685
|
-
category: "nestjs",
|
|
2686
|
-
searchHint: "nestjs route endpoint api map inventory list all guards params",
|
|
2687
|
-
description: "Full NestJS route map with guards, params, and protected/unprotected stats.",
|
|
2688
|
-
schema: {
|
|
2689
|
-
repo: z.string().optional().describe("Repository identifier (default: auto-detected from CWD)"),
|
|
2690
|
-
max_routes: z.number().optional().describe("Max routes (default: 500)"),
|
|
2691
|
-
},
|
|
2692
|
-
handler: async (args) => nestRouteInventory(args.repo ?? "", args),
|
|
2693
|
-
},
|
|
2694
|
+
// --- NestJS analysis tools (sub-tools absorbed into nest_audit) ---
|
|
2694
2695
|
{
|
|
2695
2696
|
name: "nest_audit",
|
|
2696
2697
|
category: "nestjs",
|
|
2697
|
-
searchHint: "nestjs audit analysis comprehensive module di guard route lifecycle pattern graphql websocket schedule typeorm microservice",
|
|
2698
|
+
searchHint: "nestjs audit analysis comprehensive module di guard route lifecycle pattern graphql websocket schedule typeorm microservice hook onModuleInit onApplicationBootstrap shutdown dependency graph circular import boundary injection provider constructor inject cycle interceptor pipe filter middleware chain security endpoint api map inventory list all params resolver query mutation subscription apollo gateway subscribemessage socketio realtime event cron interval timeout scheduled job task onevent listener entity relation onetomany manytoone database schema messagepattern eventpattern kafka rabbitmq nats transport request pipeline handler execution flow visualization bull bullmq queue processor process background worker scope transient singleton performance escalation swagger openapi documentation apiproperty apioperation apiresponse contract extract",
|
|
2698
2699
|
description: "One-call NestJS architecture audit: modules, DI, guards, routes, lifecycle, patterns, GraphQL, WebSocket, schedule, TypeORM, microservices.",
|
|
2699
2700
|
schema: {
|
|
2700
2701
|
repo: z.string().optional().describe("Repository identifier (default: auto-detected from CWD)"),
|
|
@@ -2705,63 +2706,6 @@ const TOOL_DEFINITIONS = [
|
|
|
2705
2706
|
return nestAudit(args.repo ?? "", checks ? { checks } : undefined);
|
|
2706
2707
|
},
|
|
2707
2708
|
},
|
|
2708
|
-
// --- Wave 2 NestJS tools (nest-ext-tools.ts) ---
|
|
2709
|
-
{
|
|
2710
|
-
name: "nest_graphql_map",
|
|
2711
|
-
category: "nestjs",
|
|
2712
|
-
searchHint: "nestjs graphql resolver query mutation subscription apollo",
|
|
2713
|
-
description: "Map NestJS GraphQL resolvers — Query, Mutation, Subscription handlers with return types.",
|
|
2714
|
-
schema: {
|
|
2715
|
-
repo: z.string().optional().describe("Repository identifier (default: auto-detected from CWD)"),
|
|
2716
|
-
max_entries: z.number().optional().describe("Max resolver entries (default: 300)"),
|
|
2717
|
-
},
|
|
2718
|
-
handler: async (args) => nestGraphQLMap(args.repo ?? "", args),
|
|
2719
|
-
},
|
|
2720
|
-
{
|
|
2721
|
-
name: "nest_websocket_map",
|
|
2722
|
-
category: "nestjs",
|
|
2723
|
-
searchHint: "nestjs websocket gateway subscribemessage socketio realtime event",
|
|
2724
|
-
description: "Map NestJS WebSocket gateways with port, namespace, and subscribed events.",
|
|
2725
|
-
schema: {
|
|
2726
|
-
repo: z.string().optional().describe("Repository identifier (default: auto-detected from CWD)"),
|
|
2727
|
-
max_gateways: z.number().optional().describe("Max gateways (default: 100)"),
|
|
2728
|
-
},
|
|
2729
|
-
handler: async (args) => nestWebSocketMap(args.repo ?? "", args),
|
|
2730
|
-
},
|
|
2731
|
-
{
|
|
2732
|
-
name: "nest_schedule_map",
|
|
2733
|
-
category: "nestjs",
|
|
2734
|
-
searchHint: "nestjs cron interval timeout scheduled job task onevent event listener",
|
|
2735
|
-
description: "Map NestJS scheduled tasks (@Cron/@Interval/@Timeout) and event listeners (@OnEvent).",
|
|
2736
|
-
schema: {
|
|
2737
|
-
repo: z.string().optional().describe("Repository identifier (default: auto-detected from CWD)"),
|
|
2738
|
-
max_schedules: z.number().optional().describe("Max schedule entries (default: 300)"),
|
|
2739
|
-
max_files_scanned: z.number().optional().describe("Max files to scan (default: 2000)"),
|
|
2740
|
-
},
|
|
2741
|
-
handler: async (args) => nestScheduleMap(args.repo ?? "", args),
|
|
2742
|
-
},
|
|
2743
|
-
{
|
|
2744
|
-
name: "nest_typeorm_map",
|
|
2745
|
-
category: "nestjs",
|
|
2746
|
-
searchHint: "nestjs typeorm entity relation onetomany manytoone database schema",
|
|
2747
|
-
description: "Build TypeORM entity relation graph with OneToMany/ManyToOne edges and cycle detection.",
|
|
2748
|
-
schema: {
|
|
2749
|
-
repo: z.string().optional().describe("Repository identifier (default: auto-detected from CWD)"),
|
|
2750
|
-
max_entities: z.number().optional().describe("Max entities (default: 200)"),
|
|
2751
|
-
},
|
|
2752
|
-
handler: async (args) => nestTypeOrmMap(args.repo ?? "", args),
|
|
2753
|
-
},
|
|
2754
|
-
{
|
|
2755
|
-
name: "nest_microservice_map",
|
|
2756
|
-
category: "nestjs",
|
|
2757
|
-
searchHint: "nestjs microservice messagepattern eventpattern kafka rabbitmq nats transport",
|
|
2758
|
-
description: "Map NestJS microservice @MessagePattern and @EventPattern handlers.",
|
|
2759
|
-
schema: {
|
|
2760
|
-
repo: z.string().optional().describe("Repository identifier (default: auto-detected from CWD)"),
|
|
2761
|
-
max_patterns: z.number().optional().describe("Max patterns (default: 300)"),
|
|
2762
|
-
},
|
|
2763
|
-
handler: async (args) => nestMicroserviceMap(args.repo ?? "", args),
|
|
2764
|
-
},
|
|
2765
2709
|
// --- Agent config audit ---
|
|
2766
2710
|
{
|
|
2767
2711
|
name: "audit_agent_config",
|
|
@@ -3007,6 +2951,7 @@ const TOOL_DEFINITIONS = [
|
|
|
3007
2951
|
repo: z.string().optional().describe("Repository identifier (default: auto-detected from CWD)"),
|
|
3008
2952
|
severity: z.enum(["all", "warnings", "errors"]).default("all").describe("Filter issues by severity (default: all)"),
|
|
3009
2953
|
path_prefix: z.string().optional().describe("Only scan files under this path prefix"),
|
|
2954
|
+
fail_on: z.enum(["error", "warning", "info"]).optional().describe("Set exit_code gate: 'error' exits 1 on any errors; 'warning' exits 2 on warnings; 'info' exits 2 on info or warnings"),
|
|
3010
2955
|
},
|
|
3011
2956
|
handler: async (args) => {
|
|
3012
2957
|
const opts = {};
|
|
@@ -3016,6 +2961,8 @@ const TOOL_DEFINITIONS = [
|
|
|
3016
2961
|
opts.severity = args.severity;
|
|
3017
2962
|
if (args.path_prefix != null)
|
|
3018
2963
|
opts.path_prefix = args.path_prefix;
|
|
2964
|
+
if (args.fail_on != null)
|
|
2965
|
+
opts.fail_on = args.fail_on;
|
|
3019
2966
|
return await astroHydrationAudit(opts);
|
|
3020
2967
|
},
|
|
3021
2968
|
},
|
|
@@ -3055,20 +3002,82 @@ const TOOL_DEFINITIONS = [
|
|
|
3055
3002
|
return await astroConfigAnalyze({ project_root: index.root });
|
|
3056
3003
|
},
|
|
3057
3004
|
},
|
|
3005
|
+
{
|
|
3006
|
+
name: "astro_actions_audit",
|
|
3007
|
+
category: "analysis",
|
|
3008
|
+
searchHint: "astro actions defineAction zod refine passthrough multipart file enctype audit",
|
|
3009
|
+
description: "Audit Astro Actions (src/actions/index.ts) for 6 known anti-patterns (AA01-AA06): missing handler return, top-level .refine() (Astro issue #11641), .passthrough() usage (issue #11693), File schema without multipart form, server-side invocation via actions.xxx(), and client calls to unknown actions. Returns issues grouped by severity with an A/B/C/D score.",
|
|
3010
|
+
schema: {
|
|
3011
|
+
repo: z.string().optional().describe("Repository identifier (default: auto-detected from CWD)"),
|
|
3012
|
+
severity: z.enum(["all", "warnings", "errors"]).default("all").describe("Filter issues by severity (default: all)"),
|
|
3013
|
+
},
|
|
3014
|
+
handler: async (args) => {
|
|
3015
|
+
const opts = {};
|
|
3016
|
+
if (args.repo != null)
|
|
3017
|
+
opts.repo = args.repo;
|
|
3018
|
+
if (args.severity != null)
|
|
3019
|
+
opts.severity = args.severity;
|
|
3020
|
+
return await astroActionsAudit(opts);
|
|
3021
|
+
},
|
|
3022
|
+
},
|
|
3023
|
+
{
|
|
3024
|
+
name: "astro_content_collections",
|
|
3025
|
+
category: "analysis",
|
|
3026
|
+
searchHint: "astro content collections defineCollection zod schema reference glob loader frontmatter",
|
|
3027
|
+
description: "Parse an Astro content collections config (src/content.config.ts or legacy src/content/config.ts), extract each collection's loader + Zod schema fields, build a reference() graph, and optionally validate entry frontmatter against required fields.",
|
|
3028
|
+
schema: {
|
|
3029
|
+
repo: z.string().optional().describe("Repository identifier (default: auto-detected from CWD)"),
|
|
3030
|
+
validate_entries: z.boolean().default(true).describe("Validate entry frontmatter against required schema fields (default: true)"),
|
|
3031
|
+
},
|
|
3032
|
+
handler: async (args) => {
|
|
3033
|
+
const index = await getCodeIndex(args.repo ?? "");
|
|
3034
|
+
if (!index)
|
|
3035
|
+
throw new Error("Repository not found — run index_folder first");
|
|
3036
|
+
const opts = { project_root: index.root };
|
|
3037
|
+
if (args.validate_entries != null)
|
|
3038
|
+
opts.validate_entries = args.validate_entries;
|
|
3039
|
+
return await astroContentCollections(opts);
|
|
3040
|
+
},
|
|
3041
|
+
},
|
|
3042
|
+
{
|
|
3043
|
+
name: "astro_audit",
|
|
3044
|
+
category: "analysis",
|
|
3045
|
+
searchHint: "astro meta audit full health check score gates recommendations islands hydration routes config actions content migration patterns",
|
|
3046
|
+
description: "One-call Astro project health check: runs all 7 Astro tools + 13 Astro patterns in parallel, returns unified {score, gates, sections, recommendations}. Mirrors react_quickstart pattern.",
|
|
3047
|
+
schema: {
|
|
3048
|
+
repo: z.string().optional().describe("Repository identifier (default: auto-detected from CWD)"),
|
|
3049
|
+
skip: z.array(z.string()).optional().describe("Sections to skip: config, hydration, routes, actions, content, migration, patterns"),
|
|
3050
|
+
},
|
|
3051
|
+
handler: async (args) => {
|
|
3052
|
+
const opts = {};
|
|
3053
|
+
if (args.repo != null)
|
|
3054
|
+
opts.repo = args.repo;
|
|
3055
|
+
if (args.skip != null)
|
|
3056
|
+
opts.skip = args.skip;
|
|
3057
|
+
return await astroAudit(opts);
|
|
3058
|
+
},
|
|
3059
|
+
},
|
|
3058
3060
|
// --- Hono framework tools (Task 23) ---
|
|
3059
3061
|
{
|
|
3060
3062
|
name: "trace_middleware_chain",
|
|
3061
3063
|
category: "graph",
|
|
3062
|
-
searchHint: "hono middleware chain trace order scope auth use",
|
|
3063
|
-
description: "
|
|
3064
|
+
searchHint: "hono middleware chain trace order scope auth use conditional applied_when if method header path basicAuth gated",
|
|
3065
|
+
description: "Hono middleware introspection. Three query modes: (1) route mode — pass path (+optional method) to get the chain effective for that route; (2) scope mode — pass scope literal (e.g. '/posts/*') to get that specific app.use chain; (3) app-wide mode — omit path and scope to get every chain flattened. Any mode supports only_conditional=true to filter to entries with applied_when populated, so the blog-API pattern (basicAuth wrapped in `if (method !== 'GET')`) is surfaced as gated rather than missed. Absorbs the former trace_conditional_middleware tool.",
|
|
3064
3066
|
schema: {
|
|
3065
3067
|
repo: z.string().optional().describe("Repository identifier (default: auto-detected from CWD)"),
|
|
3066
|
-
path: z.string().describe("
|
|
3067
|
-
method: z.string().optional().describe("HTTP method filter (GET, POST, etc.)"),
|
|
3068
|
+
path: z.string().optional().describe("Route path to look up (e.g. '/api/users/:id'). Omit for scope or app-wide query."),
|
|
3069
|
+
method: z.string().optional().describe("HTTP method filter (GET, POST, etc.). Only used in route mode."),
|
|
3070
|
+
scope: z.string().optional().describe("Exact middleware scope literal (e.g. '/posts/*'). Mutually exclusive with path."),
|
|
3071
|
+
only_conditional: z.boolean().optional().describe("Filter entries to those whose applied_when field is populated (conditional middleware)."),
|
|
3068
3072
|
},
|
|
3069
3073
|
handler: async (args) => {
|
|
3070
3074
|
const { traceMiddlewareChain } = await import("./tools/hono-middleware-chain.js");
|
|
3071
|
-
|
|
3075
|
+
const opts = {};
|
|
3076
|
+
if (args.scope !== undefined)
|
|
3077
|
+
opts.scope = args.scope;
|
|
3078
|
+
if (args.only_conditional !== undefined)
|
|
3079
|
+
opts.only_conditional = args.only_conditional;
|
|
3080
|
+
return await traceMiddlewareChain(args.repo, args.path, args.method, Object.keys(opts).length > 0 ? opts : undefined);
|
|
3072
3081
|
},
|
|
3073
3082
|
},
|
|
3074
3083
|
{
|
|
@@ -3131,8 +3140,8 @@ const TOOL_DEFINITIONS = [
|
|
|
3131
3140
|
{
|
|
3132
3141
|
name: "audit_hono_security",
|
|
3133
3142
|
category: "security",
|
|
3134
|
-
searchHint: "hono security audit rate limit secure headers auth order csrf",
|
|
3135
|
-
description: "Security audit of a Hono app: missing rate
|
|
3143
|
+
searchHint: "hono security audit rate limit secure headers auth order csrf env regression createMiddleware BlankEnv Issue 3587",
|
|
3144
|
+
description: "Security + type-safety audit of a Hono app. Rules: missing-secure-headers (global), missing-rate-limit + missing-auth (mutation routes, conditional-middleware aware via applied_when), auth-ordering (auth after non-auth in chain), env-regression (plain createMiddleware in 3+ chains — Hono Issue #3587, absorbed from the former detect_middleware_env_regression tool). Returns prioritized findings plus heuristic disclaimers via `notes` field for best-effort rules.",
|
|
3136
3145
|
schema: {
|
|
3137
3146
|
repo: z.string().optional().describe("Repository identifier (default: auto-detected from CWD)"),
|
|
3138
3147
|
},
|
|
@@ -3156,20 +3165,6 @@ const TOOL_DEFINITIONS = [
|
|
|
3156
3165
|
},
|
|
3157
3166
|
},
|
|
3158
3167
|
// --- Hono Phase 2 tools (T13) ---
|
|
3159
|
-
{
|
|
3160
|
-
name: "trace_conditional_middleware",
|
|
3161
|
-
category: "analysis",
|
|
3162
|
-
searchHint: "hono conditional middleware applied_when if method header path basicAuth auth gated",
|
|
3163
|
-
description: "List Hono middleware entries that are applied under a runtime condition (e.g., basicAuth only for non-GET methods). Each entry carries condition_type (method|header|path|custom) + condition_text. Closes blog-API false positive where audit_hono_security flagged inline-arrow conditional auth as missing.",
|
|
3164
|
-
schema: {
|
|
3165
|
-
repo: z.string().optional().describe("Repository identifier (default: auto-detected from CWD)"),
|
|
3166
|
-
scope: z.string().optional().describe("Filter to a specific middleware scope (e.g. '/posts/*')"),
|
|
3167
|
-
},
|
|
3168
|
-
handler: async (args) => {
|
|
3169
|
-
const { traceConditionalMiddleware } = await import("./tools/hono-conditional-middleware.js");
|
|
3170
|
-
return await traceConditionalMiddleware(args.repo, args.scope);
|
|
3171
|
-
},
|
|
3172
|
-
},
|
|
3173
3168
|
{
|
|
3174
3169
|
name: "analyze_inline_handler",
|
|
3175
3170
|
category: "analysis",
|
|
@@ -3198,19 +3193,6 @@ const TOOL_DEFINITIONS = [
|
|
|
3198
3193
|
return await extractResponseTypes(args.repo);
|
|
3199
3194
|
},
|
|
3200
3195
|
},
|
|
3201
|
-
{
|
|
3202
|
-
name: "detect_middleware_env_regression",
|
|
3203
|
-
category: "analysis",
|
|
3204
|
-
searchHint: "hono middleware env regression createMiddleware generic BlankEnv type Issue 3587",
|
|
3205
|
-
description: "Heuristic static check for Hono Issue #3587: flags middleware chains of 3+ entries where an intermediate member is declared with plain createMiddleware(...) (no Env generic), which resets the accumulated Env type to BlankEnv for downstream middleware. Reports chain_scope + chain_length + middleware_name + definition file:line. Includes a heuristic disclaimer in the result note.",
|
|
3206
|
-
schema: {
|
|
3207
|
-
repo: z.string().optional().describe("Repository identifier (default: auto-detected from CWD)"),
|
|
3208
|
-
},
|
|
3209
|
-
handler: async (args) => {
|
|
3210
|
-
const { detectMiddlewareEnvRegression } = await import("./tools/hono-env-regression.js");
|
|
3211
|
-
return await detectMiddlewareEnvRegression(args.repo);
|
|
3212
|
-
},
|
|
3213
|
-
},
|
|
3214
3196
|
{
|
|
3215
3197
|
name: "detect_hono_modules",
|
|
3216
3198
|
category: "analysis",
|
|
@@ -3238,29 +3220,6 @@ const TOOL_DEFINITIONS = [
|
|
|
3238
3220
|
},
|
|
3239
3221
|
},
|
|
3240
3222
|
// --- Next.js framework tools ---
|
|
3241
|
-
{
|
|
3242
|
-
name: "analyze_nextjs_components",
|
|
3243
|
-
category: "analysis",
|
|
3244
|
-
searchHint: "nextjs next.js component server client classifier use client use server hooks",
|
|
3245
|
-
description: "Classify Next.js files as Server or Client components via AST analysis. Detects 'use client'/'use server' directives (with 512-byte window + comment stripping), hooks, JSX event handlers, browser globals, and next/dynamic({ ssr:false }). Flags unnecessary 'use client' and async client components. Supports monorepo workspace auto-detection.",
|
|
3246
|
-
schema: {
|
|
3247
|
-
repo: z.string().optional().describe("Repository identifier (default: auto-detected from CWD)"),
|
|
3248
|
-
workspace: z.string().optional().describe("Monorepo workspace path, e.g. 'apps/web'"),
|
|
3249
|
-
file_pattern: z.string().optional().describe("Glob to scope the scan, e.g. 'app/products/**'"),
|
|
3250
|
-
max_files: z.number().int().positive().optional().describe("Max files to scan (default 2000)"),
|
|
3251
|
-
},
|
|
3252
|
-
handler: async (args) => {
|
|
3253
|
-
const opts = {};
|
|
3254
|
-
if (args.workspace != null)
|
|
3255
|
-
opts.workspace = args.workspace;
|
|
3256
|
-
if (args.file_pattern != null)
|
|
3257
|
-
opts.file_pattern = args.file_pattern;
|
|
3258
|
-
if (args.max_files != null)
|
|
3259
|
-
opts.max_files = args.max_files;
|
|
3260
|
-
const result = await analyzeNextjsComponents(args.repo ?? "", opts);
|
|
3261
|
-
return formatNextjsComponents(result);
|
|
3262
|
-
},
|
|
3263
|
-
},
|
|
3264
3223
|
{
|
|
3265
3224
|
name: "nextjs_route_map",
|
|
3266
3225
|
category: "analysis",
|
|
@@ -3307,135 +3266,17 @@ const TOOL_DEFINITIONS = [
|
|
|
3307
3266
|
return formatNextjsMetadataAudit(result);
|
|
3308
3267
|
},
|
|
3309
3268
|
},
|
|
3310
|
-
{
|
|
3311
|
-
name: "nextjs_audit_server_actions",
|
|
3312
|
-
category: "security",
|
|
3313
|
-
searchHint: "nextjs server actions security audit auth validation rate limit zod use server",
|
|
3314
|
-
description: "Audit Next.js Server Actions for security weaknesses across four checks: authorization guards, input validation (Zod-aware), rate limiting, and structured error handling. Per-action weighted scoring (auth 40, validation 30, rate 20, errors 10) with grade buckets.",
|
|
3315
|
-
schema: {
|
|
3316
|
-
repo: z.string().optional().describe("Repository identifier (default: auto-detected from CWD)"),
|
|
3317
|
-
workspace: z.string().optional().describe("Monorepo workspace path, e.g. 'apps/web'"),
|
|
3318
|
-
max_files: z.number().int().positive().optional().describe("Max files to scan (default 2000)"),
|
|
3319
|
-
},
|
|
3320
|
-
handler: async (args) => {
|
|
3321
|
-
const opts = {};
|
|
3322
|
-
if (args.workspace != null)
|
|
3323
|
-
opts.workspace = args.workspace;
|
|
3324
|
-
if (args.max_files != null)
|
|
3325
|
-
opts.max_files = args.max_files;
|
|
3326
|
-
const result = await nextjsAuditServerActions(args.repo ?? "", opts);
|
|
3327
|
-
return formatNextjsAuditServerActions(result);
|
|
3328
|
-
},
|
|
3329
|
-
},
|
|
3330
|
-
{
|
|
3331
|
-
name: "nextjs_api_contract",
|
|
3332
|
-
category: "analysis",
|
|
3333
|
-
searchHint: "nextjs api contract route handler openapi method body schema response zod",
|
|
3334
|
-
description: "Extract API handler contracts from Next.js route handlers (App Router app/api/**/route.ts and Pages Router pages/api/**/*.ts). Captures HTTP methods, query params, request body schemas (Zod-aware), response shapes, and inferred status codes per handler.",
|
|
3335
|
-
schema: {
|
|
3336
|
-
repo: z.string().optional().describe("Repository identifier (default: auto-detected from CWD)"),
|
|
3337
|
-
workspace: z.string().optional().describe("Monorepo workspace path, e.g. 'apps/web'"),
|
|
3338
|
-
max_files: z.number().int().positive().optional().describe("Max files to scan (default 1000)"),
|
|
3339
|
-
},
|
|
3340
|
-
handler: async (args) => {
|
|
3341
|
-
const opts = {};
|
|
3342
|
-
if (args.workspace != null)
|
|
3343
|
-
opts.workspace = args.workspace;
|
|
3344
|
-
if (args.max_files != null)
|
|
3345
|
-
opts.max_files = args.max_files;
|
|
3346
|
-
const result = await nextjsApiContract(args.repo ?? "", opts);
|
|
3347
|
-
return formatNextjsApiContract(result);
|
|
3348
|
-
},
|
|
3349
|
-
},
|
|
3350
|
-
{
|
|
3351
|
-
name: "nextjs_boundary_analyzer",
|
|
3352
|
-
category: "analysis",
|
|
3353
|
-
searchHint: "nextjs client boundary use client component bundle imports loc score",
|
|
3354
|
-
description: "Analyze Next.js client component boundaries — walks `app/**/*.{tsx,jsx}` files marked `\"use client\"`, computes a deterministic ranking score from cheap signals (LOC, import counts, dynamic imports, third-party imports), and returns a top-N list of largest offenders. Score is signal-based, not actual bundle bytes.",
|
|
3355
|
-
schema: {
|
|
3356
|
-
repo: z.string().optional().describe("Repository identifier (default: auto-detected from CWD)"),
|
|
3357
|
-
workspace: z.string().optional().describe("Monorepo workspace path, e.g. 'apps/web'"),
|
|
3358
|
-
top_n: z.number().int().positive().optional().describe("Number of top entries to return (default 20)"),
|
|
3359
|
-
},
|
|
3360
|
-
handler: async (args) => {
|
|
3361
|
-
const opts = {};
|
|
3362
|
-
if (args.workspace != null)
|
|
3363
|
-
opts.workspace = args.workspace;
|
|
3364
|
-
if (args.top_n != null)
|
|
3365
|
-
opts.top_n = args.top_n;
|
|
3366
|
-
const result = await nextjsBoundaryAnalyzer(args.repo ?? "", opts);
|
|
3367
|
-
return formatNextjsBoundaryAnalyzer(result);
|
|
3368
|
-
},
|
|
3369
|
-
},
|
|
3370
|
-
{
|
|
3371
|
-
name: "nextjs_link_integrity",
|
|
3372
|
-
category: "analysis",
|
|
3373
|
-
searchHint: "nextjs link integrity broken navigation Link href router push 404",
|
|
3374
|
-
description: "Cross-reference Next.js navigation refs (<Link href>, router.push/.replace) against the route map to flag broken links. Template-literal hrefs are bucketed as 'unresolved' rather than guessed.",
|
|
3375
|
-
schema: {
|
|
3376
|
-
repo: z.string().optional().describe("Repository identifier (default: auto-detected from CWD)"),
|
|
3377
|
-
workspace: z.string().optional().describe("Monorepo workspace path, e.g. 'apps/web'"),
|
|
3378
|
-
max_files: z.number().int().positive().optional().describe("Max files to scan (default 2000)"),
|
|
3379
|
-
},
|
|
3380
|
-
handler: async (args) => {
|
|
3381
|
-
const opts = {};
|
|
3382
|
-
if (args.workspace != null)
|
|
3383
|
-
opts.workspace = args.workspace;
|
|
3384
|
-
if (args.max_files != null)
|
|
3385
|
-
opts.max_files = args.max_files;
|
|
3386
|
-
const result = await nextjsLinkIntegrity(args.repo ?? "", opts);
|
|
3387
|
-
return formatNextjsLinkIntegrity(result);
|
|
3388
|
-
},
|
|
3389
|
-
},
|
|
3390
|
-
{
|
|
3391
|
-
name: "nextjs_data_flow",
|
|
3392
|
-
category: "analysis",
|
|
3393
|
-
searchHint: "nextjs data flow fetch waterfall cache cookies headers ssr revalidate",
|
|
3394
|
-
description: "Analyze data fetching patterns in Next.js pages: detect fetch waterfalls (sequential awaits in same scope), classify cache strategies (no-cache, cached, ISR), and aggregate per-page data flow with totals.",
|
|
3395
|
-
schema: {
|
|
3396
|
-
repo: z.string().optional().describe("Repository identifier (default: auto-detected from CWD)"),
|
|
3397
|
-
workspace: z.string().optional().describe("Monorepo workspace path, e.g. 'apps/web'"),
|
|
3398
|
-
url_path: z.string().optional().describe("Filter to a single URL path"),
|
|
3399
|
-
},
|
|
3400
|
-
handler: async (args) => {
|
|
3401
|
-
const opts = {};
|
|
3402
|
-
if (args.workspace != null)
|
|
3403
|
-
opts.workspace = args.workspace;
|
|
3404
|
-
if (args.url_path != null)
|
|
3405
|
-
opts.url_path = args.url_path;
|
|
3406
|
-
const result = await nextjsDataFlow(args.repo ?? "", opts);
|
|
3407
|
-
return formatNextjsDataFlow(result);
|
|
3408
|
-
},
|
|
3409
|
-
},
|
|
3410
|
-
{
|
|
3411
|
-
name: "nextjs_middleware_coverage",
|
|
3412
|
-
category: "security",
|
|
3413
|
-
searchHint: "nextjs middleware coverage protected admin auth route matcher security",
|
|
3414
|
-
description: "Cross-reference Next.js routes with middleware matcher config to compute coverage. Flags admin/dashboard routes without middleware protection as high-severity warnings.",
|
|
3415
|
-
schema: {
|
|
3416
|
-
repo: z.string().optional().describe("Repository identifier (default: auto-detected from CWD)"),
|
|
3417
|
-
workspace: z.string().optional().describe("Monorepo workspace path, e.g. 'apps/web'"),
|
|
3418
|
-
flag_admin_prefix: z.union([z.string(), z.array(z.string())]).optional().describe("Admin path prefix(es) to flag (default: ['/admin', '/dashboard'])"),
|
|
3419
|
-
},
|
|
3420
|
-
handler: async (args) => {
|
|
3421
|
-
const opts = {};
|
|
3422
|
-
if (args.workspace != null)
|
|
3423
|
-
opts.workspace = args.workspace;
|
|
3424
|
-
if (args.flag_admin_prefix != null)
|
|
3425
|
-
opts.flag_admin_prefix = args.flag_admin_prefix;
|
|
3426
|
-
const result = await nextjsMiddlewareCoverage(args.repo ?? "", opts);
|
|
3427
|
-
return formatNextjsMiddlewareCoverage(result);
|
|
3428
|
-
},
|
|
3429
|
-
},
|
|
3430
3269
|
{
|
|
3431
3270
|
name: "framework_audit",
|
|
3432
3271
|
category: "analysis",
|
|
3433
|
-
searchHint: "nextjs framework audit meta-tool overall score security metadata routes components",
|
|
3272
|
+
searchHint: "nextjs next.js framework audit meta-tool overall score security metadata routes components classifier use client use server hooks server actions auth validation rate limit zod api contract route handler openapi method body schema response client boundary bundle imports loc link integrity broken navigation href router push 404 data flow fetch waterfall cache cookies headers ssr revalidate middleware coverage protected admin matcher",
|
|
3434
3273
|
description: "Run all Next.js sub-audits (components, routes, metadata, security, api_contract, boundary, links, data_flow, middleware_coverage) and aggregate into a unified weighted overall score with grade. Use as a single first-call for any Next.js project.",
|
|
3435
3274
|
schema: {
|
|
3436
3275
|
repo: z.string().optional().describe("Repository identifier (default: auto-detected from CWD)"),
|
|
3437
3276
|
workspace: z.string().optional().describe("Monorepo workspace path, e.g. 'apps/web'"),
|
|
3438
3277
|
tools: z.array(z.string()).optional().describe("Subset of tools to run (default: all 9). Names: components, routes, metadata, security, api_contract, boundary, links, data_flow, middleware_coverage"),
|
|
3278
|
+
mode: z.enum(["full", "priority"]).optional().describe("Output mode: 'full' returns per-tool results + aggregated summary; 'priority' returns a single unified top-N actionable findings list sorted by severity × cross-tool occurrences"),
|
|
3279
|
+
priority_limit: z.number().int().positive().optional().describe("Max findings in priority mode (default: 20)"),
|
|
3439
3280
|
},
|
|
3440
3281
|
handler: async (args) => {
|
|
3441
3282
|
const opts = {};
|
|
@@ -3443,6 +3284,10 @@ const TOOL_DEFINITIONS = [
|
|
|
3443
3284
|
opts.workspace = args.workspace;
|
|
3444
3285
|
if (args.tools != null)
|
|
3445
3286
|
opts.tools = args.tools;
|
|
3287
|
+
if (args.mode != null)
|
|
3288
|
+
opts.mode = args.mode;
|
|
3289
|
+
if (args.priority_limit != null)
|
|
3290
|
+
opts.priority_limit = args.priority_limit;
|
|
3446
3291
|
const result = await frameworkAudit(args.repo ?? "", opts);
|
|
3447
3292
|
return formatFrameworkAudit(result);
|
|
3448
3293
|
},
|
|
@@ -3543,94 +3388,40 @@ const TOOL_DEFINITIONS = [
|
|
|
3543
3388
|
},
|
|
3544
3389
|
},
|
|
3545
3390
|
{
|
|
3546
|
-
name: "
|
|
3547
|
-
category: "analysis",
|
|
3548
|
-
searchHint: "schema complexity god table column count FK index score refactor",
|
|
3549
|
-
description: "Per-table complexity score based on column count, FK relationships, and indexes. Identifies god tables needing refactoring. Sorted by score descending.",
|
|
3550
|
-
schema: {
|
|
3551
|
-
repo: z.string().optional().describe("Repository identifier (default: auto-detected from CWD)"),
|
|
3552
|
-
file_pattern: z.string().optional().describe("Scope to files matching pattern"),
|
|
3553
|
-
top_n: zNum().describe("Return top N most complex tables (default: 50)"),
|
|
3554
|
-
},
|
|
3555
|
-
handler: async (args) => {
|
|
3556
|
-
const { analyzeSchemaComplexity } = await import("./tools/sql-tools.js");
|
|
3557
|
-
const opts = {};
|
|
3558
|
-
if (args.file_pattern != null)
|
|
3559
|
-
opts.file_pattern = args.file_pattern;
|
|
3560
|
-
if (args.top_n != null)
|
|
3561
|
-
opts.top_n = args.top_n;
|
|
3562
|
-
const result = await analyzeSchemaComplexity(args.repo, opts);
|
|
3563
|
-
const parts = [];
|
|
3564
|
-
parts.push(`Schema complexity: ${result.tables.length} tables`);
|
|
3565
|
-
parts.push(`${"Table".padEnd(30)} ${"Cols".padStart(5)} ${"FKs".padStart(4)} ${"Idx".padStart(4)} ${"Score".padStart(7)}`);
|
|
3566
|
-
for (const t of result.tables) {
|
|
3567
|
-
parts.push(` ${t.name.padEnd(28)} ${String(t.column_count).padStart(5)} ${String(t.fk_count).padStart(4)} ${String(t.index_count).padStart(4)} ${t.score.toFixed(1).padStart(7)}`);
|
|
3568
|
-
}
|
|
3569
|
-
return parts.join("\n");
|
|
3570
|
-
},
|
|
3571
|
-
},
|
|
3572
|
-
{
|
|
3573
|
-
name: "scan_dml_safety",
|
|
3391
|
+
name: "sql_audit",
|
|
3574
3392
|
category: "analysis",
|
|
3575
|
-
searchHint: "
|
|
3576
|
-
description: "
|
|
3393
|
+
searchHint: "SQL audit composite drift orphan lint DML safety complexity god table schema diagnostic",
|
|
3394
|
+
description: "Composite SQL audit — runs 5 diagnostic gates (drift, orphan, lint, dml, complexity) in one call. Use this instead of calling the individual gate functions separately.",
|
|
3577
3395
|
schema: {
|
|
3578
3396
|
repo: z.string().optional().describe("Repository identifier (default: auto-detected from CWD)"),
|
|
3397
|
+
checks: z.array(z.enum(["drift", "orphan", "lint", "dml", "complexity"])).optional().describe("Subset of gates to run (default: all 5)"),
|
|
3579
3398
|
file_pattern: z.string().optional().describe("Scope to files matching pattern"),
|
|
3580
|
-
max_results: zNum().describe("Max findings per pattern (default: 200)"),
|
|
3399
|
+
max_results: zNum().describe("Max DML findings per pattern (default: 200)"),
|
|
3581
3400
|
},
|
|
3582
3401
|
handler: async (args) => {
|
|
3583
|
-
const {
|
|
3402
|
+
const { sqlAudit } = await import("./tools/sql-tools.js");
|
|
3584
3403
|
const opts = {};
|
|
3404
|
+
if (args.checks != null)
|
|
3405
|
+
opts.checks = args.checks;
|
|
3585
3406
|
if (args.file_pattern != null)
|
|
3586
3407
|
opts.file_pattern = args.file_pattern;
|
|
3587
3408
|
if (args.max_results != null)
|
|
3588
3409
|
opts.max_results = args.max_results;
|
|
3589
|
-
const result = await
|
|
3410
|
+
const result = await sqlAudit(args.repo, opts);
|
|
3590
3411
|
const parts = [];
|
|
3591
|
-
parts.push(`
|
|
3592
|
-
|
|
3593
|
-
|
|
3594
|
-
|
|
3595
|
-
const
|
|
3596
|
-
|
|
3597
|
-
parts.push(
|
|
3598
|
-
for (const f of high.slice(0, 20)) {
|
|
3599
|
-
parts.push(` [${f.rule}] ${f.file}:${f.line} ${f.context ?? ""}`);
|
|
3600
|
-
}
|
|
3601
|
-
}
|
|
3602
|
-
return parts.join("\n");
|
|
3603
|
-
},
|
|
3604
|
-
},
|
|
3605
|
-
{
|
|
3606
|
-
name: "lint_schema",
|
|
3607
|
-
category: "analysis",
|
|
3608
|
-
searchHint: "lint SQL schema anti-pattern primary key wide table duplicate index design",
|
|
3609
|
-
description: "Lint SQL schema for anti-patterns: missing primary key, wide tables (>20 cols), duplicate index names. Conservative ruleset with near-zero false positives.",
|
|
3610
|
-
schema: {
|
|
3611
|
-
repo: z.string().optional().describe("Repository identifier (default: auto-detected from CWD)"),
|
|
3612
|
-
file_pattern: z.string().optional().describe("Scope to files matching pattern"),
|
|
3613
|
-
},
|
|
3614
|
-
handler: async (args) => {
|
|
3615
|
-
const { lintSchema } = await import("./tools/sql-tools.js");
|
|
3616
|
-
const opts = {};
|
|
3617
|
-
if (args.file_pattern != null)
|
|
3618
|
-
opts.file_pattern = args.file_pattern;
|
|
3619
|
-
const result = await lintSchema(args.repo, opts);
|
|
3620
|
-
const parts = [];
|
|
3621
|
-
parts.push(`Schema lint: ${result.summary.total} finding${result.summary.total === 1 ? "" : "s"}`);
|
|
3622
|
-
for (const [rule, count] of Object.entries(result.summary.by_rule)) {
|
|
3623
|
-
parts.push(` ${rule}: ${count}`);
|
|
3412
|
+
parts.push(`SQL audit: ${result.summary.gates_run} gates run, ${result.summary.gates_passed} passed, ${result.summary.gates_failed} failed`);
|
|
3413
|
+
parts.push(` Total findings: ${result.summary.total_findings}`);
|
|
3414
|
+
parts.push(` Critical findings: ${result.summary.critical_findings}`);
|
|
3415
|
+
parts.push("");
|
|
3416
|
+
for (const g of result.gates) {
|
|
3417
|
+
const icon = g.pass ? "✓" : (g.critical ? "✗ CRITICAL" : "⚠");
|
|
3418
|
+
parts.push(`${icon} ${g.check}: ${g.summary}`);
|
|
3624
3419
|
}
|
|
3625
3420
|
if (result.warnings.length > 0) {
|
|
3626
|
-
for (const w of result.warnings)
|
|
3627
|
-
parts.push(`⚠ ${w}`);
|
|
3628
|
-
}
|
|
3629
|
-
if (result.findings.length > 0) {
|
|
3630
3421
|
parts.push("");
|
|
3631
|
-
|
|
3632
|
-
|
|
3633
|
-
|
|
3422
|
+
parts.push("─── Warnings ───");
|
|
3423
|
+
for (const w of result.warnings)
|
|
3424
|
+
parts.push(` ⚠ ${w}`);
|
|
3634
3425
|
}
|
|
3635
3426
|
return parts.join("\n");
|
|
3636
3427
|
},
|
|
@@ -3670,35 +3461,6 @@ const TOOL_DEFINITIONS = [
|
|
|
3670
3461
|
return parts.join("\n");
|
|
3671
3462
|
},
|
|
3672
3463
|
},
|
|
3673
|
-
{
|
|
3674
|
-
name: "find_orphan_tables",
|
|
3675
|
-
category: "analysis",
|
|
3676
|
-
searchHint: "orphan table SQL unused dead unreferenced no query no model drop candidate",
|
|
3677
|
-
description: "Find SQL tables with zero references in the codebase — no DML queries, no ORM models, no FK references. Candidates for DROP TABLE.",
|
|
3678
|
-
schema: {
|
|
3679
|
-
repo: z.string().optional().describe("Repository identifier (default: auto-detected from CWD)"),
|
|
3680
|
-
file_pattern: z.string().optional().describe("Scope to SQL files matching pattern"),
|
|
3681
|
-
},
|
|
3682
|
-
handler: async (args) => {
|
|
3683
|
-
const { findOrphanTables } = await import("./tools/sql-tools.js");
|
|
3684
|
-
const opts = {};
|
|
3685
|
-
if (args.file_pattern != null)
|
|
3686
|
-
opts.file_pattern = args.file_pattern;
|
|
3687
|
-
const result = await findOrphanTables(args.repo, opts);
|
|
3688
|
-
const parts = [];
|
|
3689
|
-
parts.push(`Tables: ${result.total_tables} | Orphans: ${result.orphan_count}`);
|
|
3690
|
-
if (result.orphans.length > 0) {
|
|
3691
|
-
parts.push("");
|
|
3692
|
-
for (const o of result.orphans) {
|
|
3693
|
-
parts.push(` ${o.name.padEnd(30)} ${o.column_count} cols ${o.file}:${o.line}`);
|
|
3694
|
-
}
|
|
3695
|
-
}
|
|
3696
|
-
else {
|
|
3697
|
-
parts.push("No orphan tables found — all tables have at least one reference.");
|
|
3698
|
-
}
|
|
3699
|
-
return parts.join("\n");
|
|
3700
|
-
},
|
|
3701
|
-
},
|
|
3702
3464
|
{
|
|
3703
3465
|
name: "search_columns",
|
|
3704
3466
|
category: "search",
|
|
@@ -3734,45 +3496,69 @@ const TOOL_DEFINITIONS = [
|
|
|
3734
3496
|
return parts.join("\n");
|
|
3735
3497
|
},
|
|
3736
3498
|
},
|
|
3499
|
+
// --- Astro v6 migration check ---
|
|
3737
3500
|
{
|
|
3738
|
-
name: "
|
|
3501
|
+
name: "astro_migration_check",
|
|
3739
3502
|
category: "analysis",
|
|
3740
|
-
searchHint: "
|
|
3741
|
-
description: "
|
|
3503
|
+
searchHint: "astro v6 migration upgrade breaking changes compatibility check AM01 AM10 content collections ViewTransitions",
|
|
3504
|
+
description: "Scan an Astro project for v5→v6 breaking changes. Detects 10 issues (AM01–AM10): removed APIs (Astro.glob, emitESMImage), component renames (ViewTransitions→ClientRouter), content collection config changes, Node.js version requirements, Zod 4 deprecations, hybrid output mode, and removed integrations (@astrojs/lit). Returns a migration report with per-issue effort estimates.",
|
|
3742
3505
|
schema: {
|
|
3743
3506
|
repo: z.string().optional().describe("Repository identifier (default: auto-detected from CWD)"),
|
|
3744
|
-
|
|
3507
|
+
target_version: z.enum(["6"]).optional().describe("Target Astro version (default: '6')"),
|
|
3745
3508
|
},
|
|
3746
3509
|
handler: async (args) => {
|
|
3747
|
-
const
|
|
3748
|
-
|
|
3749
|
-
|
|
3750
|
-
|
|
3751
|
-
|
|
3752
|
-
const
|
|
3753
|
-
|
|
3754
|
-
|
|
3755
|
-
|
|
3756
|
-
|
|
3757
|
-
|
|
3758
|
-
|
|
3759
|
-
|
|
3760
|
-
|
|
3761
|
-
parts.push(`⚠ ${w}`);
|
|
3510
|
+
const mcArgs = {};
|
|
3511
|
+
if (args.repo != null)
|
|
3512
|
+
mcArgs.repo = args.repo;
|
|
3513
|
+
if (args.target_version != null)
|
|
3514
|
+
mcArgs.target_version = args.target_version;
|
|
3515
|
+
const result = await astroMigrationCheck(mcArgs);
|
|
3516
|
+
const lines = [];
|
|
3517
|
+
lines.push(`ASTRO MIGRATION CHECK: v${result.current_version ?? "unknown"} → v${result.target_version}`);
|
|
3518
|
+
lines.push(`Issues: ${result.summary.total_issues} | Estimated: ${result.summary.estimated_migration_hours}`);
|
|
3519
|
+
if (Object.keys(result.summary.by_effort).length > 0) {
|
|
3520
|
+
const effortStr = Object.entries(result.summary.by_effort)
|
|
3521
|
+
.map(([k, v]) => `${v}×${k}`)
|
|
3522
|
+
.join(", ");
|
|
3523
|
+
lines.push(`Effort: ${effortStr}`);
|
|
3762
3524
|
}
|
|
3763
|
-
if (result.
|
|
3764
|
-
|
|
3765
|
-
|
|
3766
|
-
|
|
3767
|
-
|
|
3768
|
-
|
|
3769
|
-
|
|
3770
|
-
|
|
3771
|
-
|
|
3772
|
-
|
|
3525
|
+
if (result.breaking_changes.length === 0) {
|
|
3526
|
+
lines.push("\n✓ No v6 breaking changes detected.");
|
|
3527
|
+
}
|
|
3528
|
+
else {
|
|
3529
|
+
lines.push("");
|
|
3530
|
+
for (const issue of result.breaking_changes) {
|
|
3531
|
+
const sev = issue.severity === "error" ? "✗" : issue.severity === "warning" ? "⚠" : "ℹ";
|
|
3532
|
+
lines.push(`${sev} ${issue.code} [${issue.category}] — ${issue.message}`);
|
|
3533
|
+
lines.push(` effort: ${issue.effort} | files: ${issue.files.slice(0, 3).join(", ")}${issue.files.length > 3 ? ` +${issue.files.length - 3} more` : ""}`);
|
|
3534
|
+
if (issue.migration_guide)
|
|
3535
|
+
lines.push(` guide: ${issue.migration_guide}`);
|
|
3773
3536
|
}
|
|
3774
3537
|
}
|
|
3775
|
-
return
|
|
3538
|
+
return lines.join("\n");
|
|
3539
|
+
},
|
|
3540
|
+
},
|
|
3541
|
+
// --- Discovery / concierge ---
|
|
3542
|
+
{
|
|
3543
|
+
name: "plan_turn",
|
|
3544
|
+
category: "discovery",
|
|
3545
|
+
searchHint: "plan turn routing recommend tools symbols files gap analysis session aware concierge",
|
|
3546
|
+
description: "Routes a natural-language query to the most relevant CodeSift tools, symbols, and files. Uses hybrid BM25+semantic ranking with session-aware dedup. Call at the start of a task to get a prioritized action list.",
|
|
3547
|
+
schema: {
|
|
3548
|
+
repo: z.string().optional().describe("Repository identifier (default: auto-detected from CWD)"),
|
|
3549
|
+
query: z.string().describe("Natural-language description of what you want to do"),
|
|
3550
|
+
max_results: z.number().optional().describe("Max tools to return (default 10)"),
|
|
3551
|
+
skip_session: z.boolean().optional().describe("Skip session state checks (default false)"),
|
|
3552
|
+
},
|
|
3553
|
+
handler: async (args) => {
|
|
3554
|
+
const { query, max_results, skip_session } = args;
|
|
3555
|
+
const opts = {};
|
|
3556
|
+
if (max_results !== undefined)
|
|
3557
|
+
opts.max_results = max_results;
|
|
3558
|
+
if (skip_session !== undefined)
|
|
3559
|
+
opts.skip_session = skip_session;
|
|
3560
|
+
const result = await planTurn(args.repo, query, opts);
|
|
3561
|
+
return formatPlanTurnResult(result);
|
|
3776
3562
|
},
|
|
3777
3563
|
},
|
|
3778
3564
|
];
|
|
@@ -3971,9 +3757,6 @@ export function registerTools(server, options) {
|
|
|
3971
3757
|
registerShortener("nextjs_route_map", { compact: formatNextjsRouteMapCompact, counts: formatNextjsRouteMapCounts });
|
|
3972
3758
|
registerShortener("nextjs_metadata_audit", { compact: formatNextjsMetadataAuditCompact, counts: formatNextjsMetadataAuditCounts });
|
|
3973
3759
|
registerShortener("framework_audit", { compact: formatFrameworkAuditCompact, counts: formatFrameworkAuditCounts });
|
|
3974
|
-
registerShortener("nextjs_audit_server_actions", { compact: formatServerActionsAuditCompact, counts: formatServerActionsAuditCounts });
|
|
3975
|
-
registerShortener("nextjs_api_contract", { compact: formatApiContractCompact, counts: formatApiContractCounts });
|
|
3976
|
-
registerShortener("nextjs_boundary_analyzer", { compact: formatBoundaryAnalyzerCompact, counts: formatBoundaryAnalyzerCounts });
|
|
3977
3760
|
registerShortener("get_session_context", {
|
|
3978
3761
|
compact: (raw) => {
|
|
3979
3762
|
const text = typeof raw === "string" ? raw : JSON.stringify(raw);
|