codesift-mcp 0.4.0 → 0.5.3
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 +30 -6
- 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 +1 -1
- package/dist/parser/parser-manager.d.ts.map +1 -1
- package/dist/parser/parser-manager.js +14 -5
- package/dist/parser/parser-manager.js.map +1 -1
- package/dist/parser/stub-languages.d.ts +2 -0
- package/dist/parser/stub-languages.d.ts.map +1 -0
- package/dist/parser/stub-languages.js +5 -0
- package/dist/parser/stub-languages.js.map +1 -0
- package/dist/register-tool-loaders.d.ts +130 -0
- package/dist/register-tool-loaders.d.ts.map +1 -0
- package/dist/register-tool-loaders.js +212 -0
- package/dist/register-tool-loaders.js.map +1 -0
- package/dist/register-tools.d.ts +2 -2
- package/dist/register-tools.d.ts.map +1 -1
- package/dist/register-tools.js +355 -634
- 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.d.ts.map +1 -1
- package/dist/server.js +23 -14
- 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 +3 -3
- 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
|
@@ -3,82 +3,13 @@ import { z } from "zod";
|
|
|
3
3
|
const zBool = () => z.union([z.boolean(), z.string().transform((s) => s === "true")]).optional();
|
|
4
4
|
import { wrapTool, registerShortener } from "./server-helpers.js";
|
|
5
5
|
import { detectProjectLanguagesSync } from "./utils/language-detect.js";
|
|
6
|
-
import {
|
|
7
|
-
import { STUB_LANGUAGES } from "./parser/parser-manager.js";
|
|
8
|
-
import { searchSymbols, searchText, semanticSearch } from "./tools/search-tools.js";
|
|
9
|
-
import { getFileTree, getFileOutline, getRepoOutline, suggestQueries } from "./tools/outline-tools.js";
|
|
10
|
-
import { getSymbol, getSymbols, findAndShow, findReferences, findReferencesBatch, findDeadCode, getContextBundle, formatRefsCompact, formatSymbolCompact, formatSymbolsCompact, formatBundleCompact } from "./tools/symbol-tools.js";
|
|
11
|
-
import { traceCallChain } from "./tools/graph-tools.js";
|
|
12
|
-
import { traceComponentTree, analyzeHooks, analyzeRenders, buildContextGraph, auditCompilerReadiness } from "./tools/react-tools.js";
|
|
13
|
-
import { impactAnalysis } from "./tools/impact-tools.js";
|
|
14
|
-
import { traceRoute } from "./tools/route-tools.js";
|
|
15
|
-
import { detectCommunities } from "./tools/community-tools.js";
|
|
16
|
-
import { assembleContext, getKnowledgeMap } from "./tools/context-tools.js";
|
|
17
|
-
import { diffOutline, changedSymbols } from "./tools/diff-tools.js";
|
|
18
|
-
import { generateClaudeMd } from "./tools/generate-tools.js";
|
|
19
|
-
import { codebaseRetrieval } from "./retrieval/codebase-retrieval.js";
|
|
20
|
-
import { analyzeComplexity } from "./tools/complexity-tools.js";
|
|
21
|
-
import { findClones } from "./tools/clone-tools.js";
|
|
22
|
-
import { analyzeHotspots } from "./tools/hotspot-tools.js";
|
|
23
|
-
import { crossRepoSearchSymbols, crossRepoFindReferences } from "./tools/cross-repo-tools.js";
|
|
24
|
-
import { searchPatterns, listPatterns } from "./tools/pattern-tools.js";
|
|
25
|
-
import { generateReport } from "./tools/report-tools.js";
|
|
6
|
+
import { STUB_LANGUAGES } from "./parser/stub-languages.js";
|
|
26
7
|
import { getUsageStats, formatUsageReport } from "./storage/usage-stats.js";
|
|
27
|
-
import { goToDefinition, getTypeInfo, renameSymbol, getCallHierarchy } from "./
|
|
28
|
-
import { indexConversations, searchConversations, searchAllConversations, findConversationsForSymbol } from "./tools/conversation-tools.js";
|
|
29
|
-
import { scanSecrets } from "./tools/secret-tools.js";
|
|
30
|
-
import { resolvePhpNamespace, analyzeActiveRecord, tracePhpEvent, findPhpViews, resolvePhpService, phpSecurityScan, phpProjectAudit, findPhpNPlusOne, findPhpGodModel, } from "./tools/php-tools.js";
|
|
31
|
-
import { consolidateMemories, readMemory } from "./tools/memory-tools.js";
|
|
32
|
-
import { createAnalysisPlan, writeScratchpad, readScratchpad, listScratchpad, updateStepStatus, getPlan, listPlans } from "./tools/coordinator-tools.js";
|
|
33
|
-
import { frequencyAnalysis } from "./tools/frequency-tools.js";
|
|
34
|
-
import { findExtensionFunctions, analyzeSealedHierarchy, traceSuspendChain, analyzeKmpDeclarations, traceFlowChain } from "./tools/kotlin-tools.js";
|
|
35
|
-
import { traceHiltGraph } from "./tools/hilt-tools.js";
|
|
36
|
-
import { traceComposeTree, analyzeComposeRecomposition } from "./tools/compose-tools.js";
|
|
37
|
-
import { traceRoomSchema } from "./tools/room-tools.js";
|
|
38
|
-
import { extractKotlinSerializationContract } from "./tools/serialization-tools.js";
|
|
39
|
-
import { astroAnalyzeIslands, astroHydrationAudit } from "./tools/astro-islands.js";
|
|
40
|
-
import { astroRouteMap } from "./tools/astro-routes.js";
|
|
41
|
-
import { analyzeNextjsComponents } from "./tools/nextjs-component-tools.js";
|
|
42
|
-
import { nextjsRouteMap } from "./tools/nextjs-route-tools.js";
|
|
43
|
-
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
|
-
import { frameworkAudit } from "./tools/nextjs-framework-audit-tools.js";
|
|
51
|
-
import { astroConfigAnalyze } from "./tools/astro-config.js";
|
|
52
|
-
import { analyzeProject, getExtractorVersions } from "./tools/project-tools.js";
|
|
53
|
-
import { getModelGraph } from "./tools/model-tools.js";
|
|
54
|
-
import { getTestFixtures } from "./tools/pytest-tools.js";
|
|
55
|
-
import { findFrameworkWiring } from "./tools/wiring-tools.js";
|
|
56
|
-
import { runRuff } from "./tools/ruff-tools.js";
|
|
57
|
-
import { parsePyproject } from "./tools/pyproject-tools.js";
|
|
58
|
-
import { findPythonCallers } from "./tools/python-callers.js";
|
|
59
|
-
import { analyzeDjangoSettings } from "./tools/django-settings.js";
|
|
60
|
-
import { traceCeleryChain } from "./tools/celery-tools.js";
|
|
61
|
-
import { runMypy, runPyright } from "./tools/typecheck-tools.js";
|
|
62
|
-
import { analyzePythonDeps } from "./tools/python-deps-analyzer.js";
|
|
63
|
-
import { findPythonCircularImports } from "./tools/python-circular-imports.js";
|
|
64
|
-
import { reviewDiff } from "./tools/review-diff-tools.js";
|
|
65
|
-
import { auditScan } from "./tools/audit-tools.js";
|
|
66
|
-
import { indexStatus } from "./tools/status-tools.js";
|
|
67
|
-
import { auditAgentConfig } from "./tools/agent-config-tools.js";
|
|
68
|
-
import { testImpactAnalysis } from "./tools/test-impact-tools.js";
|
|
69
|
-
import { dependencyAudit } from "./tools/dependency-audit-tools.js";
|
|
70
|
-
import { migrationLint } from "./tools/migration-lint-tools.js";
|
|
71
|
-
import { analyzePrismaSchema } from "./tools/prisma-schema-tools.js";
|
|
72
|
-
import { findPerfHotspots } from "./tools/perf-tools.js";
|
|
73
|
-
import { fanInFanOut, coChangeAnalysis } from "./tools/coupling-tools.js";
|
|
74
|
-
import { architectureSummary } from "./tools/architecture-tools.js";
|
|
75
|
-
import { nestLifecycleMap, nestModuleGraph, nestDIGraph, nestGuardChain, nestRouteInventory, nestAudit } from "./tools/nest-tools.js";
|
|
76
|
-
import { nestGraphQLMap, nestWebSocketMap, nestScheduleMap, nestTypeOrmMap, nestMicroserviceMap } from "./tools/nest-ext-tools.js";
|
|
77
|
-
import { explainQuery } from "./tools/query-tools.js";
|
|
8
|
+
import { indexFolder, indexFile, indexRepo, listAllRepos, invalidateCache, getCodeIndex, searchSymbols, searchText, semanticSearch, getFileTree, getFileOutline, getRepoOutline, suggestQueries, getSymbol, getSymbols, findAndShow, findReferences, findReferencesBatch, findDeadCode, getContextBundle, formatRefsCompact, formatSymbolCompact, formatSymbolsCompact, formatBundleCompact, traceCallChain, traceComponentTree, analyzeHooks, analyzeRenders, buildContextGraph, auditCompilerReadiness, reactQuickstart, impactAnalysis, traceRoute, detectCommunities, assembleContext, getKnowledgeMap, diffOutline, changedSymbols, generateClaudeMd, codebaseRetrieval, analyzeComplexity, findClones, analyzeHotspots, crossRepoSearchSymbols, crossRepoFindReferences, searchPatterns, listPatterns, generateReport, goToDefinition, getTypeInfo, renameSymbol, getCallHierarchy, indexConversations, searchConversations, searchAllConversations, findConversationsForSymbol, scanSecrets, resolvePhpNamespace, tracePhpEvent, findPhpViews, resolvePhpService, phpSecurityScan, phpProjectAudit, consolidateMemories, readMemory, createAnalysisPlan, writeScratchpad, readScratchpad, listScratchpad, updateStepStatus, getPlan, listPlans, frequencyAnalysis, findExtensionFunctions, analyzeSealedHierarchy, traceSuspendChain, analyzeKmpDeclarations, traceFlowChain, traceHiltGraph, traceComposeTree, analyzeComposeRecomposition, traceRoomSchema, extractKotlinSerializationContract, astroAnalyzeIslands, astroHydrationAudit, astroRouteMap, astroActionsAudit, astroAudit, nextjsRouteMap, nextjsMetadataAudit, frameworkAudit, astroConfigAnalyze, astroContentCollections, analyzeProject, getExtractorVersions, getModelGraph, getTestFixtures, findFrameworkWiring, runRuff, parsePyproject, resolveConstantValue, effectiveDjangoViewSecurity, findPythonCallers, taintTrace, analyzeDjangoSettings, runMypy, runPyright, analyzePythonDeps, pythonAudit, traceFastAPIDepends, analyzeAsyncCorrectness, getPydanticModels, reviewDiff, auditScan, indexStatus, auditAgentConfig, testImpactAnalysis, dependencyAudit, migrationLint, planTurn, formatPlanTurnResult, astroMigrationCheck, analyzePrismaSchema, findPerfHotspots, fanInFanOut, coChangeAnalysis, architectureSummary, nestAudit, explainQuery, } from "./register-tool-loaders.js";
|
|
78
9
|
import { formatSnapshot, getContext, getSessionState } from "./storage/session-state.js";
|
|
79
10
|
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
|
|
11
|
+
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";
|
|
12
|
+
import { formatNextjsRouteMapCompact, formatNextjsRouteMapCounts, formatNextjsMetadataAuditCompact, formatNextjsMetadataAuditCounts, formatFrameworkAuditCompact, formatFrameworkAuditCounts } from "./formatters-shortening.js";
|
|
82
13
|
const zFiniteNumber = z.number().finite();
|
|
83
14
|
/** Coerce string→number for numeric params while rejecting NaN/empty strings. */
|
|
84
15
|
export const zNum = () => z.union([
|
|
@@ -167,19 +98,7 @@ export function getToolHandle(name) {
|
|
|
167
98
|
/** Framework-specific tool bundles — auto-enabled when the framework is detected in an indexed repo */
|
|
168
99
|
const FRAMEWORK_TOOL_BUNDLES = {
|
|
169
100
|
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
|
|
101
|
+
// All NestJS sub-tools absorbed into nest_audit
|
|
183
102
|
],
|
|
184
103
|
};
|
|
185
104
|
/** Track which framework bundles have been auto-enabled this session (avoid repeat work) */
|
|
@@ -217,14 +136,12 @@ const FRAMEWORK_TOOL_GROUPS = {
|
|
|
217
136
|
// PHP / Yii2 / Laravel — detected by composer.json
|
|
218
137
|
"composer.json": [
|
|
219
138
|
"resolve_php_namespace",
|
|
220
|
-
|
|
139
|
+
// analyze_activerecord, find_php_n_plus_one, find_php_god_model absorbed into php_project_audit
|
|
221
140
|
"trace_php_event",
|
|
222
141
|
"find_php_views",
|
|
223
142
|
"resolve_php_service",
|
|
224
143
|
"php_security_scan",
|
|
225
144
|
"php_project_audit",
|
|
226
|
-
"find_php_n_plus_one",
|
|
227
|
-
"find_php_god_model",
|
|
228
145
|
],
|
|
229
146
|
// Kotlin / Android / Gradle — detected by build.gradle.kts or settings.gradle.kts
|
|
230
147
|
"build.gradle.kts": [
|
|
@@ -277,6 +194,7 @@ const REACT_TOOLS = [
|
|
|
277
194
|
"analyze_renders",
|
|
278
195
|
"analyze_context_graph",
|
|
279
196
|
"audit_compiler_readiness",
|
|
197
|
+
"react_quickstart",
|
|
280
198
|
];
|
|
281
199
|
/**
|
|
282
200
|
* Hono-specific tools — auto-enabled when a Hono project is detected.
|
|
@@ -287,20 +205,6 @@ const REACT_TOOLS = [
|
|
|
287
205
|
* Detection: package.json with "hono" OR "@hono/zod-openapi" dep.
|
|
288
206
|
* Content-based (not filename), so lives outside FRAMEWORK_TOOL_GROUPS.
|
|
289
207
|
*/
|
|
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
208
|
const HONO_TOOLS = [
|
|
305
209
|
"trace_context_flow",
|
|
306
210
|
"extract_api_contract",
|
|
@@ -308,10 +212,8 @@ const HONO_TOOLS = [
|
|
|
308
212
|
"audit_hono_security",
|
|
309
213
|
"visualize_hono_routes",
|
|
310
214
|
// Phase 2 additions — closes blog-API demo gaps + GitHub issues #3587/#4121/#4270
|
|
311
|
-
"trace_conditional_middleware",
|
|
312
215
|
"analyze_inline_handler",
|
|
313
216
|
"extract_response_types",
|
|
314
|
-
"detect_middleware_env_regression",
|
|
315
217
|
"detect_hono_modules",
|
|
316
218
|
"find_dead_hono_routes",
|
|
317
219
|
];
|
|
@@ -351,11 +253,6 @@ export async function detectAutoLoadTools(cwd) {
|
|
|
351
253
|
if (hasHono) {
|
|
352
254
|
toEnable.push(...HONO_TOOLS);
|
|
353
255
|
}
|
|
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
256
|
}
|
|
360
257
|
catch { /* malformed package.json */ }
|
|
361
258
|
}
|
|
@@ -504,15 +401,20 @@ export const CORE_TOOL_NAMES = new Set([
|
|
|
504
401
|
"index_folder", // repo onboarding
|
|
505
402
|
"discover_tools", // meta: discovers remaining hidden tools
|
|
506
403
|
"describe_tools", // meta: full schema for hidden tools
|
|
404
|
+
"plan_turn", // meta: route query to best tools/symbols/files
|
|
507
405
|
"get_session_snapshot", // session: compaction survival
|
|
508
406
|
"analyze_project", // project profile
|
|
509
407
|
"get_extractor_versions", // cache invalidation
|
|
510
408
|
"index_status", // meta: check if repo is indexed
|
|
511
|
-
// --- Astro tools ---
|
|
409
|
+
// --- Astro tools (7 core) ---
|
|
512
410
|
"astro_analyze_islands",
|
|
513
|
-
|
|
411
|
+
// astro_hydration_audit: discoverable — use astro_audit for full check or call directly
|
|
514
412
|
"astro_route_map",
|
|
515
413
|
"astro_config_analyze",
|
|
414
|
+
"astro_actions_audit",
|
|
415
|
+
"astro_migration_check",
|
|
416
|
+
"astro_content_collections",
|
|
417
|
+
"astro_audit",
|
|
516
418
|
// --- Hono tools (Task 23) ---
|
|
517
419
|
"trace_middleware_chain", // core: top Hono pain point (Discussion #4255)
|
|
518
420
|
"analyze_hono_app", // core: meta-tool, first call for any Hono project
|
|
@@ -605,12 +507,13 @@ const TOOL_DEFINITIONS = [
|
|
|
605
507
|
category: "search",
|
|
606
508
|
searchHint: "search find symbols functions classes types methods by name signature",
|
|
607
509
|
outputSchema: OutputSchemas.searchResults,
|
|
608
|
-
description: "Search symbols by name/signature. detail_level: compact (~15 tok), standard (default), full.",
|
|
510
|
+
description: "Search symbols by name/signature. Supports kind, file, and decorator filters. detail_level: compact (~15 tok), standard (default), full.",
|
|
609
511
|
schema: {
|
|
610
512
|
repo: z.string().optional().describe("Repository identifier (default: auto-detected from CWD)"),
|
|
611
513
|
query: z.string().describe("Search query string"),
|
|
612
514
|
kind: z.string().optional().describe("Filter by symbol kind (function, class, etc.)"),
|
|
613
515
|
file_pattern: z.string().optional().describe("Glob pattern to filter files"),
|
|
516
|
+
decorator: z.string().optional().describe("Filter by decorator metadata, e.g. login_required, @dataclass, router.get"),
|
|
614
517
|
include_source: zBool().describe("Include full source code of each symbol"),
|
|
615
518
|
top_k: zNum().describe("Maximum number of results to return (default 50)"),
|
|
616
519
|
source_chars: zNum().describe("Truncate each symbol's source to N characters (reduces output size)"),
|
|
@@ -622,6 +525,7 @@ const TOOL_DEFINITIONS = [
|
|
|
622
525
|
const results = await searchSymbols(args.repo, args.query, {
|
|
623
526
|
kind: args.kind,
|
|
624
527
|
file_pattern: args.file_pattern,
|
|
528
|
+
decorator: args.decorator,
|
|
625
529
|
include_source: args.include_source,
|
|
626
530
|
top_k: args.top_k,
|
|
627
531
|
source_chars: args.source_chars,
|
|
@@ -798,7 +702,7 @@ const TOOL_DEFINITIONS = [
|
|
|
798
702
|
const hint = await checkTextStubHint(args.repo, "get_symbol", true);
|
|
799
703
|
return hint ?? null;
|
|
800
704
|
}
|
|
801
|
-
let text = formatSymbolCompact(result.symbol);
|
|
705
|
+
let text = await formatSymbolCompact(result.symbol);
|
|
802
706
|
if (result.related && result.related.length > 0) {
|
|
803
707
|
text += "\n\n--- children ---\n" + result.related.map((s) => `${s.kind} ${s.name}${s.signature ? s.signature : ""} [${s.file}:${s.start_line}]`).join("\n");
|
|
804
708
|
}
|
|
@@ -819,7 +723,7 @@ const TOOL_DEFINITIONS = [
|
|
|
819
723
|
},
|
|
820
724
|
handler: async (args) => {
|
|
821
725
|
const syms = await getSymbols(args.repo, args.symbol_ids);
|
|
822
|
-
const output = formatSymbolsCompact(syms);
|
|
726
|
+
const output = await formatSymbolsCompact(syms);
|
|
823
727
|
const hint = await checkTextStubHint(args.repo, "get_symbols", syms.length === 0);
|
|
824
728
|
return hint ? hint + output : output;
|
|
825
729
|
},
|
|
@@ -838,9 +742,9 @@ const TOOL_DEFINITIONS = [
|
|
|
838
742
|
const result = await findAndShow(args.repo, args.query, args.include_refs);
|
|
839
743
|
if (!result)
|
|
840
744
|
return null;
|
|
841
|
-
let text = formatSymbolCompact(result.symbol);
|
|
745
|
+
let text = await formatSymbolCompact(result.symbol);
|
|
842
746
|
if (result.references) {
|
|
843
|
-
text += `\n\n--- references ---\n${formatRefsCompact(result.references)}`;
|
|
747
|
+
text += `\n\n--- references ---\n${await formatRefsCompact(result.references)}`;
|
|
844
748
|
}
|
|
845
749
|
return text;
|
|
846
750
|
},
|
|
@@ -881,7 +785,7 @@ const TOOL_DEFINITIONS = [
|
|
|
881
785
|
return findReferencesBatch(args.repo, names, args.file_pattern);
|
|
882
786
|
}
|
|
883
787
|
const refs = await findReferences(args.repo, args.symbol_name, args.file_pattern);
|
|
884
|
-
const output = formatRefsCompact(refs);
|
|
788
|
+
const output = await formatRefsCompact(refs);
|
|
885
789
|
const hint = await checkTextStubHint(args.repo, "find_references", refs.length === 0);
|
|
886
790
|
return hint ? hint + output : output;
|
|
887
791
|
},
|
|
@@ -1017,7 +921,7 @@ const TOOL_DEFINITIONS = [
|
|
|
1017
921
|
const index = await getCodeIndex(args.repo);
|
|
1018
922
|
if (!index)
|
|
1019
923
|
throw new Error(`Repository not found: ${args.repo}`);
|
|
1020
|
-
const result = buildContextGraph(index.symbols);
|
|
924
|
+
const result = await buildContextGraph(index.symbols);
|
|
1021
925
|
return JSON.stringify(result, null, 2);
|
|
1022
926
|
},
|
|
1023
927
|
},
|
|
@@ -1039,6 +943,19 @@ const TOOL_DEFINITIONS = [
|
|
|
1039
943
|
return JSON.stringify(result, null, 2);
|
|
1040
944
|
},
|
|
1041
945
|
},
|
|
946
|
+
{
|
|
947
|
+
name: "react_quickstart",
|
|
948
|
+
category: "analysis",
|
|
949
|
+
searchHint: "react onboarding day-1 overview stack inventory components hooks critical issues",
|
|
950
|
+
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.",
|
|
951
|
+
schema: {
|
|
952
|
+
repo: z.string().optional().describe("Repository identifier (default: auto-detected from CWD)"),
|
|
953
|
+
},
|
|
954
|
+
handler: async (args) => {
|
|
955
|
+
const result = await reactQuickstart(args.repo);
|
|
956
|
+
return JSON.stringify(result, null, 2);
|
|
957
|
+
},
|
|
958
|
+
},
|
|
1042
959
|
{
|
|
1043
960
|
name: "trace_route",
|
|
1044
961
|
category: "graph",
|
|
@@ -1886,6 +1803,87 @@ const TOOL_DEFINITIONS = [
|
|
|
1886
1803
|
schema: { repo: z.string().optional().describe("Repository identifier (default: auto-detected from CWD)") },
|
|
1887
1804
|
handler: async (args) => { return await parsePyproject(args.repo); },
|
|
1888
1805
|
},
|
|
1806
|
+
{
|
|
1807
|
+
name: "resolve_constant_value",
|
|
1808
|
+
category: "analysis",
|
|
1809
|
+
searchHint: "python typescript nestjs resolve constant value literal alias import default parameter propagation",
|
|
1810
|
+
description: "Resolve Python or TypeScript constants and function default values through simple aliases and import chains. Returns literals or explicit unresolved reasons.",
|
|
1811
|
+
schema: {
|
|
1812
|
+
repo: z.string().optional().describe("Repository identifier (default: auto-detected from CWD)"),
|
|
1813
|
+
symbol_name: z.string().describe("Constant, function, or method name to resolve"),
|
|
1814
|
+
file_pattern: z.string().optional().describe("Filter candidate symbols by file path substring"),
|
|
1815
|
+
language: z.enum(["python", "typescript"]).optional().describe("Force resolver language instead of auto-inference"),
|
|
1816
|
+
max_depth: zFiniteNumber.optional().describe("Maximum alias/import resolution depth (default: 8)"),
|
|
1817
|
+
},
|
|
1818
|
+
handler: async (args) => {
|
|
1819
|
+
const opts = {};
|
|
1820
|
+
if (args.file_pattern != null)
|
|
1821
|
+
opts.file_pattern = args.file_pattern;
|
|
1822
|
+
if (args.language != null)
|
|
1823
|
+
opts.language = args.language;
|
|
1824
|
+
if (args.max_depth != null)
|
|
1825
|
+
opts.max_depth = args.max_depth;
|
|
1826
|
+
return await resolveConstantValue(args.repo, args.symbol_name, opts);
|
|
1827
|
+
},
|
|
1828
|
+
},
|
|
1829
|
+
{
|
|
1830
|
+
name: "effective_django_view_security",
|
|
1831
|
+
category: "security",
|
|
1832
|
+
requiresLanguage: "python",
|
|
1833
|
+
searchHint: "python django view auth csrf login_required middleware mixin route security posture",
|
|
1834
|
+
description: "Assess effective Django view security from decorators, mixins, settings middleware, and optional route resolution.",
|
|
1835
|
+
schema: {
|
|
1836
|
+
repo: z.string().optional().describe("Repository identifier (default: auto-detected from CWD)"),
|
|
1837
|
+
path: z.string().optional().describe("Django route path to resolve first, e.g. /settings/"),
|
|
1838
|
+
symbol_name: z.string().optional().describe("View function/class/method name when you already know the symbol"),
|
|
1839
|
+
file_pattern: z.string().optional().describe("Filter candidate symbols by file path substring"),
|
|
1840
|
+
settings_file: z.string().optional().describe("Explicit Django settings file path (auto-detects if omitted)"),
|
|
1841
|
+
},
|
|
1842
|
+
handler: async (args) => {
|
|
1843
|
+
const opts = {};
|
|
1844
|
+
if (args.path != null)
|
|
1845
|
+
opts.path = args.path;
|
|
1846
|
+
if (args.symbol_name != null)
|
|
1847
|
+
opts.symbol_name = args.symbol_name;
|
|
1848
|
+
if (args.file_pattern != null)
|
|
1849
|
+
opts.file_pattern = args.file_pattern;
|
|
1850
|
+
if (args.settings_file != null)
|
|
1851
|
+
opts.settings_file = args.settings_file;
|
|
1852
|
+
return await effectiveDjangoViewSecurity(args.repo, opts);
|
|
1853
|
+
},
|
|
1854
|
+
},
|
|
1855
|
+
{
|
|
1856
|
+
name: "taint_trace",
|
|
1857
|
+
category: "security",
|
|
1858
|
+
requiresLanguage: "python",
|
|
1859
|
+
searchHint: "python django taint data flow source sink request get post redirect mark_safe cursor execute subprocess session trace",
|
|
1860
|
+
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.",
|
|
1861
|
+
schema: {
|
|
1862
|
+
repo: z.string().optional().describe("Repository identifier (default: auto-detected from CWD)"),
|
|
1863
|
+
framework: z.enum(["python-django"]).optional().describe("Currently only python-django is implemented"),
|
|
1864
|
+
file_pattern: z.string().optional().describe("Restrict analysis to matching Python files"),
|
|
1865
|
+
source_patterns: z.array(z.string()).optional().describe("Optional source pattern allowlist (defaults to request.* presets)"),
|
|
1866
|
+
sink_patterns: z.array(z.string()).optional().describe("Optional sink pattern allowlist (defaults to built-in security sinks)"),
|
|
1867
|
+
max_depth: zFiniteNumber.optional().describe("Maximum interprocedural helper depth (default: 4)"),
|
|
1868
|
+
max_traces: zFiniteNumber.optional().describe("Maximum traces to return before truncation (default: 50)"),
|
|
1869
|
+
},
|
|
1870
|
+
handler: async (args) => {
|
|
1871
|
+
const opts = {};
|
|
1872
|
+
if (args.framework != null)
|
|
1873
|
+
opts.framework = args.framework;
|
|
1874
|
+
if (args.file_pattern != null)
|
|
1875
|
+
opts.file_pattern = args.file_pattern;
|
|
1876
|
+
if (args.source_patterns != null)
|
|
1877
|
+
opts.source_patterns = args.source_patterns;
|
|
1878
|
+
if (args.sink_patterns != null)
|
|
1879
|
+
opts.sink_patterns = args.sink_patterns;
|
|
1880
|
+
if (args.max_depth != null)
|
|
1881
|
+
opts.max_depth = args.max_depth;
|
|
1882
|
+
if (args.max_traces != null)
|
|
1883
|
+
opts.max_traces = args.max_traces;
|
|
1884
|
+
return await taintTrace(args.repo, opts);
|
|
1885
|
+
},
|
|
1886
|
+
},
|
|
1889
1887
|
{
|
|
1890
1888
|
name: "find_python_callers",
|
|
1891
1889
|
category: "analysis",
|
|
@@ -1927,26 +1925,6 @@ const TOOL_DEFINITIONS = [
|
|
|
1927
1925
|
return await analyzeDjangoSettings(args.repo, opts);
|
|
1928
1926
|
},
|
|
1929
1927
|
},
|
|
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
1928
|
{
|
|
1951
1929
|
name: "run_mypy",
|
|
1952
1930
|
category: "analysis",
|
|
@@ -2014,58 +1992,104 @@ const TOOL_DEFINITIONS = [
|
|
|
2014
1992
|
},
|
|
2015
1993
|
},
|
|
2016
1994
|
{
|
|
2017
|
-
name: "
|
|
1995
|
+
name: "trace_fastapi_depends",
|
|
2018
1996
|
category: "analysis",
|
|
2019
1997
|
requiresLanguage: "python",
|
|
2020
|
-
searchHint: "python
|
|
2021
|
-
description: "
|
|
1998
|
+
searchHint: "python fastapi depends dependency injection security scopes oauth2 authentication auth endpoint",
|
|
1999
|
+
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
2000
|
schema: {
|
|
2023
2001
|
repo: z.string().optional().describe("Repository identifier (default: auto-detected from CWD)"),
|
|
2024
2002
|
file_pattern: z.string().optional().describe("Filter by file path substring"),
|
|
2025
|
-
|
|
2003
|
+
endpoint: z.string().optional().describe("Focus on a specific endpoint function name"),
|
|
2004
|
+
max_depth: zFiniteNumber.optional().describe("Max dependency tree depth (default: 5)"),
|
|
2026
2005
|
},
|
|
2027
2006
|
handler: async (args) => {
|
|
2028
2007
|
const opts = {};
|
|
2029
2008
|
if (args.file_pattern != null)
|
|
2030
2009
|
opts.file_pattern = args.file_pattern;
|
|
2031
|
-
if (args.
|
|
2032
|
-
opts.
|
|
2033
|
-
|
|
2010
|
+
if (args.endpoint != null)
|
|
2011
|
+
opts.endpoint = args.endpoint;
|
|
2012
|
+
if (args.max_depth != null)
|
|
2013
|
+
opts.max_depth = args.max_depth;
|
|
2014
|
+
return await traceFastAPIDepends(args.repo, opts);
|
|
2034
2015
|
},
|
|
2035
2016
|
},
|
|
2036
|
-
// --- PHP / Yii2 tools (all discoverable via discover_tools(query="php")) ---
|
|
2037
2017
|
{
|
|
2038
|
-
name: "
|
|
2018
|
+
name: "analyze_async_correctness",
|
|
2039
2019
|
category: "analysis",
|
|
2040
|
-
requiresLanguage: "
|
|
2041
|
-
searchHint: "
|
|
2042
|
-
description: "
|
|
2020
|
+
requiresLanguage: "python",
|
|
2021
|
+
searchHint: "python async await asyncio blocking sync requests sleep subprocess django sqlalchemy ORM coroutine fastapi",
|
|
2022
|
+
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
2023
|
schema: {
|
|
2044
2024
|
repo: z.string().optional().describe("Repository identifier (default: auto-detected from CWD)"),
|
|
2045
|
-
|
|
2025
|
+
file_pattern: z.string().optional().describe("Filter by file path substring"),
|
|
2026
|
+
rules: z.array(z.string()).optional().describe("Subset of rules to run"),
|
|
2027
|
+
max_results: zFiniteNumber.optional().describe("Max findings (default: 200)"),
|
|
2046
2028
|
},
|
|
2047
2029
|
handler: async (args) => {
|
|
2048
|
-
|
|
2030
|
+
const opts = {};
|
|
2031
|
+
if (args.file_pattern != null)
|
|
2032
|
+
opts.file_pattern = args.file_pattern;
|
|
2033
|
+
if (args.rules != null)
|
|
2034
|
+
opts.rules = args.rules;
|
|
2035
|
+
if (args.max_results != null)
|
|
2036
|
+
opts.max_results = args.max_results;
|
|
2037
|
+
return await analyzeAsyncCorrectness(args.repo, opts);
|
|
2049
2038
|
},
|
|
2050
2039
|
},
|
|
2051
2040
|
{
|
|
2052
|
-
name: "
|
|
2041
|
+
name: "get_pydantic_models",
|
|
2053
2042
|
category: "analysis",
|
|
2054
|
-
requiresLanguage: "
|
|
2055
|
-
searchHint: "
|
|
2056
|
-
description: "Extract
|
|
2043
|
+
requiresLanguage: "python",
|
|
2044
|
+
searchHint: "python pydantic basemodel fastapi schema request response contract validator field constraint type classdiagram",
|
|
2045
|
+
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
2046
|
schema: {
|
|
2058
2047
|
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
2048
|
file_pattern: z.string().optional().describe("Filter by file path substring"),
|
|
2049
|
+
output_format: z.enum(["json", "mermaid"]).optional().describe("Output as structured JSON or mermaid classDiagram"),
|
|
2061
2050
|
},
|
|
2062
2051
|
handler: async (args) => {
|
|
2063
2052
|
const opts = {};
|
|
2064
|
-
if (
|
|
2065
|
-
opts.model_name = args.model_name;
|
|
2066
|
-
if (typeof args.file_pattern === "string")
|
|
2053
|
+
if (args.file_pattern != null)
|
|
2067
2054
|
opts.file_pattern = args.file_pattern;
|
|
2068
|
-
|
|
2055
|
+
if (args.output_format != null)
|
|
2056
|
+
opts.output_format = args.output_format;
|
|
2057
|
+
return await getPydanticModels(args.repo, opts);
|
|
2058
|
+
},
|
|
2059
|
+
},
|
|
2060
|
+
{
|
|
2061
|
+
name: "python_audit",
|
|
2062
|
+
category: "analysis",
|
|
2063
|
+
requiresLanguage: "python",
|
|
2064
|
+
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",
|
|
2065
|
+
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.",
|
|
2066
|
+
schema: {
|
|
2067
|
+
repo: z.string().optional().describe("Repository identifier (default: auto-detected from CWD)"),
|
|
2068
|
+
file_pattern: z.string().optional().describe("Filter by file path substring"),
|
|
2069
|
+
checks: z.array(z.string()).optional().describe("Subset of checks: circular_imports, django_settings, anti_patterns, framework_wiring, celery, pytest_fixtures, dependencies, dead_code"),
|
|
2070
|
+
},
|
|
2071
|
+
handler: async (args) => {
|
|
2072
|
+
const opts = {};
|
|
2073
|
+
if (args.file_pattern != null)
|
|
2074
|
+
opts.file_pattern = args.file_pattern;
|
|
2075
|
+
if (args.checks != null)
|
|
2076
|
+
opts.checks = args.checks;
|
|
2077
|
+
return await pythonAudit(args.repo, opts);
|
|
2078
|
+
},
|
|
2079
|
+
},
|
|
2080
|
+
// --- PHP / Yii2 tools (all discoverable via discover_tools(query="php")) ---
|
|
2081
|
+
{
|
|
2082
|
+
name: "resolve_php_namespace",
|
|
2083
|
+
category: "analysis",
|
|
2084
|
+
requiresLanguage: "php",
|
|
2085
|
+
searchHint: "php namespace resolve PSR-4 autoload composer class file path yii2 laravel symfony",
|
|
2086
|
+
description: "Resolve a PHP FQCN to file path via composer.json PSR-4 autoload mapping.",
|
|
2087
|
+
schema: {
|
|
2088
|
+
repo: z.string().optional().describe("Repository identifier (default: auto-detected from CWD)"),
|
|
2089
|
+
class_name: z.string().describe("Fully-qualified class name, e.g. 'App\\\\Models\\\\User'"),
|
|
2090
|
+
},
|
|
2091
|
+
handler: async (args) => {
|
|
2092
|
+
return await resolvePhpNamespace(args.repo, args.class_name);
|
|
2069
2093
|
},
|
|
2070
2094
|
},
|
|
2071
2095
|
{
|
|
@@ -2143,62 +2167,23 @@ const TOOL_DEFINITIONS = [
|
|
|
2143
2167
|
name: "php_project_audit",
|
|
2144
2168
|
category: "analysis",
|
|
2145
2169
|
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.",
|
|
2170
|
+
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",
|
|
2171
|
+
description: "Compound PHP project audit: security scan + ActiveRecord analysis + N+1 detection + god model detection + health score. Runs checks in parallel.",
|
|
2148
2172
|
schema: {
|
|
2149
2173
|
repo: z.string().optional().describe("Repository identifier (default: auto-detected from CWD)"),
|
|
2150
2174
|
file_pattern: z.string().optional().describe("Glob pattern to filter analyzed files"),
|
|
2175
|
+
checks: z.string().optional().describe("Comma-separated checks: n_plus_one, god_model, activerecord, security, events, views, services, namespace. Default: all"),
|
|
2151
2176
|
},
|
|
2152
2177
|
handler: async (args) => {
|
|
2153
2178
|
const opts = {};
|
|
2154
2179
|
if (typeof args.file_pattern === "string")
|
|
2155
2180
|
opts.file_pattern = args.file_pattern;
|
|
2181
|
+
if (typeof args.checks === "string" && args.checks.trim()) {
|
|
2182
|
+
opts.checks = args.checks.split(",").map((c) => c.trim()).filter(Boolean);
|
|
2183
|
+
}
|
|
2156
2184
|
return await phpProjectAudit(args.repo, opts);
|
|
2157
2185
|
},
|
|
2158
2186
|
},
|
|
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
2187
|
// --- Memory consolidation ---
|
|
2203
2188
|
{
|
|
2204
2189
|
name: "consolidate_memories",
|
|
@@ -2386,7 +2371,10 @@ const TOOL_DEFINITIONS = [
|
|
|
2386
2371
|
schema: {},
|
|
2387
2372
|
handler: async () => {
|
|
2388
2373
|
const stats = await getUsageStats();
|
|
2389
|
-
|
|
2374
|
+
const { createRequire } = await import("node:module");
|
|
2375
|
+
const req = createRequire(import.meta.url);
|
|
2376
|
+
const pkgVersion = req("../package.json").version;
|
|
2377
|
+
return { version: pkgVersion, report: formatUsageReport(stats) };
|
|
2390
2378
|
},
|
|
2391
2379
|
},
|
|
2392
2380
|
// ── Session context tools ───────────────────────────────────────────────
|
|
@@ -2635,66 +2623,11 @@ const TOOL_DEFINITIONS = [
|
|
|
2635
2623
|
return parts.join("\n");
|
|
2636
2624
|
},
|
|
2637
2625
|
},
|
|
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
|
-
},
|
|
2626
|
+
// --- NestJS analysis tools (sub-tools absorbed into nest_audit) ---
|
|
2694
2627
|
{
|
|
2695
2628
|
name: "nest_audit",
|
|
2696
2629
|
category: "nestjs",
|
|
2697
|
-
searchHint: "nestjs audit analysis comprehensive module di guard route lifecycle pattern graphql websocket schedule typeorm microservice",
|
|
2630
|
+
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
2631
|
description: "One-call NestJS architecture audit: modules, DI, guards, routes, lifecycle, patterns, GraphQL, WebSocket, schedule, TypeORM, microservices.",
|
|
2699
2632
|
schema: {
|
|
2700
2633
|
repo: z.string().optional().describe("Repository identifier (default: auto-detected from CWD)"),
|
|
@@ -2705,63 +2638,6 @@ const TOOL_DEFINITIONS = [
|
|
|
2705
2638
|
return nestAudit(args.repo ?? "", checks ? { checks } : undefined);
|
|
2706
2639
|
},
|
|
2707
2640
|
},
|
|
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
2641
|
// --- Agent config audit ---
|
|
2766
2642
|
{
|
|
2767
2643
|
name: "audit_agent_config",
|
|
@@ -3007,6 +2883,7 @@ const TOOL_DEFINITIONS = [
|
|
|
3007
2883
|
repo: z.string().optional().describe("Repository identifier (default: auto-detected from CWD)"),
|
|
3008
2884
|
severity: z.enum(["all", "warnings", "errors"]).default("all").describe("Filter issues by severity (default: all)"),
|
|
3009
2885
|
path_prefix: z.string().optional().describe("Only scan files under this path prefix"),
|
|
2886
|
+
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
2887
|
},
|
|
3011
2888
|
handler: async (args) => {
|
|
3012
2889
|
const opts = {};
|
|
@@ -3016,6 +2893,8 @@ const TOOL_DEFINITIONS = [
|
|
|
3016
2893
|
opts.severity = args.severity;
|
|
3017
2894
|
if (args.path_prefix != null)
|
|
3018
2895
|
opts.path_prefix = args.path_prefix;
|
|
2896
|
+
if (args.fail_on != null)
|
|
2897
|
+
opts.fail_on = args.fail_on;
|
|
3019
2898
|
return await astroHydrationAudit(opts);
|
|
3020
2899
|
},
|
|
3021
2900
|
},
|
|
@@ -3055,20 +2934,82 @@ const TOOL_DEFINITIONS = [
|
|
|
3055
2934
|
return await astroConfigAnalyze({ project_root: index.root });
|
|
3056
2935
|
},
|
|
3057
2936
|
},
|
|
2937
|
+
{
|
|
2938
|
+
name: "astro_actions_audit",
|
|
2939
|
+
category: "analysis",
|
|
2940
|
+
searchHint: "astro actions defineAction zod refine passthrough multipart file enctype audit",
|
|
2941
|
+
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.",
|
|
2942
|
+
schema: {
|
|
2943
|
+
repo: z.string().optional().describe("Repository identifier (default: auto-detected from CWD)"),
|
|
2944
|
+
severity: z.enum(["all", "warnings", "errors"]).default("all").describe("Filter issues by severity (default: all)"),
|
|
2945
|
+
},
|
|
2946
|
+
handler: async (args) => {
|
|
2947
|
+
const opts = {};
|
|
2948
|
+
if (args.repo != null)
|
|
2949
|
+
opts.repo = args.repo;
|
|
2950
|
+
if (args.severity != null)
|
|
2951
|
+
opts.severity = args.severity;
|
|
2952
|
+
return await astroActionsAudit(opts);
|
|
2953
|
+
},
|
|
2954
|
+
},
|
|
2955
|
+
{
|
|
2956
|
+
name: "astro_content_collections",
|
|
2957
|
+
category: "analysis",
|
|
2958
|
+
searchHint: "astro content collections defineCollection zod schema reference glob loader frontmatter",
|
|
2959
|
+
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.",
|
|
2960
|
+
schema: {
|
|
2961
|
+
repo: z.string().optional().describe("Repository identifier (default: auto-detected from CWD)"),
|
|
2962
|
+
validate_entries: z.boolean().default(true).describe("Validate entry frontmatter against required schema fields (default: true)"),
|
|
2963
|
+
},
|
|
2964
|
+
handler: async (args) => {
|
|
2965
|
+
const index = await getCodeIndex(args.repo ?? "");
|
|
2966
|
+
if (!index)
|
|
2967
|
+
throw new Error("Repository not found — run index_folder first");
|
|
2968
|
+
const opts = { project_root: index.root };
|
|
2969
|
+
if (args.validate_entries != null)
|
|
2970
|
+
opts.validate_entries = args.validate_entries;
|
|
2971
|
+
return await astroContentCollections(opts);
|
|
2972
|
+
},
|
|
2973
|
+
},
|
|
2974
|
+
{
|
|
2975
|
+
name: "astro_audit",
|
|
2976
|
+
category: "analysis",
|
|
2977
|
+
searchHint: "astro meta audit full health check score gates recommendations islands hydration routes config actions content migration patterns",
|
|
2978
|
+
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.",
|
|
2979
|
+
schema: {
|
|
2980
|
+
repo: z.string().optional().describe("Repository identifier (default: auto-detected from CWD)"),
|
|
2981
|
+
skip: z.array(z.string()).optional().describe("Sections to skip: config, hydration, routes, actions, content, migration, patterns"),
|
|
2982
|
+
},
|
|
2983
|
+
handler: async (args) => {
|
|
2984
|
+
const opts = {};
|
|
2985
|
+
if (args.repo != null)
|
|
2986
|
+
opts.repo = args.repo;
|
|
2987
|
+
if (args.skip != null)
|
|
2988
|
+
opts.skip = args.skip;
|
|
2989
|
+
return await astroAudit(opts);
|
|
2990
|
+
},
|
|
2991
|
+
},
|
|
3058
2992
|
// --- Hono framework tools (Task 23) ---
|
|
3059
2993
|
{
|
|
3060
2994
|
name: "trace_middleware_chain",
|
|
3061
2995
|
category: "graph",
|
|
3062
|
-
searchHint: "hono middleware chain trace order scope auth use",
|
|
3063
|
-
description: "
|
|
2996
|
+
searchHint: "hono middleware chain trace order scope auth use conditional applied_when if method header path basicAuth gated",
|
|
2997
|
+
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
2998
|
schema: {
|
|
3065
2999
|
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.)"),
|
|
3000
|
+
path: z.string().optional().describe("Route path to look up (e.g. '/api/users/:id'). Omit for scope or app-wide query."),
|
|
3001
|
+
method: z.string().optional().describe("HTTP method filter (GET, POST, etc.). Only used in route mode."),
|
|
3002
|
+
scope: z.string().optional().describe("Exact middleware scope literal (e.g. '/posts/*'). Mutually exclusive with path."),
|
|
3003
|
+
only_conditional: z.boolean().optional().describe("Filter entries to those whose applied_when field is populated (conditional middleware)."),
|
|
3068
3004
|
},
|
|
3069
3005
|
handler: async (args) => {
|
|
3070
3006
|
const { traceMiddlewareChain } = await import("./tools/hono-middleware-chain.js");
|
|
3071
|
-
|
|
3007
|
+
const opts = {};
|
|
3008
|
+
if (args.scope !== undefined)
|
|
3009
|
+
opts.scope = args.scope;
|
|
3010
|
+
if (args.only_conditional !== undefined)
|
|
3011
|
+
opts.only_conditional = args.only_conditional;
|
|
3012
|
+
return await traceMiddlewareChain(args.repo, args.path, args.method, Object.keys(opts).length > 0 ? opts : undefined);
|
|
3072
3013
|
},
|
|
3073
3014
|
},
|
|
3074
3015
|
{
|
|
@@ -3131,8 +3072,8 @@ const TOOL_DEFINITIONS = [
|
|
|
3131
3072
|
{
|
|
3132
3073
|
name: "audit_hono_security",
|
|
3133
3074
|
category: "security",
|
|
3134
|
-
searchHint: "hono security audit rate limit secure headers auth order csrf",
|
|
3135
|
-
description: "Security audit of a Hono app: missing rate
|
|
3075
|
+
searchHint: "hono security audit rate limit secure headers auth order csrf env regression createMiddleware BlankEnv Issue 3587",
|
|
3076
|
+
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
3077
|
schema: {
|
|
3137
3078
|
repo: z.string().optional().describe("Repository identifier (default: auto-detected from CWD)"),
|
|
3138
3079
|
},
|
|
@@ -3156,20 +3097,6 @@ const TOOL_DEFINITIONS = [
|
|
|
3156
3097
|
},
|
|
3157
3098
|
},
|
|
3158
3099
|
// --- 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
3100
|
{
|
|
3174
3101
|
name: "analyze_inline_handler",
|
|
3175
3102
|
category: "analysis",
|
|
@@ -3198,19 +3125,6 @@ const TOOL_DEFINITIONS = [
|
|
|
3198
3125
|
return await extractResponseTypes(args.repo);
|
|
3199
3126
|
},
|
|
3200
3127
|
},
|
|
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
3128
|
{
|
|
3215
3129
|
name: "detect_hono_modules",
|
|
3216
3130
|
category: "analysis",
|
|
@@ -3238,29 +3152,6 @@ const TOOL_DEFINITIONS = [
|
|
|
3238
3152
|
},
|
|
3239
3153
|
},
|
|
3240
3154
|
// --- 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
3155
|
{
|
|
3265
3156
|
name: "nextjs_route_map",
|
|
3266
3157
|
category: "analysis",
|
|
@@ -3307,135 +3198,17 @@ const TOOL_DEFINITIONS = [
|
|
|
3307
3198
|
return formatNextjsMetadataAudit(result);
|
|
3308
3199
|
},
|
|
3309
3200
|
},
|
|
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
3201
|
{
|
|
3431
3202
|
name: "framework_audit",
|
|
3432
3203
|
category: "analysis",
|
|
3433
|
-
searchHint: "nextjs framework audit meta-tool overall score security metadata routes components",
|
|
3204
|
+
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
3205
|
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
3206
|
schema: {
|
|
3436
3207
|
repo: z.string().optional().describe("Repository identifier (default: auto-detected from CWD)"),
|
|
3437
3208
|
workspace: z.string().optional().describe("Monorepo workspace path, e.g. 'apps/web'"),
|
|
3438
3209
|
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"),
|
|
3210
|
+
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"),
|
|
3211
|
+
priority_limit: z.number().int().positive().optional().describe("Max findings in priority mode (default: 20)"),
|
|
3439
3212
|
},
|
|
3440
3213
|
handler: async (args) => {
|
|
3441
3214
|
const opts = {};
|
|
@@ -3443,6 +3216,10 @@ const TOOL_DEFINITIONS = [
|
|
|
3443
3216
|
opts.workspace = args.workspace;
|
|
3444
3217
|
if (args.tools != null)
|
|
3445
3218
|
opts.tools = args.tools;
|
|
3219
|
+
if (args.mode != null)
|
|
3220
|
+
opts.mode = args.mode;
|
|
3221
|
+
if (args.priority_limit != null)
|
|
3222
|
+
opts.priority_limit = args.priority_limit;
|
|
3446
3223
|
const result = await frameworkAudit(args.repo ?? "", opts);
|
|
3447
3224
|
return formatFrameworkAudit(result);
|
|
3448
3225
|
},
|
|
@@ -3543,94 +3320,40 @@ const TOOL_DEFINITIONS = [
|
|
|
3543
3320
|
},
|
|
3544
3321
|
},
|
|
3545
3322
|
{
|
|
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",
|
|
3323
|
+
name: "sql_audit",
|
|
3574
3324
|
category: "analysis",
|
|
3575
|
-
searchHint: "
|
|
3576
|
-
description: "
|
|
3325
|
+
searchHint: "SQL audit composite drift orphan lint DML safety complexity god table schema diagnostic",
|
|
3326
|
+
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
3327
|
schema: {
|
|
3578
3328
|
repo: z.string().optional().describe("Repository identifier (default: auto-detected from CWD)"),
|
|
3329
|
+
checks: z.array(z.enum(["drift", "orphan", "lint", "dml", "complexity"])).optional().describe("Subset of gates to run (default: all 5)"),
|
|
3579
3330
|
file_pattern: z.string().optional().describe("Scope to files matching pattern"),
|
|
3580
|
-
max_results: zNum().describe("Max findings per pattern (default: 200)"),
|
|
3331
|
+
max_results: zNum().describe("Max DML findings per pattern (default: 200)"),
|
|
3581
3332
|
},
|
|
3582
3333
|
handler: async (args) => {
|
|
3583
|
-
const {
|
|
3334
|
+
const { sqlAudit } = await import("./tools/sql-tools.js");
|
|
3584
3335
|
const opts = {};
|
|
3336
|
+
if (args.checks != null)
|
|
3337
|
+
opts.checks = args.checks;
|
|
3585
3338
|
if (args.file_pattern != null)
|
|
3586
3339
|
opts.file_pattern = args.file_pattern;
|
|
3587
3340
|
if (args.max_results != null)
|
|
3588
3341
|
opts.max_results = args.max_results;
|
|
3589
|
-
const result = await
|
|
3342
|
+
const result = await sqlAudit(args.repo, opts);
|
|
3590
3343
|
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}`);
|
|
3344
|
+
parts.push(`SQL audit: ${result.summary.gates_run} gates run, ${result.summary.gates_passed} passed, ${result.summary.gates_failed} failed`);
|
|
3345
|
+
parts.push(` Total findings: ${result.summary.total_findings}`);
|
|
3346
|
+
parts.push(` Critical findings: ${result.summary.critical_findings}`);
|
|
3347
|
+
parts.push("");
|
|
3348
|
+
for (const g of result.gates) {
|
|
3349
|
+
const icon = g.pass ? "✓" : (g.critical ? "✗ CRITICAL" : "⚠");
|
|
3350
|
+
parts.push(`${icon} ${g.check}: ${g.summary}`);
|
|
3624
3351
|
}
|
|
3625
3352
|
if (result.warnings.length > 0) {
|
|
3626
|
-
for (const w of result.warnings)
|
|
3627
|
-
parts.push(`⚠ ${w}`);
|
|
3628
|
-
}
|
|
3629
|
-
if (result.findings.length > 0) {
|
|
3630
3353
|
parts.push("");
|
|
3631
|
-
|
|
3632
|
-
|
|
3633
|
-
|
|
3354
|
+
parts.push("─── Warnings ───");
|
|
3355
|
+
for (const w of result.warnings)
|
|
3356
|
+
parts.push(` ⚠ ${w}`);
|
|
3634
3357
|
}
|
|
3635
3358
|
return parts.join("\n");
|
|
3636
3359
|
},
|
|
@@ -3670,35 +3393,6 @@ const TOOL_DEFINITIONS = [
|
|
|
3670
3393
|
return parts.join("\n");
|
|
3671
3394
|
},
|
|
3672
3395
|
},
|
|
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
3396
|
{
|
|
3703
3397
|
name: "search_columns",
|
|
3704
3398
|
category: "search",
|
|
@@ -3734,45 +3428,75 @@ const TOOL_DEFINITIONS = [
|
|
|
3734
3428
|
return parts.join("\n");
|
|
3735
3429
|
},
|
|
3736
3430
|
},
|
|
3431
|
+
// --- Astro v6 migration check ---
|
|
3737
3432
|
{
|
|
3738
|
-
name: "
|
|
3433
|
+
name: "astro_migration_check",
|
|
3739
3434
|
category: "analysis",
|
|
3740
|
-
searchHint: "
|
|
3741
|
-
description: "
|
|
3435
|
+
searchHint: "astro v6 migration upgrade breaking changes compatibility check AM01 AM10 content collections ViewTransitions",
|
|
3436
|
+
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
3437
|
schema: {
|
|
3743
3438
|
repo: z.string().optional().describe("Repository identifier (default: auto-detected from CWD)"),
|
|
3744
|
-
|
|
3439
|
+
target_version: z.enum(["6"]).optional().describe("Target Astro version (default: '6')"),
|
|
3745
3440
|
},
|
|
3746
3441
|
handler: async (args) => {
|
|
3747
|
-
const
|
|
3748
|
-
|
|
3749
|
-
|
|
3750
|
-
|
|
3751
|
-
|
|
3752
|
-
const
|
|
3753
|
-
|
|
3754
|
-
|
|
3755
|
-
|
|
3756
|
-
|
|
3757
|
-
|
|
3758
|
-
|
|
3759
|
-
|
|
3760
|
-
|
|
3761
|
-
parts.push(`⚠ ${w}`);
|
|
3442
|
+
const mcArgs = {};
|
|
3443
|
+
if (args.repo != null)
|
|
3444
|
+
mcArgs.repo = args.repo;
|
|
3445
|
+
if (args.target_version != null)
|
|
3446
|
+
mcArgs.target_version = args.target_version;
|
|
3447
|
+
const result = await astroMigrationCheck(mcArgs);
|
|
3448
|
+
const lines = [];
|
|
3449
|
+
lines.push(`ASTRO MIGRATION CHECK: v${result.current_version ?? "unknown"} → v${result.target_version}`);
|
|
3450
|
+
lines.push(`Issues: ${result.summary.total_issues} | Estimated: ${result.summary.estimated_migration_hours}`);
|
|
3451
|
+
if (Object.keys(result.summary.by_effort).length > 0) {
|
|
3452
|
+
const effortStr = Object.entries(result.summary.by_effort)
|
|
3453
|
+
.map(([k, v]) => `${v}×${k}`)
|
|
3454
|
+
.join(", ");
|
|
3455
|
+
lines.push(`Effort: ${effortStr}`);
|
|
3762
3456
|
}
|
|
3763
|
-
if (result.
|
|
3764
|
-
|
|
3765
|
-
|
|
3766
|
-
|
|
3767
|
-
|
|
3768
|
-
|
|
3769
|
-
|
|
3457
|
+
if (result.breaking_changes.length === 0) {
|
|
3458
|
+
lines.push("\n✓ No v6 breaking changes detected.");
|
|
3459
|
+
}
|
|
3460
|
+
else {
|
|
3461
|
+
lines.push("");
|
|
3462
|
+
for (const issue of result.breaking_changes) {
|
|
3463
|
+
const sev = issue.severity === "error" ? "✗" : issue.severity === "warning" ? "⚠" : "ℹ";
|
|
3464
|
+
lines.push(`${sev} ${issue.code} [${issue.category}] — ${issue.message}`);
|
|
3465
|
+
lines.push(` effort: ${issue.effort} | files: ${issue.files.slice(0, 3).join(", ")}${issue.files.length > 3 ? ` +${issue.files.length - 3} more` : ""}`);
|
|
3466
|
+
if (issue.migration_guide)
|
|
3467
|
+
lines.push(` guide: ${issue.migration_guide}`);
|
|
3770
3468
|
}
|
|
3771
|
-
|
|
3772
|
-
|
|
3469
|
+
}
|
|
3470
|
+
return lines.join("\n");
|
|
3471
|
+
},
|
|
3472
|
+
},
|
|
3473
|
+
// --- Discovery / concierge ---
|
|
3474
|
+
{
|
|
3475
|
+
name: "plan_turn",
|
|
3476
|
+
category: "discovery",
|
|
3477
|
+
searchHint: "plan turn routing recommend tools symbols files gap analysis session aware concierge",
|
|
3478
|
+
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.",
|
|
3479
|
+
schema: {
|
|
3480
|
+
repo: z.string().optional().describe("Repository identifier (default: auto-detected from CWD)"),
|
|
3481
|
+
query: z.string().describe("Natural-language description of what you want to do"),
|
|
3482
|
+
max_results: z.number().optional().describe("Max tools to return (default 10)"),
|
|
3483
|
+
skip_session: z.boolean().optional().describe("Skip session state checks (default false)"),
|
|
3484
|
+
},
|
|
3485
|
+
handler: async (args) => {
|
|
3486
|
+
const { query, max_results, skip_session } = args;
|
|
3487
|
+
const opts = {};
|
|
3488
|
+
if (max_results !== undefined)
|
|
3489
|
+
opts.max_results = max_results;
|
|
3490
|
+
if (skip_session !== undefined)
|
|
3491
|
+
opts.skip_session = skip_session;
|
|
3492
|
+
const result = await planTurn(args.repo, query, opts);
|
|
3493
|
+
for (const name of result.reveal_required) {
|
|
3494
|
+
const handle = toolHandles.get(name);
|
|
3495
|
+
if (handle && typeof handle.enable === "function") {
|
|
3496
|
+
handle.enable();
|
|
3773
3497
|
}
|
|
3774
3498
|
}
|
|
3775
|
-
return
|
|
3499
|
+
return formatPlanTurnResult(result);
|
|
3776
3500
|
},
|
|
3777
3501
|
},
|
|
3778
3502
|
];
|
|
@@ -3971,9 +3695,6 @@ export function registerTools(server, options) {
|
|
|
3971
3695
|
registerShortener("nextjs_route_map", { compact: formatNextjsRouteMapCompact, counts: formatNextjsRouteMapCounts });
|
|
3972
3696
|
registerShortener("nextjs_metadata_audit", { compact: formatNextjsMetadataAuditCompact, counts: formatNextjsMetadataAuditCounts });
|
|
3973
3697
|
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
3698
|
registerShortener("get_session_context", {
|
|
3978
3699
|
compact: (raw) => {
|
|
3979
3700
|
const text = typeof raw === "string" ? raw : JSON.stringify(raw);
|