@4da/mcp-server 6.0.2 → 6.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (119) hide show
  1. package/CHANGELOG.md +433 -0
  2. package/README.md +26 -18
  3. package/dist/db.d.ts +73 -8
  4. package/dist/db.js +180 -43
  5. package/dist/doctor.d.ts +1 -1
  6. package/dist/doctor.js +15 -9
  7. package/dist/embeddings.js +19 -7
  8. package/dist/gitignore.js +9 -3
  9. package/dist/index.js +43 -4
  10. package/dist/live/cache.d.ts +31 -2
  11. package/dist/live/cache.js +113 -1
  12. package/dist/live/changelog-classify.d.ts +9 -3
  13. package/dist/live/changelog-classify.js +125 -12
  14. package/dist/live/changelog.d.ts +22 -3
  15. package/dist/live/changelog.js +132 -38
  16. package/dist/live/dev-scope.d.ts +2 -2
  17. package/dist/live/fix-paths.d.ts +118 -0
  18. package/dist/live/fix-paths.js +498 -0
  19. package/dist/live/github-releases.d.ts +69 -0
  20. package/dist/live/github-releases.js +252 -0
  21. package/dist/live/go-registry.d.ts +5 -0
  22. package/dist/live/go-registry.js +1 -1
  23. package/dist/live/go-releases.d.ts +48 -0
  24. package/dist/live/go-releases.js +196 -0
  25. package/dist/live/index.d.ts +34 -8
  26. package/dist/live/index.js +66 -7
  27. package/dist/live/lockfile-parents.d.ts +61 -0
  28. package/dist/live/lockfile-parents.js +360 -0
  29. package/dist/live/lockfile-parsers-pygo.d.ts +31 -0
  30. package/dist/live/lockfile-parsers-pygo.js +178 -28
  31. package/dist/live/lockfile-parsers.d.ts +4 -1
  32. package/dist/live/lockfile-parsers.js +57 -24
  33. package/dist/live/lockfile-types.d.ts +12 -3
  34. package/dist/live/lockfile-types.js +2 -1
  35. package/dist/live/osv-ranges.d.ts +85 -0
  36. package/dist/live/osv-ranges.js +136 -0
  37. package/dist/live/osv-scanner.d.ts +1 -0
  38. package/dist/live/osv-scanner.js +85 -78
  39. package/dist/live/package-archive.d.ts +2 -0
  40. package/dist/live/package-archive.js +7 -4
  41. package/dist/live/pypi-releases.d.ts +44 -0
  42. package/dist/live/pypi-releases.js +103 -0
  43. package/dist/live/range-satisfies.d.ts +21 -0
  44. package/dist/live/range-satisfies.js +190 -0
  45. package/dist/live/rate-limiter.d.ts +6 -0
  46. package/dist/live/rate-limiter.js +5 -0
  47. package/dist/live/registry-health.js +2 -0
  48. package/dist/live/release-metadata.d.ts +17 -8
  49. package/dist/live/release-metadata.js +6 -3
  50. package/dist/live/resolution.d.ts +11 -1
  51. package/dist/live/resolution.js +16 -6
  52. package/dist/live/semver-utils.d.ts +8 -0
  53. package/dist/live/semver-utils.js +10 -2
  54. package/dist/live/types.d.ts +17 -1
  55. package/dist/live/upgrade-go.d.ts +62 -0
  56. package/dist/live/upgrade-go.js +130 -0
  57. package/dist/live/upgrade-pypi.d.ts +42 -0
  58. package/dist/live/upgrade-pypi.js +85 -0
  59. package/dist/live/upgrade-sources.d.ts +30 -11
  60. package/dist/live/upgrade-sources.js +93 -21
  61. package/dist/live/zip-archive.d.ts +22 -0
  62. package/dist/live/zip-archive.js +98 -0
  63. package/dist/memory-store.d.ts +19 -0
  64. package/dist/memory-store.js +8 -0
  65. package/dist/native-bindings.d.ts +7 -2
  66. package/dist/native-bindings.js +4 -0
  67. package/dist/project-tree.d.ts +50 -8
  68. package/dist/project-tree.js +121 -29
  69. package/dist/schema-registry.js +5 -5
  70. package/dist/server-instructions.d.ts +6 -0
  71. package/dist/server-instructions.js +20 -15
  72. package/dist/sqlite-driver.d.ts +134 -0
  73. package/dist/sqlite-driver.js +359 -0
  74. package/dist/tool-dispatch.d.ts +8 -1
  75. package/dist/tool-dispatch.js +17 -2
  76. package/dist/tools/agent-memory.js +10 -2
  77. package/dist/tools/app-plan.d.ts +11 -1
  78. package/dist/tools/app-plan.js +32 -6
  79. package/dist/tools/briefing-task-scope.d.ts +21 -2
  80. package/dist/tools/briefing-task-scope.js +97 -4
  81. package/dist/tools/decision-memory.js +9 -3
  82. package/dist/tools/dependency-check-signals.d.ts +23 -5
  83. package/dist/tools/dependency-check-signals.js +62 -19
  84. package/dist/tools/dependency-check-versions.d.ts +94 -0
  85. package/dist/tools/dependency-check-versions.js +213 -0
  86. package/dist/tools/dependency-check.d.ts +27 -11
  87. package/dist/tools/dependency-check.js +321 -74
  88. package/dist/tools/dependency-health.d.ts +1 -1
  89. package/dist/tools/dependency-health.js +5 -0
  90. package/dist/tools/knowledge-gap-ranges.d.ts +1 -1
  91. package/dist/tools/knowledge-gap-ranges.js +1 -1
  92. package/dist/tools/knowledge-gap-scope.d.ts +2 -2
  93. package/dist/tools/project-scope.d.ts +45 -0
  94. package/dist/tools/project-scope.js +119 -0
  95. package/dist/tools/record-feedback.js +1 -1
  96. package/dist/tools/upgrade-impact-callsites.d.ts +1 -0
  97. package/dist/tools/upgrade-impact-callsites.js +23 -5
  98. package/dist/tools/upgrade-impact-changelog.d.ts +41 -0
  99. package/dist/tools/upgrade-impact-changelog.js +79 -0
  100. package/dist/tools/upgrade-impact-imports.d.ts +42 -0
  101. package/dist/tools/upgrade-impact-imports.js +260 -0
  102. package/dist/tools/upgrade-impact-literals.js +1 -1
  103. package/dist/tools/upgrade-impact-report.d.ts +23 -0
  104. package/dist/tools/upgrade-impact-report.js +45 -6
  105. package/dist/tools/upgrade-impact.d.ts +13 -4
  106. package/dist/tools/upgrade-impact.js +236 -85
  107. package/dist/tools/upgrade-planner-fixpaths.d.ts +40 -0
  108. package/dist/tools/upgrade-planner-fixpaths.js +0 -0
  109. package/dist/tools/upgrade-planner.d.ts +31 -3
  110. package/dist/tools/upgrade-planner.js +74 -19
  111. package/dist/tools/vulnerability-scan-concise.d.ts +13 -1
  112. package/dist/tools/vulnerability-scan-concise.js +15 -3
  113. package/dist/tools/vulnerability-scan-format.d.ts +58 -1
  114. package/dist/tools/vulnerability-scan-format.js +107 -11
  115. package/dist/tools/vulnerability-scan.d.ts +104 -13
  116. package/dist/tools/vulnerability-scan.js +27 -3
  117. package/dist/tools/what-should-i-know.d.ts +22 -2
  118. package/dist/tools/what-should-i-know.js +122 -12
  119. package/package.json +10 -32
@@ -74,7 +74,7 @@ export async function flagOldSyntax(sections, files, root) {
74
74
  const candidates = sections
75
75
  .flatMap((s) => s.entries)
76
76
  .filter((e) => e.kind === "breaking" || e.kind === "deprecation")
77
- .map((entry) => ({ entry, shapes: oldSyntaxShapes(entry.text) }))
77
+ .map((entry) => ({ entry, shapes: [entry.text, ...(entry.details ?? [])].flatMap(oldSyntaxShapes) }))
78
78
  .filter((c) => c.shapes.length > 0);
79
79
  if (!root || candidates.length === 0 || files.length === 0)
80
80
  return { newlyTouching: 0, examples: [] };
@@ -24,6 +24,8 @@ export interface ReportEntry {
24
24
  text: string;
25
25
  /** The changelog heading or parent bullet the entry sits under ("Removed", "Breaking Changes"). */
26
26
  under?: string;
27
+ /** Bullets nested under the entry: part of it, not counted as entries of their own. */
28
+ details?: string[];
27
29
  touches_your_code?: boolean;
28
30
  matched_symbols?: string[];
29
31
  /** String literals in your code that use the syntax this entry retires (route patterns and the like). */
@@ -62,6 +64,14 @@ export type UpgradeType = "patch" | "minor" | "major" | "prerelease" | "unknown"
62
64
  export declare function upgradeType(from: string, to: string): UpgradeType;
63
65
  /** Major versions crossed (0.x minors count as majors, matching `upgradeType`). */
64
66
  export declare function majorsCrossed(from: string, to: string): number;
67
+ /**
68
+ * `majorsCrossed` for versions as a task names them: "0.13", "7.x", "v2",
69
+ * "1.4.0". A partial version is read as the start of its line (0.13 ->
70
+ * 0.13.0, 7.x -> 7.0.0). Null when either side is unreadable. A plain
71
+ * major-number compare read reqwest 0.12 -> 0.13 as 0 majors crossed, and
72
+ * the briefing called a breaking upgrade safe to delegate.
73
+ */
74
+ export declare function majorsCrossedLoose(from: string | null, to: string | null): number | null;
65
75
  /** Up to `count` published versions nearest to `wanted` by precedence, for "version not found" errors. */
66
76
  export declare function nearestVersions(published: string[], requested: string, count?: number): string[];
67
77
  export interface SummaryInput {
@@ -75,6 +85,19 @@ export interface SummaryInput {
75
85
  /** missing = no changelog file; no_entries = a file with no section for these releases; partial = some of them. */
76
86
  changelog: "missing" | "no_entries" | "partial" | "complete";
77
87
  advisoriesFixed: number | null;
88
+ /** Versions as the ecosystem writes them (`v1.2.3`, `3.0rc1`); `from`/`to` are their semver reading. */
89
+ fromLabel?: string;
90
+ toLabel?: string;
91
+ /** Where the entries came from when not the archive ("GitHub release notes"). */
92
+ changelogFrom?: string | null;
93
+ /** How to get a changelog that is missing (the opt-in GitHub fallback), when it would help. */
94
+ githubHint?: string | null;
95
+ /** Go: the upgrade moves to another module path. */
96
+ pathChange?: {
97
+ from: string;
98
+ to: string;
99
+ files: number;
100
+ } | null;
78
101
  }
79
102
  /** The one sentence a human or agent reads first. */
80
103
  export declare function summarize(input: SummaryInput): string;
@@ -50,9 +50,15 @@ export function shapeChangelog(sections, symbols, format) {
50
50
  return true;
51
51
  });
52
52
  const entries = unique.map((e) => {
53
- const entry = { kind: e.kind, text: e.text, ...(e.under ? { under: e.under } : {}) };
53
+ const entry = {
54
+ kind: e.kind,
55
+ text: e.text,
56
+ ...(e.under ? { under: e.under } : {}),
57
+ ...(e.details?.length ? { details: e.details } : {}),
58
+ };
54
59
  if (e.kind === "breaking" || e.kind === "deprecation") {
55
- const matched = matchSymbols(e.text, symbols);
60
+ // The nested points name the affected functions (date-fns 3.0) as often as the entry does.
61
+ const matched = matchSymbols([e.text, ...(e.details ?? [])].join(" "), symbols);
56
62
  if (matched.length > 0) {
57
63
  entry.touches_your_code = true;
58
64
  entry.matched_symbols = matched;
@@ -78,7 +84,10 @@ export function shapeChangelog(sections, symbols, format) {
78
84
  if (format === "concise") {
79
85
  const important = entries.filter((e) => e.kind !== "change");
80
86
  const others = entries.filter((e) => e.kind === "change");
81
- const additive = (e) => (e.under ? classifyHeading(e.under) === "additive" : false);
87
+ const additive = (e) => {
88
+ const ctx = e.under ? classifyHeading(e.under) : null;
89
+ return ctx === "additive" || ctx === "fixes";
90
+ };
82
91
  const neutral = others.filter((e) => !additive(e)).slice(0, CONCISE_NEUTRAL_PER_VERSION);
83
92
  const minor = others.filter(additive).slice(0, CONCISE_ADDITIVE_PER_VERSION);
84
93
  // Keep document order among the kept plain changes.
@@ -120,6 +129,9 @@ export function upgradeType(from, to) {
120
129
  return "major";
121
130
  if (a.major === 0 && a.minor !== b.minor)
122
131
  return "major";
132
+ // ^0.0.3 admits only 0.0.3: any 0.0.x change is breaking (dependency_health and dependency_check agree).
133
+ if (a.major === 0 && a.minor === 0 && a.patch !== b.patch)
134
+ return "major";
123
135
  if (a.minor !== b.minor)
124
136
  return "minor";
125
137
  return "patch";
@@ -134,6 +146,27 @@ export function majorsCrossed(from, to) {
134
146
  return Math.max(0, b.minor - a.minor);
135
147
  return Math.max(0, b.major - a.major);
136
148
  }
149
+ /**
150
+ * `majorsCrossed` for versions as a task names them: "0.13", "7.x", "v2",
151
+ * "1.4.0". A partial version is read as the start of its line (0.13 ->
152
+ * 0.13.0, 7.x -> 7.0.0). Null when either side is unreadable. A plain
153
+ * major-number compare read reqwest 0.12 -> 0.13 as 0 majors crossed, and
154
+ * the briefing called a breaking upgrade safe to delegate.
155
+ */
156
+ export function majorsCrossedLoose(from, to) {
157
+ const pad = (v) => {
158
+ const m = v ? /^v?(\d+)(?:\.(\d+|[x*]))?(?:\.(\d+|[x*]))?/i.exec(v.trim()) : null;
159
+ if (!m)
160
+ return null;
161
+ const num = (s) => (s === undefined || /[x*]/i.test(s) ? "0" : s);
162
+ return `${m[1]}.${num(m[2])}.${num(m[3])}`;
163
+ };
164
+ const a = pad(from);
165
+ const b = pad(to);
166
+ if (!a || !b)
167
+ return null;
168
+ return majorsCrossed(a, b);
169
+ }
137
170
  /** Up to `count` published versions nearest to `wanted` by precedence, for "version not found" errors. */
138
171
  export function nearestVersions(published, requested, count = 5) {
139
172
  // "7" / "7.x" / "7.1" are not semver: read them as the start of that line,
@@ -156,10 +189,11 @@ export function summarize(input) {
156
189
  ].filter(Boolean);
157
190
  let breaking;
158
191
  const atLeast = input.changelog === "partial" ? "at least " : "";
192
+ const hint = input.githubHint ? `; ${input.githubHint}` : "";
159
193
  if (input.changelog === "missing")
160
- breaking = "no changelog in the package archive (see release_notes_url)";
194
+ breaking = `no changelog in the package archive, so breaking changes are unknown (see release_notes_url${hint})`;
161
195
  else if (input.changelog === "no_entries") {
162
- breaking = "the package's changelog has no entries for these releases, so breaking changes are unknown (see release_notes_url)";
196
+ breaking = `the package's changelog has no entries for these releases, so breaking changes are unknown (see release_notes_url${hint})`;
163
197
  }
164
198
  else {
165
199
  // "flagged", not "N breaking changes": the flags come from headings and
@@ -172,7 +206,12 @@ export function summarize(input) {
172
206
  }
173
207
  else
174
208
  breaking = flagged;
209
+ if (input.changelogFrom)
210
+ breaking += ` (from ${input.changelogFrom})`;
175
211
  }
176
212
  const advisories = input.advisoriesFixed === null ? "advisories unknown (OSV unreachable)" : `${input.advisoriesFixed} advisories fixed`;
177
- return `${input.pkg} ${input.from} -> ${input.to}: ${parts.join(", ")}, ${breaking}, ${advisories}.`;
213
+ const path = input.pathChange
214
+ ? `, module path changes to ${input.pathChange.to} (${input.pathChange.files} ${input.pathChange.files === 1 ? "file imports" : "files import"} ${input.pathChange.from})`
215
+ : "";
216
+ return `${input.pkg} ${input.fromLabel ?? input.from} -> ${input.toLabel ?? input.to}: ${parts.join(", ")}${path}, ${breaking}, ${advisories}.`;
178
217
  }
@@ -8,12 +8,19 @@
8
8
  * (breaking / deprecation / security), and cross-references the breaking
9
9
  * ones against the symbols this project actually imports from the package.
10
10
  *
11
- * Why the changelog comes from the archive and nowhere else: an agent asked
12
- * to bump fastembed 5 -> 7 otherwise reads GitHub release pages one by one, or
11
+ * Why the changelog comes from the archive first: an agent asked to bump
12
+ * fastembed 5 -> 7 otherwise reads GitHub release pages one by one, or
13
13
  * guesses from the version number. The archive is on the registry the
14
14
  * package manager already trusts, so reading it discloses nothing new
15
- * (Decision 1, option A). When the archive has no changelog the report says
16
- * so and gives `release_notes_url`; it never fetches that page itself.
15
+ * (Decision 1, option A). When the archive has no changelog for the range,
16
+ * GitHub release notes are read only if the user opted in
17
+ * (FOURDA_GITHUB_CHANGELOG, Decision 1 option B); otherwise the report says
18
+ * the changelog is unavailable, how to enable the fallback, and gives
19
+ * `release_notes_url`. It never fetches a docs page itself.
20
+ *
21
+ * Ecosystems: npm, crates.io, PyPI (PEP 440 versions, sdist changelogs,
22
+ * distribution -> import-name mapping) and Go (module proxy, module-zip
23
+ * changelogs, major versions as separate module paths).
17
24
  *
18
25
  * Changelog text is third-party input: entries are sanitised (control and
19
26
  * bidi characters stripped, 400-char cap) and `_meta.untrusted_text` tells
@@ -46,6 +53,8 @@ export interface UpgradeImpactContext {
46
53
  projectRoot: string | null;
47
54
  installed: InstalledDep[];
48
55
  offline: boolean;
56
+ /** FOURDA_GITHUB_CHANGELOG: read GitHub release notes when the archive has none (opt-in, default off). */
57
+ githubChangelog?: boolean;
49
58
  }
50
59
  export declare const upgradeImpactTool: {
51
60
  name: string;