@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.
- package/CHANGELOG.md +433 -0
- package/README.md +26 -18
- package/dist/db.d.ts +73 -8
- package/dist/db.js +180 -43
- package/dist/doctor.d.ts +1 -1
- package/dist/doctor.js +15 -9
- package/dist/embeddings.js +19 -7
- package/dist/gitignore.js +9 -3
- package/dist/index.js +43 -4
- package/dist/live/cache.d.ts +31 -2
- package/dist/live/cache.js +113 -1
- package/dist/live/changelog-classify.d.ts +9 -3
- package/dist/live/changelog-classify.js +125 -12
- package/dist/live/changelog.d.ts +22 -3
- package/dist/live/changelog.js +132 -38
- package/dist/live/dev-scope.d.ts +2 -2
- package/dist/live/fix-paths.d.ts +118 -0
- package/dist/live/fix-paths.js +498 -0
- package/dist/live/github-releases.d.ts +69 -0
- package/dist/live/github-releases.js +252 -0
- package/dist/live/go-registry.d.ts +5 -0
- package/dist/live/go-registry.js +1 -1
- package/dist/live/go-releases.d.ts +48 -0
- package/dist/live/go-releases.js +196 -0
- package/dist/live/index.d.ts +34 -8
- package/dist/live/index.js +66 -7
- package/dist/live/lockfile-parents.d.ts +61 -0
- package/dist/live/lockfile-parents.js +360 -0
- package/dist/live/lockfile-parsers-pygo.d.ts +31 -0
- package/dist/live/lockfile-parsers-pygo.js +178 -28
- package/dist/live/lockfile-parsers.d.ts +4 -1
- package/dist/live/lockfile-parsers.js +57 -24
- package/dist/live/lockfile-types.d.ts +12 -3
- package/dist/live/lockfile-types.js +2 -1
- package/dist/live/osv-ranges.d.ts +85 -0
- package/dist/live/osv-ranges.js +136 -0
- package/dist/live/osv-scanner.d.ts +1 -0
- package/dist/live/osv-scanner.js +85 -78
- package/dist/live/package-archive.d.ts +2 -0
- package/dist/live/package-archive.js +7 -4
- package/dist/live/pypi-releases.d.ts +44 -0
- package/dist/live/pypi-releases.js +103 -0
- package/dist/live/range-satisfies.d.ts +21 -0
- package/dist/live/range-satisfies.js +190 -0
- package/dist/live/rate-limiter.d.ts +6 -0
- package/dist/live/rate-limiter.js +5 -0
- package/dist/live/registry-health.js +2 -0
- package/dist/live/release-metadata.d.ts +17 -8
- package/dist/live/release-metadata.js +6 -3
- package/dist/live/resolution.d.ts +11 -1
- package/dist/live/resolution.js +16 -6
- package/dist/live/semver-utils.d.ts +8 -0
- package/dist/live/semver-utils.js +10 -2
- package/dist/live/types.d.ts +17 -1
- package/dist/live/upgrade-go.d.ts +62 -0
- package/dist/live/upgrade-go.js +130 -0
- package/dist/live/upgrade-pypi.d.ts +42 -0
- package/dist/live/upgrade-pypi.js +85 -0
- package/dist/live/upgrade-sources.d.ts +30 -11
- package/dist/live/upgrade-sources.js +93 -21
- package/dist/live/zip-archive.d.ts +22 -0
- package/dist/live/zip-archive.js +98 -0
- package/dist/memory-store.d.ts +19 -0
- package/dist/memory-store.js +8 -0
- package/dist/native-bindings.d.ts +7 -2
- package/dist/native-bindings.js +4 -0
- package/dist/project-tree.d.ts +50 -8
- package/dist/project-tree.js +121 -29
- package/dist/schema-registry.js +5 -5
- package/dist/server-instructions.d.ts +6 -0
- package/dist/server-instructions.js +20 -15
- package/dist/sqlite-driver.d.ts +134 -0
- package/dist/sqlite-driver.js +359 -0
- package/dist/tool-dispatch.d.ts +8 -1
- package/dist/tool-dispatch.js +17 -2
- package/dist/tools/agent-memory.js +10 -2
- package/dist/tools/app-plan.d.ts +11 -1
- package/dist/tools/app-plan.js +32 -6
- package/dist/tools/briefing-task-scope.d.ts +21 -2
- package/dist/tools/briefing-task-scope.js +97 -4
- package/dist/tools/decision-memory.js +9 -3
- package/dist/tools/dependency-check-signals.d.ts +23 -5
- package/dist/tools/dependency-check-signals.js +62 -19
- package/dist/tools/dependency-check-versions.d.ts +94 -0
- package/dist/tools/dependency-check-versions.js +213 -0
- package/dist/tools/dependency-check.d.ts +27 -11
- package/dist/tools/dependency-check.js +321 -74
- package/dist/tools/dependency-health.d.ts +1 -1
- package/dist/tools/dependency-health.js +5 -0
- package/dist/tools/knowledge-gap-ranges.d.ts +1 -1
- package/dist/tools/knowledge-gap-ranges.js +1 -1
- package/dist/tools/knowledge-gap-scope.d.ts +2 -2
- package/dist/tools/project-scope.d.ts +45 -0
- package/dist/tools/project-scope.js +119 -0
- package/dist/tools/record-feedback.js +1 -1
- package/dist/tools/upgrade-impact-callsites.d.ts +1 -0
- package/dist/tools/upgrade-impact-callsites.js +23 -5
- package/dist/tools/upgrade-impact-changelog.d.ts +41 -0
- package/dist/tools/upgrade-impact-changelog.js +79 -0
- package/dist/tools/upgrade-impact-imports.d.ts +42 -0
- package/dist/tools/upgrade-impact-imports.js +260 -0
- package/dist/tools/upgrade-impact-literals.js +1 -1
- package/dist/tools/upgrade-impact-report.d.ts +23 -0
- package/dist/tools/upgrade-impact-report.js +45 -6
- package/dist/tools/upgrade-impact.d.ts +13 -4
- package/dist/tools/upgrade-impact.js +236 -85
- package/dist/tools/upgrade-planner-fixpaths.d.ts +40 -0
- package/dist/tools/upgrade-planner-fixpaths.js +0 -0
- package/dist/tools/upgrade-planner.d.ts +31 -3
- package/dist/tools/upgrade-planner.js +74 -19
- package/dist/tools/vulnerability-scan-concise.d.ts +13 -1
- package/dist/tools/vulnerability-scan-concise.js +15 -3
- package/dist/tools/vulnerability-scan-format.d.ts +58 -1
- package/dist/tools/vulnerability-scan-format.js +107 -11
- package/dist/tools/vulnerability-scan.d.ts +104 -13
- package/dist/tools/vulnerability-scan.js +27 -3
- package/dist/tools/what-should-i-know.d.ts +22 -2
- package/dist/tools/what-should-i-know.js +122 -12
- 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:
|
|
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 = {
|
|
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
|
-
|
|
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) =>
|
|
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 =
|
|
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 =
|
|
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
|
-
|
|
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
|
|
12
|
-
*
|
|
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
|
|
16
|
-
*
|
|
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;
|