githits 0.4.2 → 0.4.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/.claude-plugin/marketplace.json +1 -1
- package/.claude-plugin/plugin.json +1 -1
- package/.plugin/plugin.json +1 -1
- package/README.md +3 -3
- package/dist/cli.js +369 -189
- package/dist/index.js +1 -1
- package/dist/shared/{chunk-v8sths32.js → chunk-15argn2z.js} +7 -17
- package/dist/shared/{chunk-q2mre780.js → chunk-kmka6wpx.js} +2 -2
- package/dist/shared/{chunk-jdygt0ra.js → chunk-q6d3ttgn.js} +1 -1
- package/gemini-extension.json +1 -1
- package/package.json +4 -1
- package/plugins/claude/.claude-plugin/plugin.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -49,11 +49,11 @@ import {
|
|
|
49
49
|
shouldRunUpdateCheck,
|
|
50
50
|
startTelemetrySpan,
|
|
51
51
|
withTelemetrySpan
|
|
52
|
-
} from "./shared/chunk-
|
|
52
|
+
} from "./shared/chunk-15argn2z.js";
|
|
53
53
|
import {
|
|
54
54
|
__require,
|
|
55
55
|
version
|
|
56
|
-
} from "./shared/chunk-
|
|
56
|
+
} from "./shared/chunk-q6d3ttgn.js";
|
|
57
57
|
|
|
58
58
|
// src/cli.ts
|
|
59
59
|
import { Command } from "commander";
|
|
@@ -2022,7 +2022,7 @@ var SUPPORTED_DEPS_REGISTRIES = new Set([
|
|
|
2022
2022
|
"RUBYGEMS",
|
|
2023
2023
|
"GO"
|
|
2024
2024
|
]);
|
|
2025
|
-
var
|
|
2025
|
+
var SUPPORTED_DEPS_REGISTRIES_LIST = PKGSEER_REGISTRY_ARGS.filter((arg) => SUPPORTED_DEPS_REGISTRIES.has(toPkgseerRegistry(arg))).join(", ");
|
|
2026
2026
|
function supportsDependenciesRegistry(registry) {
|
|
2027
2027
|
return SUPPORTED_DEPS_REGISTRIES.has(registry);
|
|
2028
2028
|
}
|
|
@@ -2037,7 +2037,7 @@ function buildPackageDependenciesParams(input) {
|
|
|
2037
2037
|
}
|
|
2038
2038
|
const registry = toPkgseerRegistry(normalisedRegistryArg);
|
|
2039
2039
|
if (!supportsDependenciesRegistry(registry)) {
|
|
2040
|
-
throw new UnsupportedDependenciesRegistryError(`pkg deps only supports ${
|
|
2040
|
+
throw new UnsupportedDependenciesRegistryError(`pkg deps only supports ${SUPPORTED_DEPS_REGISTRIES_LIST}. Got: ${normalisedRegistryArg}.`);
|
|
2041
2041
|
}
|
|
2042
2042
|
const version2 = normaliseVersion(input.version);
|
|
2043
2043
|
const canonicalLifecycles = resolveLifecycles(input.lifecycle);
|
|
@@ -2900,12 +2900,6 @@ function buildPackageSummarySuccessPayload(summary) {
|
|
|
2900
2900
|
const github = buildGithub(pkg.githubRepository);
|
|
2901
2901
|
if (github)
|
|
2902
2902
|
payload.github = github;
|
|
2903
|
-
if (summary.quickstart?.installCommand) {
|
|
2904
|
-
payload.install = summary.quickstart.installCommand;
|
|
2905
|
-
}
|
|
2906
|
-
const usage = normaliseUsage(summary.quickstart?.usageExample);
|
|
2907
|
-
if (usage)
|
|
2908
|
-
payload.usage = usage;
|
|
2909
2903
|
const vulns = buildVulnerabilities(summary.security);
|
|
2910
2904
|
if (vulns)
|
|
2911
2905
|
payload.vulnerabilities = vulns;
|
|
@@ -2964,20 +2958,12 @@ function buildGithub(github) {
|
|
|
2964
2958
|
result.lastPushedAt = lastPushedAt;
|
|
2965
2959
|
return Object.keys(result).length > 0 ? result : undefined;
|
|
2966
2960
|
}
|
|
2967
|
-
function normaliseUsage(usage) {
|
|
2968
|
-
if (!usage)
|
|
2969
|
-
return;
|
|
2970
|
-
const cleaned = usage.replace(/\r\n/g, `
|
|
2971
|
-
`).replace(/\r/g, `
|
|
2972
|
-
`);
|
|
2973
|
-
return cleaned.length > 0 ? cleaned : undefined;
|
|
2974
|
-
}
|
|
2975
2961
|
function buildVulnerabilities(security) {
|
|
2976
2962
|
if (!security)
|
|
2977
2963
|
return;
|
|
2978
|
-
|
|
2979
|
-
if (total === 0)
|
|
2964
|
+
if (typeof security.vulnerabilityCount !== "number")
|
|
2980
2965
|
return;
|
|
2966
|
+
const total = security.vulnerabilityCount;
|
|
2981
2967
|
const result = {
|
|
2982
2968
|
total,
|
|
2983
2969
|
affectsLatest: security.hasCurrentVulnerabilities ?? false
|
|
@@ -3033,7 +3019,7 @@ function pickChangelogSummary(entry) {
|
|
|
3033
3019
|
const firstLine = entry.body.split(/\r?\n/).map((line) => stripMarkdownHeading(line.trim())).find((line) => line.length > 0);
|
|
3034
3020
|
if (!firstLine)
|
|
3035
3021
|
return;
|
|
3036
|
-
return firstLine.length > 120 ? `${firstLine.slice(0,
|
|
3022
|
+
return firstLine.length > 120 ? `${firstLine.slice(0, 117).trimEnd()}...` : firstLine;
|
|
3037
3023
|
}
|
|
3038
3024
|
function stripMarkdownHeading(line) {
|
|
3039
3025
|
return line.replace(/^#{1,6}\s+/, "").trim();
|
|
@@ -3044,7 +3030,7 @@ function formatPackageSummaryTerminal(summary, options = {}) {
|
|
|
3044
3030
|
const width = resolveWidth(options.terminalWidth);
|
|
3045
3031
|
const now = options.now ?? new Date;
|
|
3046
3032
|
const sections = [];
|
|
3047
|
-
const header = lean.license ? `${colorize(lean.name, "bold", useColors)} @ ${lean.version}
|
|
3033
|
+
const header = lean.license ? `${colorize(lean.name, "bold", useColors)} @ ${lean.version} | ${lean.license}` : `${colorize(lean.name, "bold", useColors)} @ ${lean.version}`;
|
|
3048
3034
|
sections.push(header);
|
|
3049
3035
|
if (lean.description) {
|
|
3050
3036
|
sections.push(wrapText(lean.description, width));
|
|
@@ -3054,9 +3040,6 @@ function formatPackageSummaryTerminal(summary, options = {}) {
|
|
|
3054
3040
|
sections.push(fields.join(`
|
|
3055
3041
|
`));
|
|
3056
3042
|
}
|
|
3057
|
-
if (lean.vulnerabilities) {
|
|
3058
|
-
sections.push(formatVulnFooter(lean.vulnerabilities, useColors));
|
|
3059
|
-
}
|
|
3060
3043
|
if (options.verbose) {
|
|
3061
3044
|
const verbose = buildVerboseSections(lean, useColors);
|
|
3062
3045
|
if (verbose.length > 0)
|
|
@@ -3101,10 +3084,19 @@ function wrapText(text, width) {
|
|
|
3101
3084
|
function buildFieldList(lean, summary, useColors, now) {
|
|
3102
3085
|
const fields = [];
|
|
3103
3086
|
if (lean.repository) {
|
|
3087
|
+
const repositoryParts = [dim(lean.repository, useColors)];
|
|
3088
|
+
const githubPopularity = formatGithubPopularity(lean.github);
|
|
3089
|
+
if (githubPopularity)
|
|
3090
|
+
repositoryParts.push(`(${githubPopularity})`);
|
|
3104
3091
|
fields.push({
|
|
3105
3092
|
label: "Repository",
|
|
3106
|
-
value:
|
|
3093
|
+
value: repositoryParts.join(" ")
|
|
3107
3094
|
});
|
|
3095
|
+
} else {
|
|
3096
|
+
const githubPopularity = formatGithubPopularity(lean.github);
|
|
3097
|
+
if (githubPopularity) {
|
|
3098
|
+
fields.push({ label: "GitHub", value: githubPopularity });
|
|
3099
|
+
}
|
|
3108
3100
|
}
|
|
3109
3101
|
if (lean.homepage) {
|
|
3110
3102
|
fields.push({ label: "Homepage", value: dim(lean.homepage, useColors) });
|
|
@@ -3124,54 +3116,53 @@ function buildFieldList(lean, summary, useColors, now) {
|
|
|
3124
3116
|
value: `${formatCompactNumber(lean.downloads.total)} total`
|
|
3125
3117
|
});
|
|
3126
3118
|
}
|
|
3127
|
-
if (lean.
|
|
3128
|
-
fields.push({
|
|
3129
|
-
|
|
3130
|
-
|
|
3131
|
-
|
|
3119
|
+
if (lean.vulnerabilities) {
|
|
3120
|
+
fields.push({
|
|
3121
|
+
label: "Vulnerabilities",
|
|
3122
|
+
value: formatVulnerabilityStatus(lean.vulnerabilities)
|
|
3123
|
+
});
|
|
3132
3124
|
}
|
|
3133
3125
|
const labelWidth = Math.max(10, ...fields.map((field) => field.label.length));
|
|
3134
3126
|
return fields.map((field) => `${field.label.padEnd(labelWidth)} ${field.value}`);
|
|
3135
3127
|
}
|
|
3136
|
-
function
|
|
3128
|
+
function formatGithubPopularity(github) {
|
|
3129
|
+
if (!github)
|
|
3130
|
+
return;
|
|
3137
3131
|
const parts = [];
|
|
3132
|
+
if (github.archived) {
|
|
3133
|
+
parts.push("[ARCHIVED]");
|
|
3134
|
+
}
|
|
3138
3135
|
if (github.stars !== undefined) {
|
|
3139
|
-
parts.push(
|
|
3136
|
+
parts.push(`${formatCompactNumber(github.stars)} stars`);
|
|
3140
3137
|
}
|
|
3141
3138
|
if (github.forks !== undefined) {
|
|
3142
3139
|
parts.push(`${formatCompactNumber(github.forks)} forks`);
|
|
3143
3140
|
}
|
|
3144
3141
|
if (github.openIssues !== undefined) {
|
|
3145
|
-
parts.push(`${formatCompactNumber(github.openIssues)}
|
|
3142
|
+
parts.push(`${formatCompactNumber(github.openIssues)} issues`);
|
|
3146
3143
|
}
|
|
3147
|
-
|
|
3148
|
-
parts.push("archived");
|
|
3149
|
-
}
|
|
3150
|
-
return parts.join(" · ");
|
|
3144
|
+
return parts.length > 0 ? parts.join(", ") : undefined;
|
|
3151
3145
|
}
|
|
3152
|
-
function
|
|
3146
|
+
function formatVulnerabilityStatus(vulns) {
|
|
3147
|
+
if (vulns.total === 0) {
|
|
3148
|
+
return "No active vulnerabilities in latest published version";
|
|
3149
|
+
}
|
|
3153
3150
|
const noun = vulns.total === 1 ? "vulnerability" : "vulnerabilities";
|
|
3154
|
-
|
|
3155
|
-
|
|
3156
|
-
|
|
3151
|
+
if (vulns.affectsLatest) {
|
|
3152
|
+
return `${vulns.total} active ${noun}; latest affected`;
|
|
3153
|
+
}
|
|
3154
|
+
return `${vulns.total} known ${noun}; latest not affected`;
|
|
3157
3155
|
}
|
|
3158
3156
|
function buildVerboseSections(lean, useColors) {
|
|
3159
3157
|
const blocks = [];
|
|
3160
|
-
if (lean.
|
|
3161
|
-
|
|
3162
|
-
|
|
3163
|
-
|
|
3164
|
-
`).map((line) => ` ${line}`).join(`
|
|
3165
|
-
`)
|
|
3166
|
-
].join(`
|
|
3167
|
-
`));
|
|
3158
|
+
if (lean.github) {
|
|
3159
|
+
const github = formatVerboseGithub(lean.github, useColors);
|
|
3160
|
+
if (github)
|
|
3161
|
+
blocks.push(github);
|
|
3168
3162
|
}
|
|
3169
3163
|
if (lean.vulnerabilities?.recent && lean.vulnerabilities.recent.length > 0) {
|
|
3170
3164
|
blocks.push(formatVerboseAdvisories(lean.vulnerabilities.recent, useColors));
|
|
3171
3165
|
}
|
|
3172
|
-
if (lean.github?.topics && lean.github.topics.length > 0) {
|
|
3173
|
-
blocks.push(`${"Topics".padEnd(10)} ${lean.github.topics.join(", ")}`);
|
|
3174
|
-
}
|
|
3175
3166
|
if (lean.recentChanges && lean.recentChanges.length > 0) {
|
|
3176
3167
|
blocks.push(formatVerboseChanges(lean.recentChanges, useColors));
|
|
3177
3168
|
}
|
|
@@ -3179,6 +3170,23 @@ function buildVerboseSections(lean, useColors) {
|
|
|
3179
3170
|
|
|
3180
3171
|
`);
|
|
3181
3172
|
}
|
|
3173
|
+
function formatVerboseGithub(github, useColors) {
|
|
3174
|
+
const fields = [];
|
|
3175
|
+
if (github.language)
|
|
3176
|
+
fields.push({ label: "Language", value: github.language });
|
|
3177
|
+
if (github.lastPushedAt) {
|
|
3178
|
+
fields.push({ label: "Last pushed", value: github.lastPushedAt });
|
|
3179
|
+
}
|
|
3180
|
+
if (github.topics && github.topics.length > 0) {
|
|
3181
|
+
fields.push({ label: "Topics", value: github.topics.join(", ") });
|
|
3182
|
+
}
|
|
3183
|
+
const labelWidth = Math.max(10, ...fields.map((field) => field.label.length));
|
|
3184
|
+
return fields.length > 0 ? [
|
|
3185
|
+
highlight("GitHub", useColors),
|
|
3186
|
+
...fields.map((field) => ` ${field.label.padEnd(labelWidth)} ${field.value}`)
|
|
3187
|
+
].join(`
|
|
3188
|
+
`) : undefined;
|
|
3189
|
+
}
|
|
3182
3190
|
function formatVerboseAdvisories(advisories, useColors) {
|
|
3183
3191
|
const labelWidth = Math.max(...advisories.map((a) => (a.severityLabel ?? "").length));
|
|
3184
3192
|
const lines = [highlight("Recent advisories", useColors)];
|
|
@@ -3228,12 +3236,22 @@ var SUPPORTED_VULN_REGISTRIES = new Set([
|
|
|
3228
3236
|
"NPM",
|
|
3229
3237
|
"PYPI",
|
|
3230
3238
|
"HEX",
|
|
3231
|
-
"CRATES"
|
|
3239
|
+
"CRATES",
|
|
3240
|
+
"NUGET",
|
|
3241
|
+
"MAVEN",
|
|
3242
|
+
"PACKAGIST",
|
|
3243
|
+
"RUBYGEMS",
|
|
3244
|
+
"GO"
|
|
3232
3245
|
]);
|
|
3233
|
-
var SUPPORTED_VULN_REGISTRIES_HUMAN = "npm, pypi, hex, and
|
|
3246
|
+
var SUPPORTED_VULN_REGISTRIES_HUMAN = "npm, pypi, hex, crates, nuget, maven, packagist, rubygems, and go";
|
|
3234
3247
|
function supportsVulnerabilitiesRegistry(registry) {
|
|
3235
3248
|
return SUPPORTED_VULN_REGISTRIES.has(registry);
|
|
3236
3249
|
}
|
|
3250
|
+
var ADVISORY_SCOPE_TO_GRAPHQL = {
|
|
3251
|
+
affected: "AFFECTED",
|
|
3252
|
+
non_affecting: "NON_AFFECTING",
|
|
3253
|
+
all: "ALL"
|
|
3254
|
+
};
|
|
3237
3255
|
function buildPackageVulnerabilitiesParams(input) {
|
|
3238
3256
|
const trimmedName = input.packageName?.trim() ?? "";
|
|
3239
3257
|
if (!trimmedName) {
|
|
@@ -3247,22 +3265,27 @@ function buildPackageVulnerabilitiesParams(input) {
|
|
|
3247
3265
|
if (!supportsVulnerabilitiesRegistry(registry)) {
|
|
3248
3266
|
throw new UnsupportedVulnerabilitiesRegistryError(`pkg vulns only supports ${SUPPORTED_VULN_REGISTRIES_HUMAN}. Got: ${normalisedRegistryArg}.`);
|
|
3249
3267
|
}
|
|
3250
|
-
const
|
|
3268
|
+
const severityLabel2 = resolveMinSeverityLabel(input.minSeverity);
|
|
3269
|
+
const minSeverity = severityLabel2 !== undefined ? SEVERITY_LABEL_TO_CVSS[severityLabel2] : undefined;
|
|
3251
3270
|
const trimmedVersion = input.version?.trim();
|
|
3252
3271
|
if (trimmedVersion && /^v\d/i.test(trimmedVersion)) {
|
|
3253
3272
|
throw new InvalidPackageSpecError(`Invalid version '${trimmedVersion}'. Use the canonical package version without a leading 'v' (for example '4.18.0', not 'v4.18.0').`);
|
|
3254
3273
|
}
|
|
3274
|
+
const advisoryScope = resolveAdvisoryScope(input.advisoryScope);
|
|
3275
|
+
const filterWithScope = buildFilterEcho3(severityLabel2, input.includeWithdrawn, advisoryScope);
|
|
3255
3276
|
return {
|
|
3256
3277
|
params: {
|
|
3257
3278
|
registry,
|
|
3258
3279
|
packageName: trimmedName,
|
|
3259
3280
|
version: trimmedVersion && trimmedVersion.length > 0 ? trimmedVersion : undefined,
|
|
3260
3281
|
minSeverity,
|
|
3261
|
-
includeWithdrawn: input.includeWithdrawn
|
|
3262
|
-
|
|
3282
|
+
includeWithdrawn: input.includeWithdrawn,
|
|
3283
|
+
advisoryScope: advisoryScope ? ADVISORY_SCOPE_TO_GRAPHQL[advisoryScope] : undefined
|
|
3284
|
+
},
|
|
3285
|
+
...filterWithScope ? { filter: filterWithScope } : {}
|
|
3263
3286
|
};
|
|
3264
3287
|
}
|
|
3265
|
-
function
|
|
3288
|
+
function resolveMinSeverityLabel(raw) {
|
|
3266
3289
|
if (raw === undefined)
|
|
3267
3290
|
return;
|
|
3268
3291
|
const trimmed = raw.trim();
|
|
@@ -3272,12 +3295,36 @@ function resolveMinSeverity(raw) {
|
|
|
3272
3295
|
if (!isSeverityLabel(lower)) {
|
|
3273
3296
|
throw new InvalidPackageSpecError(`Unsupported severity '${raw}'. Expected one of: low, medium, high, critical.`);
|
|
3274
3297
|
}
|
|
3275
|
-
return
|
|
3298
|
+
return lower;
|
|
3299
|
+
}
|
|
3300
|
+
function buildFilterEcho3(minSeverity, includeWithdrawn, advisoryScope) {
|
|
3301
|
+
const filter = {};
|
|
3302
|
+
if (minSeverity !== undefined)
|
|
3303
|
+
filter.minSeverity = minSeverity;
|
|
3304
|
+
if (includeWithdrawn === true)
|
|
3305
|
+
filter.includeWithdrawn = true;
|
|
3306
|
+
if (advisoryScope !== undefined && advisoryScope !== "affected") {
|
|
3307
|
+
filter.advisoryScope = advisoryScope;
|
|
3308
|
+
}
|
|
3309
|
+
return Object.keys(filter).length > 0 ? filter : undefined;
|
|
3310
|
+
}
|
|
3311
|
+
function resolveAdvisoryScope(raw) {
|
|
3312
|
+
if (raw === undefined)
|
|
3313
|
+
return;
|
|
3314
|
+
const trimmed = raw.trim();
|
|
3315
|
+
if (trimmed.length === 0)
|
|
3316
|
+
return;
|
|
3317
|
+
const lower = trimmed.toLowerCase().replace(/-/g, "_");
|
|
3318
|
+
if (lower === "affected" || lower === "non_affecting" || lower === "all") {
|
|
3319
|
+
return lower;
|
|
3320
|
+
}
|
|
3321
|
+
throw new InvalidPackageSpecError(`Unsupported advisory scope '${raw}'. Expected one of: affected, non_affecting, all.`);
|
|
3276
3322
|
}
|
|
3277
3323
|
function isSeverityLabel(value) {
|
|
3278
3324
|
return value === "low" || value === "medium" || value === "high" || value === "critical";
|
|
3279
3325
|
}
|
|
3280
3326
|
// src/shared/package-vulnerabilities-response.ts
|
|
3327
|
+
var DEFAULT_ADVISORY_CAP = 5;
|
|
3281
3328
|
function buildPackageVulnerabilitiesSuccessPayload(report, options = {}) {
|
|
3282
3329
|
const pkg = report.package;
|
|
3283
3330
|
const security = report.security;
|
|
@@ -3293,11 +3340,12 @@ function buildPackageVulnerabilitiesSuccessPayload(report, options = {}) {
|
|
|
3293
3340
|
if (requestedEcho !== undefined) {
|
|
3294
3341
|
payload.requestedVersion = requestedEcho;
|
|
3295
3342
|
}
|
|
3296
|
-
if (
|
|
3297
|
-
|
|
3298
|
-
|
|
3299
|
-
|
|
3300
|
-
|
|
3343
|
+
if (options.filter !== undefined) {
|
|
3344
|
+
payload.filter = options.filter;
|
|
3345
|
+
}
|
|
3346
|
+
const sortedAdvisories = sortAdvisories(dedupedAdvisories.map(buildAdvisory));
|
|
3347
|
+
if (sortedAdvisories.length > 0) {
|
|
3348
|
+
payload.advisories = sortedAdvisories;
|
|
3301
3349
|
}
|
|
3302
3350
|
const upgradePaths = security?.upgradePaths;
|
|
3303
3351
|
if (upgradePaths && upgradePaths.length > 0) {
|
|
@@ -3343,7 +3391,7 @@ function buildSummary(total, security, dedupedAdvisories) {
|
|
|
3343
3391
|
if (typeof security?.currentVersionAffected === "boolean") {
|
|
3344
3392
|
summary.affected = security.currentVersionAffected;
|
|
3345
3393
|
}
|
|
3346
|
-
if (
|
|
3394
|
+
if (dedupedAdvisories.length === 0)
|
|
3347
3395
|
return summary;
|
|
3348
3396
|
const bySeverity = computeBySeverity(dedupedAdvisories);
|
|
3349
3397
|
const anyCounted = Object.values(bySeverity).some((n) => n > 0);
|
|
@@ -3731,17 +3779,25 @@ function lowerRegistry3(value) {
|
|
|
3731
3779
|
}
|
|
3732
3780
|
function formatPackageVulnerabilitiesTerminal(report, options = {}) {
|
|
3733
3781
|
const payload = buildPackageVulnerabilitiesSuccessPayload(report, {
|
|
3734
|
-
requestedVersion: options.requestedVersion
|
|
3782
|
+
requestedVersion: options.requestedVersion,
|
|
3783
|
+
filter: options.filter
|
|
3735
3784
|
});
|
|
3736
3785
|
const useColors = options.useColors ?? false;
|
|
3737
3786
|
const verbose = options.verbose ?? false;
|
|
3787
|
+
const surface = options.surface ?? "cli";
|
|
3738
3788
|
const headerLine = formatHeader(payload, useColors);
|
|
3739
3789
|
const requestedLine = payload.requestedVersion ? dim(`(requested ${payload.requestedVersion})`, useColors) : undefined;
|
|
3790
|
+
const filterLines = formatFilterLines(payload.filter);
|
|
3740
3791
|
if (payload.summary.total === 0) {
|
|
3741
3792
|
const lines = [headerLine];
|
|
3742
3793
|
if (requestedLine)
|
|
3743
3794
|
lines.push(requestedLine);
|
|
3795
|
+
lines.push(...filterLines);
|
|
3744
3796
|
lines.push(formatNoAffectedVulnerabilitiesLine(payload));
|
|
3797
|
+
if (payload.advisories && payload.advisories.length > 0) {
|
|
3798
|
+
const rangeLimit = resolveAffectedRangesLimit(options.terminalWidth);
|
|
3799
|
+
lines.push("", formatAdvisoryList(payload.advisories, verbose, useColors, rangeLimit, surface));
|
|
3800
|
+
}
|
|
3745
3801
|
return `${lines.join(`
|
|
3746
3802
|
`)}
|
|
3747
3803
|
`;
|
|
@@ -3750,15 +3806,21 @@ function formatPackageVulnerabilitiesTerminal(report, options = {}) {
|
|
|
3750
3806
|
const headerBlock = [headerLine];
|
|
3751
3807
|
if (requestedLine)
|
|
3752
3808
|
headerBlock.push(requestedLine);
|
|
3809
|
+
headerBlock.push(...filterLines);
|
|
3753
3810
|
headerBlock.push(formatSummaryLine(payload, useColors));
|
|
3754
|
-
const
|
|
3811
|
+
const selectedAdvisoryCount = payload.advisories?.length ?? 0;
|
|
3812
|
+
const scope = payload.filter?.advisoryScope;
|
|
3813
|
+
const selectedCountLine = formatSelectedAdvisoryCountLine(selectedAdvisoryCount, scope);
|
|
3814
|
+
if (selectedCountLine)
|
|
3815
|
+
headerBlock.push(selectedCountLine);
|
|
3816
|
+
const breakdown = scope === undefined ? formatBreakdownLine(payload.summary, useColors) : undefined;
|
|
3755
3817
|
if (breakdown)
|
|
3756
3818
|
headerBlock.push(breakdown);
|
|
3757
3819
|
blocks.push(headerBlock.join(`
|
|
3758
3820
|
`));
|
|
3759
3821
|
if (payload.advisories && payload.advisories.length > 0) {
|
|
3760
3822
|
const rangeLimit = resolveAffectedRangesLimit(options.terminalWidth);
|
|
3761
|
-
blocks.push(formatAdvisoryList(payload.advisories, verbose, useColors, rangeLimit));
|
|
3823
|
+
blocks.push(formatAdvisoryList(payload.advisories, verbose, useColors, rangeLimit, surface));
|
|
3762
3824
|
}
|
|
3763
3825
|
const upgradeFooter = formatUpgradeFooter(payload.upgradePaths);
|
|
3764
3826
|
if (upgradeFooter)
|
|
@@ -3770,7 +3832,29 @@ function formatPackageVulnerabilitiesTerminal(report, options = {}) {
|
|
|
3770
3832
|
}
|
|
3771
3833
|
function formatHeader(payload, useColors) {
|
|
3772
3834
|
const name = colorize(payload.name, "bold", useColors);
|
|
3773
|
-
return `${name} @ ${payload.version}
|
|
3835
|
+
return `${name} @ ${payload.version} | ${payload.registry}`;
|
|
3836
|
+
}
|
|
3837
|
+
function formatFilterLines(filter) {
|
|
3838
|
+
if (!filter)
|
|
3839
|
+
return [];
|
|
3840
|
+
const lines = [];
|
|
3841
|
+
if (filter.advisoryScope) {
|
|
3842
|
+
lines.push(`Scope ${formatAdvisoryScope(filter.advisoryScope)}`);
|
|
3843
|
+
}
|
|
3844
|
+
if (filter.minSeverity) {
|
|
3845
|
+
lines.push(`Filter severity >= ${filter.minSeverity}`);
|
|
3846
|
+
}
|
|
3847
|
+
if (filter.includeWithdrawn === true) {
|
|
3848
|
+
lines.push("Filter include withdrawn");
|
|
3849
|
+
}
|
|
3850
|
+
return lines;
|
|
3851
|
+
}
|
|
3852
|
+
function formatAdvisoryScope(scope) {
|
|
3853
|
+
if (scope === "non_affecting")
|
|
3854
|
+
return "historical advisories only";
|
|
3855
|
+
if (scope === "all")
|
|
3856
|
+
return "all package advisories";
|
|
3857
|
+
return scope;
|
|
3774
3858
|
}
|
|
3775
3859
|
function formatSummaryLine(payload, useColors) {
|
|
3776
3860
|
const n = payload.summary.total;
|
|
@@ -3786,13 +3870,41 @@ function formatSummaryLine(payload, useColors) {
|
|
|
3786
3870
|
return base;
|
|
3787
3871
|
}
|
|
3788
3872
|
function formatNoAffectedVulnerabilitiesLine(payload) {
|
|
3873
|
+
const selectedAdvisoryCount = payload.advisories?.length ?? 0;
|
|
3874
|
+
if (payload.filter?.advisoryScope === "non_affecting") {
|
|
3875
|
+
if (selectedAdvisoryCount > 0) {
|
|
3876
|
+
return "No active vulnerabilities affect this version; historical advisories are listed below.";
|
|
3877
|
+
}
|
|
3878
|
+
return "No active vulnerabilities affect this version; no historical advisories match the current filter.";
|
|
3879
|
+
}
|
|
3880
|
+
if (payload.filter?.advisoryScope === "all") {
|
|
3881
|
+
if (selectedAdvisoryCount > 0) {
|
|
3882
|
+
return "No active vulnerabilities affect this version; package advisories are listed below.";
|
|
3883
|
+
}
|
|
3884
|
+
return "No active vulnerabilities affect this version; no package advisories match the current filter.";
|
|
3885
|
+
}
|
|
3886
|
+
if (payload.filter !== undefined) {
|
|
3887
|
+
return "No vulnerabilities matching the filter affect this version.";
|
|
3888
|
+
}
|
|
3789
3889
|
const historical = payload.summary.nonAffectingVulnerabilityCount ?? 0;
|
|
3790
3890
|
if (historical > 0) {
|
|
3791
3891
|
const noun = historical === 1 ? "historical advisory" : "historical advisories";
|
|
3792
3892
|
const verb = historical === 1 ? "does" : "do";
|
|
3793
|
-
return `No vulnerabilities affect this version (${historical} ${noun} ${verb} not apply).`;
|
|
3893
|
+
return `No active vulnerabilities affect this version (${historical} ${noun} ${verb} not apply).`;
|
|
3794
3894
|
}
|
|
3795
|
-
return "No
|
|
3895
|
+
return "No active vulnerabilities affect this version.";
|
|
3896
|
+
}
|
|
3897
|
+
function formatSelectedAdvisoryCountLine(count, scope) {
|
|
3898
|
+
if (scope === undefined)
|
|
3899
|
+
return;
|
|
3900
|
+
const noun = count === 1 ? "advisory" : "advisories";
|
|
3901
|
+
if (scope === "non_affecting") {
|
|
3902
|
+
return ` showing ${count} historical ${noun} that do not affect this version`;
|
|
3903
|
+
}
|
|
3904
|
+
if (scope === "all") {
|
|
3905
|
+
return ` showing ${count} package ${noun} across affected and historical scopes`;
|
|
3906
|
+
}
|
|
3907
|
+
return;
|
|
3796
3908
|
}
|
|
3797
3909
|
function formatBreakdownLine(summary, useColors) {
|
|
3798
3910
|
if (summary.total <= 1)
|
|
@@ -3818,22 +3930,31 @@ function formatBreakdownLine(summary, useColors) {
|
|
|
3818
3930
|
}
|
|
3819
3931
|
if (parts.length === 0)
|
|
3820
3932
|
return;
|
|
3821
|
-
return ` ${parts.join("
|
|
3933
|
+
return ` ${parts.join(" | ")}`;
|
|
3822
3934
|
}
|
|
3823
|
-
function formatAdvisoryList(advisories, verbose, useColors, rangeLimit) {
|
|
3824
|
-
const
|
|
3935
|
+
function formatAdvisoryList(advisories, verbose, useColors, rangeLimit, surface) {
|
|
3936
|
+
const renderedAdvisories = verbose ? advisories : advisories.slice(0, DEFAULT_ADVISORY_CAP);
|
|
3937
|
+
const labelWidth = Math.max(...renderedAdvisories.map((a) => severityColumnLabel(a).length));
|
|
3825
3938
|
const lines = [];
|
|
3826
|
-
for (const advisory of
|
|
3827
|
-
lines.push(...formatAdvisoryLines(advisory, labelWidth, verbose, useColors, rangeLimit));
|
|
3939
|
+
for (const advisory of renderedAdvisories) {
|
|
3940
|
+
lines.push(...formatAdvisoryLines(advisory, labelWidth, verbose, useColors, rangeLimit, surface));
|
|
3828
3941
|
lines.push("");
|
|
3829
3942
|
}
|
|
3943
|
+
const hidden = advisories.length - renderedAdvisories.length;
|
|
3944
|
+
if (hidden > 0) {
|
|
3945
|
+
lines.push(dim(formatAdvisoryCapHint(hidden, surface), useColors));
|
|
3946
|
+
}
|
|
3830
3947
|
return lines.join(`
|
|
3831
3948
|
`).trimEnd();
|
|
3832
3949
|
}
|
|
3950
|
+
function formatAdvisoryCapHint(hidden, surface) {
|
|
3951
|
+
const hint = surface === "mcp" ? "use verbose=true or format=json" : "use -v";
|
|
3952
|
+
return `... (+${hidden} more; ${hint})`;
|
|
3953
|
+
}
|
|
3833
3954
|
function severityColumnLabel(advisory) {
|
|
3834
3955
|
if (advisory.isMalicious === true) {
|
|
3835
3956
|
if (advisory.severityLabel)
|
|
3836
|
-
return `MALWARE
|
|
3957
|
+
return `MALWARE | ${advisory.severityLabel}`;
|
|
3837
3958
|
return "MALWARE";
|
|
3838
3959
|
}
|
|
3839
3960
|
return advisory.severityLabel ?? "unrated";
|
|
@@ -3862,7 +3983,7 @@ function severityColumnColor(advisory, useColors, padded) {
|
|
|
3862
3983
|
return dim(padded, useColors);
|
|
3863
3984
|
}
|
|
3864
3985
|
}
|
|
3865
|
-
function formatAdvisoryLines(advisory, labelWidth, verbose, useColors, rangeLimit) {
|
|
3986
|
+
function formatAdvisoryLines(advisory, labelWidth, verbose, useColors, rangeLimit, surface) {
|
|
3866
3987
|
const rawLabel = severityColumnLabel(advisory);
|
|
3867
3988
|
const padded = rawLabel.padEnd(labelWidth);
|
|
3868
3989
|
const colouredLabel = severityColumnColor(advisory, useColors, padded);
|
|
@@ -3879,7 +4000,7 @@ function formatAdvisoryLines(advisory, labelWidth, verbose, useColors, rangeLimi
|
|
|
3879
4000
|
lines.push(` ${label.padEnd(detailWidth)} ${value}`);
|
|
3880
4001
|
};
|
|
3881
4002
|
if (advisory.affectedRanges && advisory.affectedRanges.length > 0) {
|
|
3882
|
-
pushRow("affected", formatRangeList(advisory.affectedRanges, verbose, useColors, rangeLimit, advisory.affectedVersionRangesCount, advisory.affectedVersionRangesTruncated));
|
|
4003
|
+
pushRow("affected", formatRangeList(advisory.affectedRanges, verbose, useColors, rangeLimit, surface, advisory.affectedVersionRangesCount, advisory.affectedVersionRangesTruncated));
|
|
3883
4004
|
}
|
|
3884
4005
|
if (advisory.fixedIn && advisory.fixedIn.length > 0) {
|
|
3885
4006
|
pushRow("fixed in", advisory.fixedIn.join(", "));
|
|
@@ -3906,12 +4027,12 @@ function formatAdvisoryLines(advisory, labelWidth, verbose, useColors, rangeLimi
|
|
|
3906
4027
|
}
|
|
3907
4028
|
return lines;
|
|
3908
4029
|
}
|
|
3909
|
-
function formatRangeList(ranges, verbose, useColors, limit, totalCount, backendTruncated) {
|
|
4030
|
+
function formatRangeList(ranges, verbose, useColors, limit, surface, totalCount, backendTruncated) {
|
|
3910
4031
|
const actualTotal = Math.max(totalCount ?? ranges.length, ranges.length);
|
|
3911
4032
|
const backendHidden = backendTruncated === true ? actualTotal - ranges.length : 0;
|
|
3912
4033
|
const appendBackendHint = (shown2) => {
|
|
3913
4034
|
if (backendHidden > 0) {
|
|
3914
|
-
const hint2 = dim(
|
|
4035
|
+
const hint2 = dim(`... (+${backendHidden} ranges omitted by service)`, useColors);
|
|
3915
4036
|
return shown2.length > 0 ? `${shown2}, ${hint2}` : hint2;
|
|
3916
4037
|
}
|
|
3917
4038
|
return shown2;
|
|
@@ -3921,7 +4042,8 @@ function formatRangeList(ranges, verbose, useColors, limit, totalCount, backendT
|
|
|
3921
4042
|
}
|
|
3922
4043
|
const shown = ranges.slice(0, limit).join(", ");
|
|
3923
4044
|
const localHidden = ranges.length - limit;
|
|
3924
|
-
const
|
|
4045
|
+
const localHint = surface === "mcp" ? "use verbose=true" : "use -v";
|
|
4046
|
+
const hintText = backendHidden > 0 ? `... (+${localHidden} more with ${localHint}; +${backendHidden} omitted by service)` : `... (+${localHidden} more; ${localHint})`;
|
|
3925
4047
|
const hint = dim(hintText, useColors);
|
|
3926
4048
|
return `${shown}, ${hint}`;
|
|
3927
4049
|
}
|
|
@@ -4615,11 +4737,11 @@ function buildUnifiedSearchParams(input) {
|
|
|
4615
4737
|
}
|
|
4616
4738
|
function resolveTargets(target, targets) {
|
|
4617
4739
|
if (target && targets) {
|
|
4618
|
-
throw new InvalidArgumentError("Provide either target or targets, not both.");
|
|
4740
|
+
throw new InvalidArgumentError("Provide either `target` for one search target or `targets` for multiple, not both.");
|
|
4619
4741
|
}
|
|
4620
4742
|
const resolved = target ? [target] : targets ?? [];
|
|
4621
4743
|
if (resolved.length === 0) {
|
|
4622
|
-
throw new InvalidArgumentError("
|
|
4744
|
+
throw new InvalidArgumentError("Provide either `target` for one search target or `targets` for multiple; neither was set.");
|
|
4623
4745
|
}
|
|
4624
4746
|
const deduped = [];
|
|
4625
4747
|
const seen = new Set;
|
|
@@ -4738,7 +4860,7 @@ function combineWarnings(parserWarnings, sourceStatus, hits = [], progress) {
|
|
|
4738
4860
|
out.push(...buildHitFreshnessWarnings(hits));
|
|
4739
4861
|
out.push(...buildProgressFreshnessWarnings(progress));
|
|
4740
4862
|
out.push(...buildSourceStatusWarnings(sourceStatus));
|
|
4741
|
-
return out;
|
|
4863
|
+
return Array.from(new Set(out));
|
|
4742
4864
|
}
|
|
4743
4865
|
function buildUnifiedSearchErrorPayload(error2) {
|
|
4744
4866
|
const mapped = mapCodeNavigationError(error2);
|
|
@@ -4949,7 +5071,7 @@ function compactProgress(progress) {
|
|
|
4949
5071
|
payload.requestedTargets = progress.requestedTargets;
|
|
4950
5072
|
}
|
|
4951
5073
|
if (progress.filters)
|
|
4952
|
-
payload.filters =
|
|
5074
|
+
payload.filters = buildFilterEcho4(progress.filters);
|
|
4953
5075
|
if (typeof progress.limit === "number")
|
|
4954
5076
|
payload.limit = progress.limit;
|
|
4955
5077
|
if (typeof progress.offset === "number")
|
|
@@ -4996,7 +5118,7 @@ function compactProgressTarget(target) {
|
|
|
4996
5118
|
payload.requestedRefKind = target.requestedRefKind;
|
|
4997
5119
|
return Object.keys(payload).length > 0 ? payload : undefined;
|
|
4998
5120
|
}
|
|
4999
|
-
function
|
|
5121
|
+
function buildFilterEcho4(filters) {
|
|
5000
5122
|
const echo = {};
|
|
5001
5123
|
if (filters.kind)
|
|
5002
5124
|
echo.kind = filters.kind.toLowerCase();
|
|
@@ -6271,7 +6393,7 @@ grep run. --symbol-field hydrates enclosing symbol metadata (appears under each
|
|
|
6271
6393
|
match in --verbose output; full payload in --json).`;
|
|
6272
6394
|
function registerCodeGrepCommand(pkgCommand) {
|
|
6273
6395
|
return pkgCommand.command("grep").summary("Deterministic text grep over indexed dependency source").description(PKG_GREP_DESCRIPTION).argument("[spec-or-pattern]", "Spec mode: package spec (e.g. npm:express). Repo mode (with --repo-url): the pattern.").argument("[pattern-or-prefix]", "Spec mode: the pattern. Repo mode: optional path-prefix.").argument("[path-prefix]", "Spec mode only: optional path-prefix. Ignored with --repo-url.").option("--repo-url <url>", "Repository URL addressing (requires --git-ref)").option("--git-ref <ref>", "Tag, commit, branch, or HEAD. Required with --repo-url.").option("--path <path>", "Exact file path to grep").option("--glob <glob>", "Glob scope (repeatable)", collectRepeatable2, []).option("--ext <ext>", "Extension filter without leading dot (repeatable)", collectRepeatable2, []).option("--regex", "Interpret the pattern as RE2 regex").option("--case-sensitive", "Enable ASCII case-sensitive matching").option("-C, --context <n>", "Context lines before and after each match (0-10)").option("-B, --before-context <n>", "Context lines before each match (0-10)").option("-A, --after-context <n>", "Context lines after each match (0-10)").option("--exclude-docs", "Skip files classified as documentation").option("--exclude-tests", "Skip files classified as tests").option("--limit <n>", "Max matches to return on this page (1-1000, default 50)").option("--per-file-limit <n>", "Cap matches per file within this page (0-1000, 0 = unlimited)").option("--cursor <cursor>", "Opaque nextCursor from a previous grep result").option("--symbol-field <field>", `Repeatable; surfaces in --json and under each --verbose match. ${GREP_REPO_SYMBOL_FIELDS_NOTE}`, collectRepeatable2, []).option("--wait <ms>", `Indexing wait timeout (0-${MAX_WAIT_TIMEOUT_MS}, default ${DEFAULT_WAIT_TIMEOUT_MS})`).option("-v, --verbose", "Render grouped output with file headers").option("--json", "Emit the JSON envelope").action(async (arg1, arg2, arg3, options) => {
|
|
6274
|
-
const { createContainer: createContainer2 } = await import("./shared/chunk-
|
|
6396
|
+
const { createContainer: createContainer2 } = await import("./shared/chunk-kmka6wpx.js");
|
|
6275
6397
|
const deps = await createContainer2();
|
|
6276
6398
|
await pkgGrepAction(arg1, arg2, arg3, options, {
|
|
6277
6399
|
codeNavigationService: deps.codeNavigationService,
|
|
@@ -6805,7 +6927,7 @@ function registerExampleCommand(program) {
|
|
|
6805
6927
|
});
|
|
6806
6928
|
}
|
|
6807
6929
|
async function loadContainer() {
|
|
6808
|
-
const { createContainer: createContainer2 } = await import("./shared/chunk-
|
|
6930
|
+
const { createContainer: createContainer2 } = await import("./shared/chunk-kmka6wpx.js");
|
|
6809
6931
|
return createContainer2();
|
|
6810
6932
|
}
|
|
6811
6933
|
// src/commands/feedback.ts
|
|
@@ -6833,17 +6955,25 @@ async function feedbackAction(solutionId, options, deps) {
|
|
|
6833
6955
|
process.exit(1);
|
|
6834
6956
|
}
|
|
6835
6957
|
}
|
|
6836
|
-
var FEEDBACK_DESCRIPTION = `Submit feedback on a
|
|
6958
|
+
var FEEDBACK_DESCRIPTION = `Submit feedback on a tool result or the GitHits experience.
|
|
6959
|
+
|
|
6960
|
+
Two modes:
|
|
6961
|
+
- Solution-tied: pass the [solution_id] from a prior 'githits example'
|
|
6962
|
+
result (shown at the bottom of the markdown / under 'solution_id'
|
|
6963
|
+
in --json) to anchor feedback to that specific result.
|
|
6964
|
+
- Generic: omit [solution_id] to send feedback about any command
|
|
6965
|
+
(search, pkg, docs, code) or the overall experience. A --message
|
|
6966
|
+
is strongly recommended here.
|
|
6837
6967
|
|
|
6838
|
-
|
|
6839
|
-
feedback or --reject for negative. Optionally add a message.
|
|
6968
|
+
Use --accept for positive feedback or --reject for negative.
|
|
6840
6969
|
|
|
6841
6970
|
Examples:
|
|
6842
6971
|
githits feedback abc123 --accept
|
|
6843
6972
|
githits feedback abc123 --reject -m "Example was outdated"
|
|
6844
|
-
githits feedback
|
|
6973
|
+
githits feedback --accept -m "code_grep regex is fast on npm:lodash"
|
|
6974
|
+
githits feedback --reject -m "search missing kotlin support"`;
|
|
6845
6975
|
function registerFeedbackCommand(program) {
|
|
6846
|
-
program.command("feedback").summary("Submit feedback on a
|
|
6976
|
+
program.command("feedback").summary("Submit feedback on a tool result or the GitHits experience").description(FEEDBACK_DESCRIPTION).argument("[solution_id]", "Solution ID from a prior 'githits example' result (omit for generic feedback)").addOption(new Option2("--accept", "Mark as helpful").conflicts("reject")).addOption(new Option2("--reject", "Mark as unhelpful").conflicts("accept")).option("-m, --message <text>", "Feedback explanation").option("--json", "Output as JSON for piping").action(async (solutionId, options) => {
|
|
6847
6977
|
try {
|
|
6848
6978
|
const deps = await createContainer();
|
|
6849
6979
|
await feedbackAction(solutionId, options, deps);
|
|
@@ -7908,13 +8038,17 @@ function classify3(operation, error2) {
|
|
|
7908
8038
|
|
|
7909
8039
|
// src/tools/feedback.ts
|
|
7910
8040
|
var schema = {
|
|
7911
|
-
solution_id: z.string().min(1).describe("
|
|
7912
|
-
accepted: z.boolean().describe("True
|
|
7913
|
-
feedback_text: z.string().optional().describe('Optional
|
|
8041
|
+
solution_id: z.string().min(1).optional().describe("Optional. Pass the `solution_id` from a prior `get_example` response (shown on the trailing line of the markdown result, or under the `solution_id` key in JSON mode) to anchor feedback to that specific result. Omit for generic feedback about any tool (code/package navigation, search, docs) or the overall experience."),
|
|
8042
|
+
accepted: z.boolean().describe("True for positive feedback (helpful/good), False for negative (unhelpful/bad). Always required."),
|
|
8043
|
+
feedback_text: z.string().optional().describe('Optional context (e.g., "This solved problem X" or "code_grep regex over npm:lodash missed Foo function"). Strongly recommended when `solution_id` is omitted, since there is no specific result to anchor to.')
|
|
7914
8044
|
};
|
|
7915
|
-
var DESCRIPTION = `Submit feedback on a GitHits
|
|
8045
|
+
var DESCRIPTION = `Submit feedback on a tool result or the GitHits experience.
|
|
8046
|
+
|
|
8047
|
+
Two modes:
|
|
8048
|
+
1. **Solution-tied** — pass the \`solution_id\` from a prior \`get_example\` response to rate that specific result.
|
|
8049
|
+
2. **Generic** — omit \`solution_id\` to send feedback about any tool (\`search\`, \`code_grep\`, \`code_read\`, \`code_files\`, \`docs_*\`, \`pkg_*\`) or the overall experience.
|
|
7916
8050
|
|
|
7917
|
-
|
|
8051
|
+
\`accepted\` is always required (true = positive, false = negative). Add \`feedback_text\` for context — strongly recommended in generic mode. Feeds ranking and product quality.`;
|
|
7918
8052
|
function createFeedbackTool(service) {
|
|
7919
8053
|
return {
|
|
7920
8054
|
name: "feedback",
|
|
@@ -7938,7 +8072,7 @@ var schema2 = {
|
|
|
7938
8072
|
query: z2.string().min(1).describe("Natural-language example-search query for canonical code examples."),
|
|
7939
8073
|
language: z2.string().min(1).optional().describe("Optional programming language. If omitted, GitHits tries to infer it automatically. Use search_language first only when you need to force a specific language and the exact name is uncertain."),
|
|
7940
8074
|
license_mode: z2.enum(["strict", "yolo", "custom"]).optional().describe("License filtering mode: strict (default), yolo, or custom."),
|
|
7941
|
-
format: z2.enum(["json", "text", "text-v1"]).optional().describe(
|
|
8075
|
+
format: z2.enum(["json", "text", "text-v1"]).optional().describe('Response format. Default `text-v1` returns markdown directly with a trailing `solution_id` line when available. Pass `format: "json"` for `{result, solution_id?}`.')
|
|
7942
8076
|
};
|
|
7943
8077
|
var DESCRIPTION2 = `Get verified, canonical code examples from global open source.
|
|
7944
8078
|
|
|
@@ -8063,7 +8197,7 @@ var schema3 = {
|
|
|
8063
8197
|
wait_timeout_ms: z4.number().optional(),
|
|
8064
8198
|
format: z4.enum(["json", "text", "text-v1"]).optional().describe('Response format. Default `text-v1` — compact line-oriented output (matches grouped by file with grep -A/-B notation for context). Pass `format: "json"` for the structured envelope. `text` is an alias for `text-v1`. Errors stay JSON-formatted in either mode for now.')
|
|
8065
8199
|
};
|
|
8066
|
-
var DESCRIPTION3 = "Deterministic text grep over indexed dependency and repository source files. " +
|
|
8200
|
+
var DESCRIPTION3 = "Deterministic text or regex grep over indexed dependency and repository source files. " + 'Use this when you know the pattern (literal by default; pass `pattern_type: "regex"` for RE2). ' + "Use `search` for discovery instead. " + "Whole-target grep is the default — narrow with `path`, `path_prefix`, `globs`, or `extensions` to keep responses small. " + "Each match's `path` chains into `code_read.path`; pick a window around `match.line` for `code_read.start_line` / `end_line`.";
|
|
8067
8201
|
function createGrepRepoTool(service) {
|
|
8068
8202
|
return {
|
|
8069
8203
|
name: "code_grep",
|
|
@@ -8156,9 +8290,9 @@ var schema4 = {
|
|
|
8156
8290
|
include_hidden: z5.boolean().optional(),
|
|
8157
8291
|
limit: z5.number().optional().describe("Max entries to return (1–1000, default 200). Out-of-range values return an `INVALID_ARGUMENT` envelope."),
|
|
8158
8292
|
wait_timeout_ms: z5.number().optional().describe("Max milliseconds to wait for indexing (0–60000, default 20000). On an `INDEXING` error envelope, retry with a longer timeout or pass a version from `details.availableVersions`."),
|
|
8159
|
-
format: z5.enum(["json", "text", "text-v1"]).optional().describe('Response format. Default `text-v1` — compact paths-only listing
|
|
8293
|
+
format: z5.enum(["json", "text", "text-v1"]).optional().describe('Response format. Default `text-v1` — compact paths-only listing. Pass `format: "json"` for the structured envelope. `text` is an alias for `text-v1`. Errors stay JSON-formatted in either mode for now.')
|
|
8160
8294
|
};
|
|
8161
|
-
var DESCRIPTION4 = "List files in an indexed dependency.
|
|
8295
|
+
var DESCRIPTION4 = "List files in an indexed dependency. Use this to discover paths " + "before `code_read` (when `code_read` returns `FILE_NOT_FOUND` or " + "you don't yet know the path) and to scope `code_grep`. Address " + "via `target.registry` + `target.package_name` (package scope) or " + "`target.repo_url` + `target.git_ref` (repo scope), mutually " + "exclusive. Narrow with `path`, `path_prefix`, `globs`, " + "`extensions`, `file_types`, `languages`, or file-intent filters. " + "JSON envelope shape: `{total, hasMore, files: [{path, name, " + "language, fileType, byteSize}], resolution, indexedVersion}`. " + "Returns an `INDEXING` error envelope when the dependency is being " + "indexed on-demand — retry with a longer `wait_timeout_ms` or use " + "a version from `details.availableVersions`.";
|
|
8162
8296
|
function createListFilesTool(service) {
|
|
8163
8297
|
return {
|
|
8164
8298
|
name: "code_files",
|
|
@@ -8451,11 +8585,11 @@ function formatPackageChangelogTerminal(envelope, options) {
|
|
|
8451
8585
|
const dateWidth = 10;
|
|
8452
8586
|
for (const entry of envelope.entries.items) {
|
|
8453
8587
|
const version2 = entry.version ?? "(unversioned)";
|
|
8454
|
-
const date = entry.publishedAt ? formatDate(entry.publishedAt) : dim("
|
|
8588
|
+
const date = entry.publishedAt ? formatDate(entry.publishedAt) : dim("-", options.useColors);
|
|
8455
8589
|
const url = entry.htmlUrl ? dim(entry.htmlUrl, options.useColors) : dim("(no link)", options.useColors);
|
|
8456
8590
|
const padded = padColumn(version2, versionWidth);
|
|
8457
8591
|
const datePadded = padColumn(date, dateWidth);
|
|
8458
|
-
lines.push(`${
|
|
8592
|
+
lines.push(`${highlight(`${padded} ${datePadded}`, options.useColors)} ${url}`);
|
|
8459
8593
|
if (entry.body != null) {
|
|
8460
8594
|
appendBodyLines(lines, entry.body, options);
|
|
8461
8595
|
}
|
|
@@ -8472,28 +8606,28 @@ function appendBodyLines(lines, body, options) {
|
|
|
8472
8606
|
}
|
|
8473
8607
|
const bodyLines = body.split(`
|
|
8474
8608
|
`);
|
|
8475
|
-
const cap = options.verbose ? bodyLines.length : DEFAULT_BODY_PREVIEW_LINES;
|
|
8609
|
+
const cap = options.verbose ? bodyLines.length : options.bodyPreviewLines ?? DEFAULT_BODY_PREVIEW_LINES;
|
|
8476
8610
|
const visible = bodyLines.slice(0, cap);
|
|
8477
8611
|
for (const bodyLine of visible) {
|
|
8478
|
-
lines.push(` ${
|
|
8612
|
+
lines.push(` ${bodyLine}`);
|
|
8479
8613
|
}
|
|
8480
8614
|
const hidden = bodyLines.length - visible.length;
|
|
8481
8615
|
if (hidden > 0) {
|
|
8482
|
-
lines.push(` ${dim(
|
|
8616
|
+
lines.push(` ${dim(`... (+${hidden} more line${hidden === 1 ? "" : "s"} - ${options.fullBodyHint ?? "use --verbose for the full body"})`, options.useColors)}`);
|
|
8483
8617
|
}
|
|
8484
8618
|
}
|
|
8485
8619
|
function buildSummaryLine(envelope, options) {
|
|
8486
|
-
const identity = envelope.registry && envelope.name ? `${envelope.name}
|
|
8620
|
+
const identity = envelope.registry && envelope.name ? `${envelope.name} | ${envelope.registry}` : envelope.repoUrl ?? "(unknown)";
|
|
8487
8621
|
const sourceLabel = envelope.source ? humanizeSource(envelope.source) : "package versions";
|
|
8488
8622
|
const modeLabel = envelope.mode === "range" ? rangeLabel(envelope) : latestLabel(envelope);
|
|
8489
8623
|
const countLabel = `${envelope.entries.count} ${plural2("entry", "entries", envelope.entries.count)}`;
|
|
8490
8624
|
const parts = [identity, `source: ${sourceLabel}`, modeLabel, countLabel];
|
|
8491
|
-
return colorize(parts.join("
|
|
8625
|
+
return colorize(parts.join(" | "), "bold", options.useColors);
|
|
8492
8626
|
}
|
|
8493
8627
|
function rangeLabel(envelope) {
|
|
8494
8628
|
const from = envelope.filter?.fromVersion ?? "earliest";
|
|
8495
8629
|
const to = envelope.filter?.toVersion ?? "latest";
|
|
8496
|
-
return `range ${from}
|
|
8630
|
+
return `range ${from} -> ${to}`;
|
|
8497
8631
|
}
|
|
8498
8632
|
function latestLabel(envelope) {
|
|
8499
8633
|
if (envelope.filter?.toVersion) {
|
|
@@ -8552,9 +8686,11 @@ var schema6 = {
|
|
|
8552
8686
|
limit: z7.number().optional().describe("Latest-mode cap on entry count (1–50, default 10). Rejected with `INVALID_ARGUMENT` when `from_version` is also set or when out of range."),
|
|
8553
8687
|
git_ref: z7.string().optional().describe("Git branch or tag for CHANGELOG.md source (no effect on GitHub Releases or HexDocs). Defaults to the repository's default branch."),
|
|
8554
8688
|
include_bodies: z7.boolean().optional().describe("When false, each entry in `entries.items[]` omits its `body` field. Default true. Set false when you only need the version / date / URL timeline — drops 10 KB+ per entry on large release notes."),
|
|
8555
|
-
|
|
8689
|
+
verbose: z7.boolean().optional().describe("Text output only. Show full body previews. Mutually exclusive with include_bodies:false and body_lines."),
|
|
8690
|
+
body_lines: z7.number().optional().describe("Text output only. Number of body lines to preview per entry (1-50, default 10). Ignored for format=json and include_bodies:false. Mutually exclusive with verbose:true."),
|
|
8691
|
+
format: z7.enum(["json", "text", "text-v1"]).optional().describe('Response format. Default `text-v1` — compact entry timeline with body previews. Pass `format: "json"` for the structured envelope with full markdown bodies.')
|
|
8556
8692
|
};
|
|
8557
|
-
var DESCRIPTION6 = "Release notes for a package or GitHub repo, newest-first. Default " + "latest mode returns the ten most recent entries (`limit` 1–50). " + "With `from_version`, returns every entry in the " + "`[from_version, to_version]` range (range mode, no count cap). " + "Address via `registry` + `package_name` or `repo_url` (mutually " + 'exclusive). Response includes optional `source` (`"releases"` / ' + '`"changelog_file"` / `"hexdocs"`) when a concrete changelog source ' + 'exists, `mode` (`"latest"` or `"range"`),
|
|
8693
|
+
var DESCRIPTION6 = "Release notes for a package or GitHub repo, newest-first. Default " + "latest mode returns the ten most recent entries (`limit` 1–50). " + "With `from_version`, returns every entry in the " + "`[from_version, to_version]` range (range mode, no count cap). " + "Address via `registry` + `package_name` or `repo_url` (mutually " + 'exclusive). Response includes optional `source` (`"releases"` / ' + '`"changelog_file"` / `"hexdocs"`) when a concrete changelog source ' + 'exists, `mode` (`"latest"` or `"range"`), and entries with ' + "markdown body previews. Example: " + '`{"registry":"npm","package_name":"express","limit":2}`. ' + "Text output previews 10 body lines by default; use `body_lines` " + "to tune the preview or `verbose:true` for full text bodies. Set " + "`include_bodies: false` for a version / date / URL timeline only; " + 'pass `format: "json"` for the complete structured envelope. ' + "Package-version entries without changelog " + "text succeed with `source` omitted; no-source plus no entries " + "returns `NOT_FOUND`. Supports npm, PyPI, Hex, Crates, NuGet, " + "Maven, Zig, vcpkg, Packagist, RubyGems, and Go.";
|
|
8558
8694
|
function createPackageChangelogTool(service) {
|
|
8559
8695
|
return {
|
|
8560
8696
|
name: "pkg_changelog",
|
|
@@ -8563,6 +8699,8 @@ function createPackageChangelogTool(service) {
|
|
|
8563
8699
|
annotations: { readOnlyHint: true },
|
|
8564
8700
|
handler: async (args) => {
|
|
8565
8701
|
try {
|
|
8702
|
+
const textFormat = isTextFormat5(args.format);
|
|
8703
|
+
const bodyPreviewLines = textFormat ? validateTextOptions(args) : undefined;
|
|
8566
8704
|
const { params, explicitFilterFields } = buildPackageChangelogParams({
|
|
8567
8705
|
registry: args.registry,
|
|
8568
8706
|
packageName: args.package_name,
|
|
@@ -8585,11 +8723,12 @@ function createPackageChangelogTool(service) {
|
|
|
8585
8723
|
limit: params.limit,
|
|
8586
8724
|
gitRef: params.gitRef
|
|
8587
8725
|
});
|
|
8588
|
-
if (
|
|
8726
|
+
if (textFormat) {
|
|
8589
8727
|
return textResult(formatPackageChangelogTerminal(payload, {
|
|
8590
8728
|
useColors: false,
|
|
8591
|
-
verbose: false,
|
|
8592
|
-
|
|
8729
|
+
verbose: args.verbose ?? false,
|
|
8730
|
+
bodyPreviewLines,
|
|
8731
|
+
fullBodyHint: 'pass verbose=true, body_lines=<n>, or format="json" for full bodies'
|
|
8593
8732
|
}).trimEnd());
|
|
8594
8733
|
}
|
|
8595
8734
|
return textResult(JSON.stringify(payload));
|
|
@@ -8613,22 +8752,36 @@ function createPackageChangelogTool(service) {
|
|
|
8613
8752
|
}
|
|
8614
8753
|
};
|
|
8615
8754
|
}
|
|
8755
|
+
function validateTextOptions(args) {
|
|
8756
|
+
if (args.include_bodies === false && args.verbose === true) {
|
|
8757
|
+
throw new InvalidPackageSpecError("verbose:true conflicts with include_bodies:false because bodies are omitted. Drop one of the two options.");
|
|
8758
|
+
}
|
|
8759
|
+
if (args.verbose === true && args.body_lines !== undefined) {
|
|
8760
|
+
throw new InvalidPackageSpecError("body_lines conflicts with verbose:true because verbose already shows full bodies. Drop one of the two options.");
|
|
8761
|
+
}
|
|
8762
|
+
if (args.body_lines === undefined)
|
|
8763
|
+
return;
|
|
8764
|
+
if (!Number.isInteger(args.body_lines) || args.body_lines < 1 || args.body_lines > 50) {
|
|
8765
|
+
throw new InvalidPackageSpecError(`body_lines must be an integer between 1 and 50. Got ${args.body_lines}.`);
|
|
8766
|
+
}
|
|
8767
|
+
return args.body_lines;
|
|
8768
|
+
}
|
|
8616
8769
|
function isTextFormat5(format) {
|
|
8617
8770
|
return format === undefined || format === "text" || format === "text-v1";
|
|
8618
8771
|
}
|
|
8619
8772
|
// src/tools/package-dependencies.ts
|
|
8620
8773
|
import { z as z8 } from "zod";
|
|
8621
8774
|
var schema7 = {
|
|
8622
|
-
registry: z8.string().describe(`Package registry. Dependency data is available on ${
|
|
8775
|
+
registry: z8.string().describe(`Package registry. Dependency data is available on ${SUPPORTED_DEPS_REGISTRIES_LIST}.`),
|
|
8623
8776
|
package_name: z8.string().describe("Package name (scoped names ok: @types/node)."),
|
|
8624
8777
|
version: z8.string().optional().describe("Specific version to inspect. Defaults to latest when omitted. Tag-style inputs with a leading `v` (for example `v4.18.0`) are rejected — pass the canonical version (`4.18.0`)."),
|
|
8625
8778
|
lifecycle: z8.union([z8.string(), z8.array(z8.string())]).optional().describe("Lifecycle breadth. Omit for runtime-only. Use `runtime` for explicit runtime-only, a concrete non-runtime lifecycle (`development`, `build`, `peer`, `optional`) for runtime plus matching groups, or `all` for runtime plus all available groups. Accepts a single value, a comma-separated string, or an array; `all` cannot be combined with other values. Uppercase is tolerated."),
|
|
8626
8779
|
include_transitive: z8.boolean().optional().describe("When true the response gains a `transitive` block with aggregate counts (`edges`, `uniquePackages`), the preprocessed `packages[]` list (each `{name, version}` — the complete install footprint), plus typed `conflicts[]` (`{name, requiredVersions}`) and `circularDependencies[]` (`{cycle: string[]}`) when the backend reported any. Off by default."),
|
|
8627
8780
|
include_importers: z8.boolean().optional().describe("Requires `include_transitive: true`. When true, each entry in `transitive.packages[]` also carries an `importers` array — every upstream package that pulls it in, with that importer's own resolved version and the constraint it declared. Off by default because adding provenance roughly quadruples the envelope size on heavy graphs. Turn on when you need to trace why a specific transitive dep is present."),
|
|
8628
8781
|
max_depth: z8.number().int().min(1).max(10).optional().describe("Cap the transitive traversal at this depth (1–10). Omit to get the backend's full graph. Requires `include_transitive: true` — passing `max_depth` without the transitive flag is rejected with `INVALID_ARGUMENT`."),
|
|
8629
|
-
format: z8.enum(["json", "text", "text-v1"]).optional().describe(
|
|
8782
|
+
format: z8.enum(["json", "text", "text-v1"]).optional().describe('Response format. Default `text-v1` — compact dependency listing. Pass `format: "json"` for the structured envelope.')
|
|
8630
8783
|
};
|
|
8631
|
-
var DESCRIPTION7 = "Analyze a package's dependency graph.
|
|
8784
|
+
var DESCRIPTION7 = "Analyze a package's dependency graph. Lists direct runtime " + "dependencies with resolved versions; non-runtime groups are " + "omitted by default. Use `lifecycle` with a concrete value for " + "runtime plus matching groups, or `all` for runtime plus every " + "available group. Set `include_transitive: true` to add a " + "`transitive` block with the full install footprint, conflict " + "detection, and circular-dependency flags; layer " + "`include_importers: true` on top when you also need per-package " + "provenance. Supports npm, PyPI, Hex, Crates, Zig, vcpkg, RubyGems, " + "and Go.";
|
|
8632
8785
|
function createPackageDependenciesTool(service) {
|
|
8633
8786
|
return {
|
|
8634
8787
|
name: "pkg_deps",
|
|
@@ -8701,9 +8854,10 @@ import { z as z9 } from "zod";
|
|
|
8701
8854
|
var schema8 = {
|
|
8702
8855
|
registry: z9.string().describe(`Package registry. One of: ${PKGSEER_REGISTRY_LIST}.`),
|
|
8703
8856
|
package_name: z9.string().describe("Package name (scoped names ok: @types/node)."),
|
|
8704
|
-
|
|
8857
|
+
verbose: z9.boolean().optional().describe("Text only. Adds GitHub language/topics/last-pushed, recent advisories, and recent changes. Ignored for format=json."),
|
|
8858
|
+
format: z9.enum(["json", "text", "text-v1"]).optional().describe('Response format. Default `text-v1` — compact package overview. Pass `format: "json"` for the structured envelope.')
|
|
8705
8859
|
};
|
|
8706
|
-
var DESCRIPTION8 = "
|
|
8860
|
+
var DESCRIPTION8 = "Latest-version package overview for dependency triage. Provide " + "`registry` and `package_name` (for example `npm` + `express`). " + "Default text returns license, description, repository popularity " + "(stars/forks/issues and [ARCHIVED] when applicable), downloads, " + "publish age, and vulnerability status. Set `verbose: true` for " + "GitHub language/topics/last-pushed, recent advisories, and recent " + 'changes. Pass `format: "json"` for structured fields. Use ' + "`pkg_vulns` for version-specific vulnerability details.";
|
|
8707
8861
|
function createPackageSummaryTool(service) {
|
|
8708
8862
|
return {
|
|
8709
8863
|
name: "pkg_info",
|
|
@@ -8720,6 +8874,7 @@ function createPackageSummaryTool(service) {
|
|
|
8720
8874
|
const payload = buildPackageSummarySuccessPayload(summary);
|
|
8721
8875
|
if (isTextFormat7(args.format)) {
|
|
8722
8876
|
return textResult(formatPackageSummaryTerminal(summary, {
|
|
8877
|
+
verbose: args.verbose,
|
|
8723
8878
|
useColors: false
|
|
8724
8879
|
}).trimEnd());
|
|
8725
8880
|
}
|
|
@@ -8750,14 +8905,16 @@ function isTextFormat7(format) {
|
|
|
8750
8905
|
// src/tools/package-vulnerabilities.ts
|
|
8751
8906
|
import { z as z10 } from "zod";
|
|
8752
8907
|
var schema9 = {
|
|
8753
|
-
registry: z10.string().describe("Package registry. Vulnerability data
|
|
8908
|
+
registry: z10.string().describe("Package registry. Vulnerability data is unavailable for vcpkg and zig."),
|
|
8754
8909
|
package_name: z10.string().describe("Package name (scoped names ok: @types/node)."),
|
|
8755
8910
|
version: z10.string().optional().describe("Specific version to check. Defaults to latest when omitted."),
|
|
8756
8911
|
min_severity: z10.string().optional().describe("Only return advisories at or above this severity (`low`, `medium`, `high`, `critical`; uppercase tolerated). Omit to see all, including null-severity advisories."),
|
|
8757
8912
|
include_withdrawn: z10.boolean().optional().describe("Include retracted advisories (default: false)."),
|
|
8758
|
-
|
|
8913
|
+
advisory_scope: z10.string().optional().describe("Advisory rows to return: `affected` (default), `non_affecting` for historical advisories that do not affect the inspected version, or `all` for both affected and historical advisories. Counts always include affected/non-affecting/all totals."),
|
|
8914
|
+
verbose: z10.boolean().optional().describe("Text output only. Show every advisory and full detail rows; format=json always returns the complete structured envelope."),
|
|
8915
|
+
format: z10.enum(["json", "text", "text-v1"]).optional().describe('Response format. Default `text-v1` — compact advisory summary. Pass `format: "json"` for the structured envelope.')
|
|
8759
8916
|
};
|
|
8760
|
-
var DESCRIPTION9 = "Check known vulnerabilities for a package on npm, PyPI, Hex,
|
|
8917
|
+
var DESCRIPTION9 = "Check known vulnerabilities for a package on npm, PyPI, Hex, " + "Crates, NuGet, Maven, Packagist, RubyGems, or Go (vcpkg and Zig " + "are not supported for vulnerability data). Returns a count summary, each advisory with OSV ID, " + "severity, affected ranges, and fix versions. Malicious-package " + "advisories surface in a separate bucket. Example: " + '`{"registry":"npm","package_name":"lodash","version":"4.17.20","min_severity":"high"}`. ' + "Pass `version` to inspect " + "a pinned release; omit it for latest. Default text is capped for " + "readability; use `verbose:true` for all selected advisory rows or " + '`format:"json"` for the complete envelope. Use ' + "`min_severity` to filter to a threshold (`low`, `medium`, `high`, " + "`critical`) and `include_withdrawn` to also see retracted " + 'advisories. Use `advisory_scope:"non_affecting"` to list ' + "historical advisories that do not affect the inspected version, or " + '`advisory_scope:"all"` to list affected and historical advisories together.';
|
|
8761
8918
|
function createPackageVulnerabilitiesTool(service) {
|
|
8762
8919
|
return {
|
|
8763
8920
|
name: "pkg_vulns",
|
|
@@ -8766,21 +8923,26 @@ function createPackageVulnerabilitiesTool(service) {
|
|
|
8766
8923
|
annotations: { readOnlyHint: true },
|
|
8767
8924
|
handler: async (args) => {
|
|
8768
8925
|
try {
|
|
8769
|
-
const { params } = buildPackageVulnerabilitiesParams({
|
|
8926
|
+
const { params, filter } = buildPackageVulnerabilitiesParams({
|
|
8770
8927
|
registry: args.registry,
|
|
8771
8928
|
packageName: args.package_name,
|
|
8772
8929
|
version: args.version,
|
|
8773
8930
|
minSeverity: args.min_severity,
|
|
8774
|
-
includeWithdrawn: args.include_withdrawn
|
|
8931
|
+
includeWithdrawn: args.include_withdrawn,
|
|
8932
|
+
advisoryScope: args.advisory_scope
|
|
8775
8933
|
});
|
|
8776
8934
|
const report = await service.packageVulnerabilities(params);
|
|
8777
8935
|
const payload = buildPackageVulnerabilitiesSuccessPayload(report, {
|
|
8778
|
-
requestedVersion: args.version
|
|
8936
|
+
requestedVersion: args.version,
|
|
8937
|
+
filter
|
|
8779
8938
|
});
|
|
8780
8939
|
if (isTextFormat8(args.format)) {
|
|
8781
8940
|
return textResult(formatPackageVulnerabilitiesTerminal(report, {
|
|
8782
8941
|
useColors: false,
|
|
8783
|
-
requestedVersion: args.version
|
|
8942
|
+
requestedVersion: args.version,
|
|
8943
|
+
filter,
|
|
8944
|
+
verbose: args.verbose,
|
|
8945
|
+
surface: "mcp"
|
|
8784
8946
|
}).trimEnd());
|
|
8785
8947
|
}
|
|
8786
8948
|
return textResult(JSON.stringify(payload));
|
|
@@ -8900,7 +9062,8 @@ function shouldEmitCappedHint(bounded, payload) {
|
|
|
8900
9062
|
}
|
|
8901
9063
|
function buildCappedHint(payload, originalStart, originalEnd) {
|
|
8902
9064
|
const requested = describeRequest(originalStart, originalEnd);
|
|
8903
|
-
|
|
9065
|
+
const continuation = payload.endLine !== undefined ? ` To continue, retry with start_line=${payload.endLine + 1}.` : "";
|
|
9066
|
+
return `Returned lines ${payload.startLine}-${payload.endLine}/${payload.totalLines} ` + `(MCP cap: ${MCP_READ_MAX_SPAN} lines per call; you requested ${requested}).` + `${continuation} ` + `Pick a focused start_line/end_line window — typical 80-150 lines around a search/code_grep match. ` + `Each retry also costs context, so aim for one well-sized read.`;
|
|
8904
9067
|
}
|
|
8905
9068
|
function describeRequest(originalStart, originalEnd) {
|
|
8906
9069
|
if (originalStart === undefined && originalEnd === undefined) {
|
|
@@ -9031,9 +9194,9 @@ var schema12 = {
|
|
|
9031
9194
|
limit: z13.coerce.number().int().min(1).max(100).optional().describe("Maximum results to return (default 10, max 100)."),
|
|
9032
9195
|
offset: z13.coerce.number().int().min(0).optional(),
|
|
9033
9196
|
wait_timeout_ms: z13.coerce.number().int().min(0).max(60000).optional(),
|
|
9034
|
-
format: z13.enum(["json", "text", "text-v1"]).optional().describe('Response format. Default `text-v1` — compact line-oriented output
|
|
9197
|
+
format: z13.enum(["json", "text", "text-v1"]).optional().describe('Response format. Default `text-v1` — compact line-oriented output. Pass `format: "json"` for the structured envelope. `text` is an alias for `text-v1`. The text format is a public, snapshot-tested contract.')
|
|
9035
9198
|
};
|
|
9036
|
-
var DESCRIPTION12 = "Search indexed dependency and repository code, docs, and explicit symbols. " + "Provide either `target` for one target or `targets` for many; omit `sources` to use backend AUTO. " + "
|
|
9199
|
+
var DESCRIPTION12 = "Search indexed dependency and repository code, docs, and explicit symbols. " + "Provide either `target` for one target or `targets` for many; omit `sources` to use backend AUTO. " + "Structured parameters combine with the `query` using AND semantics. " + "Complete by default — if indexing is still running, the response carries a `searchRef` and no hits; pass it to `search_status` to follow up. " + "Set `allow_partial_results: true` to opt into hits from sources that finished while others continue indexing. " + "Each hit's `type` tells you the follow-up tool: `documentation_page` and `repository_doc` → `docs_read` with `locator.pageId`; `repository_code` and `repository_symbol` → `code_read` with `locator.filePath` (and `locator.startLine`/`endLine` when present).";
|
|
9037
9200
|
function createSearchTool(service) {
|
|
9038
9201
|
return {
|
|
9039
9202
|
name: "search",
|
|
@@ -9137,7 +9300,7 @@ function isTextFormat11(format) {
|
|
|
9137
9300
|
import { z as z14 } from "zod";
|
|
9138
9301
|
var schema13 = {
|
|
9139
9302
|
query: z14.string().min(1).describe('Language name or partial name to search for (e.g., "python", "type", "java")'),
|
|
9140
|
-
format: z14.enum(["json", "text", "text-v1"]).optional().describe(
|
|
9303
|
+
format: z14.enum(["json", "text", "text-v1"]).optional().describe('Response format. Default `text-v1` returns one language per line. Pass `format: "json"` for the structured array.')
|
|
9141
9304
|
};
|
|
9142
9305
|
var DESCRIPTION13 = `Find the correct language name for \`get_example\` when it is uncertain. Returns up to 5 matching languages by name, display name, or alias. Default output is one language per line; pass \`format: "json"\` for the structured array.`;
|
|
9143
9306
|
function createSearchLanguageTool(service) {
|
|
@@ -9173,10 +9336,10 @@ function renderLanguageMatches(matches) {
|
|
|
9173
9336
|
// src/tools/search-status.ts
|
|
9174
9337
|
import { z as z15 } from "zod";
|
|
9175
9338
|
var schema14 = {
|
|
9176
|
-
search_ref: z15.string().min(1).describe("
|
|
9339
|
+
search_ref: z15.string().min(1).describe("The `searchRef` field from a prior `search` response (camelCase in the response, snake_case as this parameter). Pass it through unchanged."),
|
|
9177
9340
|
format: z15.enum(["json", "text", "text-v1"]).optional().describe('Response format. Default `text-v1` — compact line-oriented output matching `search`. Pass `format: "json"` for the structured envelope.')
|
|
9178
9341
|
};
|
|
9179
|
-
var DESCRIPTION14 = "Check progress, fetch partial hits when the original request used allow_partial_results: true, or fetch final results for a prior
|
|
9342
|
+
var DESCRIPTION14 = "Check progress, fetch partial hits (when the original request used `allow_partial_results: true`), or fetch final results for a prior `search` that returned a `searchRef`. " + "Pass the `searchRef` from that response as `search_ref` here (response field is camelCase; this parameter is snake_case).";
|
|
9180
9343
|
function createSearchStatusTool(service) {
|
|
9181
9344
|
return {
|
|
9182
9345
|
name: "search_status",
|
|
@@ -9201,50 +9364,54 @@ function isTextFormat13(format) {
|
|
|
9201
9364
|
return format === undefined || format === "text" || format === "text-v1";
|
|
9202
9365
|
}
|
|
9203
9366
|
// src/commands/mcp-instructions.ts
|
|
9204
|
-
var CORE_BLOCK = `GitHits provides verified, canonical code examples from global open source
|
|
9367
|
+
var CORE_BLOCK = `GitHits provides verified, canonical code examples from global open source for AI agents. Pick a path:
|
|
9368
|
+
|
|
9369
|
+
- Need a canonical example or cross-project pattern with no specific package pinned (you're stuck, repeated attempts failed, the user wants up-to-date API usage, or the user mentioned GitHits) — call \`get_example\` for global solution synthesis.
|
|
9370
|
+
- Inspecting a specific known dependency or repository (stack trace points there, verifying how a particular library works, evaluating an upgrade) — call \`search\` plus the indexed code, docs, and package tools listed below.
|
|
9371
|
+
- Question is comparative across OSS projects (e.g. "how does X vs Y handle Z") or requires reading how a real codebase implements a feature — combine the two: \`search\` for known targets, \`get_example\` for cross-project synthesis.
|
|
9372
|
+
- Rate a result or share tool/UX feedback — call \`feedback\` with a \`solution_id\` from a prior \`get_example\` response (solution-tied) or omit it for generic feedback about any tool (\`search\`, \`code_*\`, \`docs_*\`, \`pkg_*\`) or the overall experience.
|
|
9205
9373
|
|
|
9206
|
-
|
|
9374
|
+
\`get_example\` workflow: pass \`language\` only when you know the exact name; otherwise call \`search_language\` first. Default output is markdown with a trailing \`solution_id\`. Reuse prior results before searching again. For dependency-specific grounding, prefer package-scoped \`search\` before global \`get_example\`.`;
|
|
9207
9375
|
var PACKAGE_TOOLS_PREAMBLE = `Indexed package/source tools inspect third-party dependency source, docs, and registry metadata. Use them when a stack trace points into a dependency, you need to verify how a library works, or you're evaluating whether to add or upgrade a package.
|
|
9208
9376
|
|
|
9209
9377
|
Package spec: \`registry:name[@version]\`. Default outputs are compact \`text-v1\` for agent context efficiency; pass \`format: "json"\` only when you need structured fields for programmatic parsing.`;
|
|
9210
|
-
var
|
|
9211
|
-
var DOCS_LIST_BULLET = "- `docs_list` — browse hosted and repository-backed package docs. Entries include stable pageIds, source URLs, and repo-file follow-up metadata when available.";
|
|
9212
|
-
var DOCS_READ_BULLET = "- `docs_read` — read a documentation page by pageId. Works for both hosted docs and repo-backed docs.";
|
|
9213
|
-
var PKG_VULNS_BULLET = '- `pkg_vulns` — compact known CVE / OSV advisory summary for npm, PyPI, Hex, or Crates packages, optionally pinned to `version`. Filter with `min_severity`; include retracted advisories with `include_withdrawn`. Pass `format: "json"` for per-advisory structured fields.';
|
|
9214
|
-
var PKG_DEPS_BULLET = '- `pkg_deps` — compact direct runtime deps by default. Use `lifecycle: "runtime"` for explicit runtime-only, a concrete lifecycle for runtime plus matching non-runtime deps, or `lifecycle: "all"` for all groups. Use `include_transitive` for the full graph and `include_importers` for provenance. Pass `format: "json"` for the structured envelope.';
|
|
9215
|
-
var PKG_CHANGELOG_BULLET = '- `pkg_changelog` — compact release notes for a package or GitHub repo, newest-first. Default latest mode returns recent entries with markdown body previews; `from_version` switches to range mode. Set `include_bodies: false` for a compact timeline or pass `format: "json"` for full bodies.';
|
|
9378
|
+
var MULTI_TURN_TIP = '**Delegate multi-call work to a sub-agent.** Code-navigation work (`search`, `code_grep`, `code_read`, `code_files`) often takes 3-10 calls. For cross-project comparisons, codebase mapping, pattern surveys, or "how does X actually work" investigations, spawn a sub-task/sub-agent and ask for a compact synthesis. Do it inline only when the raw snippet belongs in the main conversation.';
|
|
9216
9379
|
var SEARCH_BULLET = '- `search` — unified search across indexed dependency code, docs, and symbols. Omit `sources` for AUTO. Use `sources:["code"]` for implementation/examples/tests text, `sources:["symbol"]` for precise API/entity lookup, and `sources:["docs"]` for guides/reference/changelogs. Default output is compact `text-v1` with ready-to-call follow-up arguments; pass `format: "json"` for structured locators, highlights, and source status. Complete by default; opt into partial hits with `allow_partial_results: true`. Incomplete responses carry a `searchRef`.';
|
|
9217
9380
|
var SEARCH_STATUS_BULLET = "- `search_status` — follow up a prior `search` by `searchRef` to check progress, fetch partial hits, or fetch final results.";
|
|
9218
|
-
var CODE_FILES_BULLET = '- `code_files` — list files in an indexed dependency. `path`, `path_prefix`, and `globs` are OR-ed selectors; extensions, language, file type, and file-intent filters intersect on top. Returned paths feed into `code_read` and help scope `code_grep`; pass `format: "json"` for language/type/size metadata.';
|
|
9219
|
-
var CODE_READ_BULLET = "- `code_read` — read a dependency file by `path`. **MCP cap: 150 lines per call**; choose focused `start_line` / `end_line` windows from `search` or `code_grep`. Binary files set `isBinary: true` and omit `content`. On `FILE_NOT_FOUND` / `NOT_FOUND`, call `code_files` for the actual path.";
|
|
9220
9381
|
var CODE_GREP_BULLET = "- `code_grep` — deterministic text or regex grep over indexed source. Use it when you know the pattern; use `search` for discovery. Narrow with `path`, `path_prefix`, `globs`, or `extensions`. Each match's `path:line` chains into `code_read`.";
|
|
9221
|
-
var
|
|
9222
|
-
var
|
|
9223
|
-
var
|
|
9382
|
+
var CODE_READ_BULLET = "- `code_read` — read a dependency file by `path`. **MCP cap: 150 lines per call**. When you already have an exact path (e.g. from a stack trace), call this directly; otherwise locate it first with `search` or `code_grep` and pick a focused `start_line` / `end_line` window. Binary files set `isBinary: true` and omit `content`. On `FILE_NOT_FOUND` / `NOT_FOUND`, call `code_files` for the actual path.";
|
|
9383
|
+
var CODE_FILES_BULLET = '- `code_files` — list files in an indexed dependency. `path`, `path_prefix`, and `globs` are OR-ed selectors; extensions, language, file type, and file-intent filters intersect on top. Returned paths feed into `code_read` and help scope `code_grep`; pass `format: "json"` for language/type/size metadata.';
|
|
9384
|
+
var DOCS_LIST_BULLET = "- `docs_list` — browse hosted and repository-backed package docs. Entries include stable pageIds, source URLs, and repo-file follow-up metadata when available.";
|
|
9385
|
+
var DOCS_READ_BULLET = "- `docs_read` — read a documentation page by pageId. Works for both hosted docs and repo-backed docs.";
|
|
9386
|
+
var PKG_INFO_BULLET = '- `pkg_info` — latest-version package triage by `registry` + `package_name` (e.g. `npm` + `express`): license, repository popularity, downloads, publish age, and vulnerability status. Set `verbose: true` for GitHub language/topics/last-pushed, recent advisories, and recent changes; pass `format: "json"` for structured fields.';
|
|
9387
|
+
var PKG_VULNS_BULLET = '- `pkg_vulns` — compact known CVE / OSV advisory summary for npm, PyPI, Hex, Crates, NuGet, Maven, Packagist, RubyGems, or Go packages; vcpkg and Zig are not supported. Optionally pin `version` (e.g. `npm` + `lodash` + `4.17.20`). Filter with `min_severity`; include retracted advisories with `include_withdrawn`; set `advisory_scope: "non_affecting"` for historical advisories or `"all"` for affected + historical rows. Default text is capped; use `verbose: true` for all selected rows or `format: "json"` for the complete per-advisory envelope.';
|
|
9388
|
+
var PKG_DEPS_BULLET = '- `pkg_deps` — compact direct runtime deps by default. Use `lifecycle: "runtime"` for explicit runtime-only, a concrete lifecycle for runtime plus matching non-runtime deps, or `lifecycle: "all"` for all groups. Use `include_transitive` for the full graph and `include_importers` for provenance. Pass `format: "json"` for the structured envelope.';
|
|
9389
|
+
var PKG_CHANGELOG_BULLET = '- `pkg_changelog` — compact release notes for a package or GitHub repo, newest-first (e.g. `npm` + `express` + `limit: 2`). Default latest mode returns recent entries with 10-line markdown previews; `from_version` switches to range mode. Set `body_lines` to tune text previews, `verbose: true` for full text bodies, `include_bodies: false` for a compact timeline, or `format: "json"` for the complete envelope.';
|
|
9390
|
+
var STRATEGY_TIP = 'Strategy — reference-first. Locate symbols and lines with `search` or `code_grep` first, then read the needed window with `code_read` using explicit `start_line` / `end_line` (typical 80-150 lines around the match; the MCP `code_read` surface caps each call at 150 lines). Source, symbols, tests, and call sites beat docs prose for behavioral claims; use `sources:["symbol"]` when you want symbol-shaped results, `code_grep` for deterministic text matching, and `get_example` for global canonical examples after package-scoped grounding.';
|
|
9224
9391
|
function buildMcpInstructions(_deps) {
|
|
9225
|
-
const
|
|
9226
|
-
|
|
9227
|
-
|
|
9228
|
-
|
|
9229
|
-
|
|
9230
|
-
|
|
9231
|
-
|
|
9232
|
-
|
|
9233
|
-
|
|
9234
|
-
|
|
9235
|
-
|
|
9236
|
-
|
|
9237
|
-
|
|
9238
|
-
const
|
|
9239
|
-
|
|
9240
|
-
|
|
9241
|
-
`
|
|
9242
|
-
|
|
9243
|
-
|
|
9244
|
-
|
|
9392
|
+
const bullets = [
|
|
9393
|
+
SEARCH_BULLET,
|
|
9394
|
+
SEARCH_STATUS_BULLET,
|
|
9395
|
+
CODE_GREP_BULLET,
|
|
9396
|
+
CODE_READ_BULLET,
|
|
9397
|
+
CODE_FILES_BULLET,
|
|
9398
|
+
DOCS_LIST_BULLET,
|
|
9399
|
+
DOCS_READ_BULLET,
|
|
9400
|
+
PKG_INFO_BULLET,
|
|
9401
|
+
PKG_VULNS_BULLET,
|
|
9402
|
+
PKG_DEPS_BULLET,
|
|
9403
|
+
PKG_CHANGELOG_BULLET
|
|
9404
|
+
];
|
|
9405
|
+
const packageSection = [
|
|
9406
|
+
PACKAGE_TOOLS_PREAMBLE,
|
|
9407
|
+
MULTI_TURN_TIP,
|
|
9408
|
+
bullets.join(`
|
|
9409
|
+
`),
|
|
9410
|
+
STRATEGY_TIP
|
|
9411
|
+
].join(`
|
|
9245
9412
|
|
|
9246
|
-
`)
|
|
9247
|
-
return
|
|
9413
|
+
`);
|
|
9414
|
+
return [CORE_BLOCK, packageSection].join(`
|
|
9248
9415
|
|
|
9249
9416
|
`);
|
|
9250
9417
|
}
|
|
@@ -9443,7 +9610,7 @@ function formatChangelogTerminalError(mapped) {
|
|
|
9443
9610
|
if (available && available.length > 0) {
|
|
9444
9611
|
const sample = available.slice(0, 5).join(", ");
|
|
9445
9612
|
const more = available.length - 5;
|
|
9446
|
-
const suffix = more > 0 ? `,
|
|
9613
|
+
const suffix = more > 0 ? `, ... (+${more} more)` : "";
|
|
9447
9614
|
lines.push(` available: ${sample}${suffix}`);
|
|
9448
9615
|
}
|
|
9449
9616
|
return lines.join(`
|
|
@@ -9582,8 +9749,7 @@ groups). Concrete --lifecycle values include runtime plus matching groups.
|
|
|
9582
9749
|
conflict detection, and circular-dependency flags.
|
|
9583
9750
|
|
|
9584
9751
|
Package spec: <registry>:<name>[@<version>]. Supported registries:
|
|
9585
|
-
|
|
9586
|
-
release.`;
|
|
9752
|
+
${SUPPORTED_DEPS_REGISTRIES_LIST}. Omit @<version> for the latest release.`;
|
|
9587
9753
|
function registerPkgDepsCommand(pkgCommand) {
|
|
9588
9754
|
return pkgCommand.command("deps").summary("Analyze dependencies for a package").description(PKG_DEPS_DESCRIPTION).argument("<spec>", "Package spec, e.g. npm:express or npm:express@4.18.0").option("-l, --lifecycle <phases>", "Dependency lifecycle breadth (runtime, development, build, peer, optional, all; comma-separated for multi-select except all).").option("-t, --transitive", "Include aggregate transitive counts, conflicts, and circular dependencies").option("--depth <n>", "Cap transitive traversal depth (1-10). Omit for the full graph.").option("-v, --verbose", "Show conditionType / selectionMode / environmentConstraints metadata in the groups view").option("--json", "Emit the lean JSON envelope").action(async (spec, options) => {
|
|
9589
9755
|
const deps = await createContainer();
|
|
@@ -9640,16 +9806,20 @@ function handlePkgInfoCommandError(error2, json) {
|
|
|
9640
9806
|
console.error(formatMappedErrorForTerminal(mapped));
|
|
9641
9807
|
process.exit(1);
|
|
9642
9808
|
}
|
|
9643
|
-
var PKG_INFO_DESCRIPTION = `
|
|
9644
|
-
|
|
9645
|
-
|
|
9646
|
-
|
|
9809
|
+
var PKG_INFO_DESCRIPTION = `Latest-version package overview for dependency triage.
|
|
9810
|
+
|
|
9811
|
+
Default output shows license, description, repository popularity
|
|
9812
|
+
(stars/forks/issues and [ARCHIVED] when applicable), downloads,
|
|
9813
|
+
publish age, and vulnerability status. --verbose adds GitHub
|
|
9814
|
+
language/topics/last-pushed, recent advisories, and recent changes.
|
|
9647
9815
|
|
|
9648
9816
|
Package spec: <registry>:<name>. Supported registries: ${PKGSEER_REGISTRY_LIST}.
|
|
9649
9817
|
|
|
9818
|
+
Example: githits pkg info npm:express
|
|
9819
|
+
|
|
9650
9820
|
Always returns data for the latest published version.`;
|
|
9651
9821
|
function registerPkgInfoCommand(pkgCommand) {
|
|
9652
|
-
return pkgCommand.command("info").summary("Show a package overview").description(PKG_INFO_DESCRIPTION).argument("<spec>", "Package spec, e.g. npm:express or pypi:requests").option("-v, --verbose", "Show
|
|
9822
|
+
return pkgCommand.command("info").summary("Show a package overview").description(PKG_INFO_DESCRIPTION).argument("<spec>", "Package spec, e.g. npm:express or pypi:requests").option("-v, --verbose", "Show GitHub language/topics/last-pushed, recent advisories, and recent changes").option("--json", "Emit the lean JSON envelope").action(async (spec, options) => {
|
|
9653
9823
|
const deps = await createContainer();
|
|
9654
9824
|
await pkgInfoAction(spec, options, {
|
|
9655
9825
|
packageIntelligenceService: deps.packageIntelligenceService,
|
|
@@ -9668,17 +9838,19 @@ async function pkgVulnsAction(spec, options, deps) {
|
|
|
9668
9838
|
throw new InvalidPackageSpecError("Package intelligence is not configured for this environment.");
|
|
9669
9839
|
}
|
|
9670
9840
|
const parsed = parsePackageSpec(spec);
|
|
9671
|
-
const { params } = buildPackageVulnerabilitiesParams({
|
|
9841
|
+
const { params, filter } = buildPackageVulnerabilitiesParams({
|
|
9672
9842
|
registry: parsed.registry,
|
|
9673
9843
|
packageName: parsed.name,
|
|
9674
9844
|
version: parsed.version,
|
|
9675
9845
|
minSeverity: options.severity,
|
|
9676
|
-
includeWithdrawn: options.includeWithdrawn
|
|
9846
|
+
includeWithdrawn: options.includeWithdrawn,
|
|
9847
|
+
advisoryScope: options.scope
|
|
9677
9848
|
});
|
|
9678
9849
|
const report = await deps.packageIntelligenceService.packageVulnerabilities(params);
|
|
9679
9850
|
if (options.json) {
|
|
9680
9851
|
const payload = buildPackageVulnerabilitiesSuccessPayload(report, {
|
|
9681
|
-
requestedVersion: parsed.version
|
|
9852
|
+
requestedVersion: parsed.version,
|
|
9853
|
+
filter
|
|
9682
9854
|
});
|
|
9683
9855
|
console.log(JSON.stringify(payload));
|
|
9684
9856
|
return;
|
|
@@ -9687,6 +9859,8 @@ async function pkgVulnsAction(spec, options, deps) {
|
|
|
9687
9859
|
verbose: options.verbose,
|
|
9688
9860
|
useColors: shouldUseColors(),
|
|
9689
9861
|
requestedVersion: parsed.version,
|
|
9862
|
+
filter,
|
|
9863
|
+
surface: "cli",
|
|
9690
9864
|
terminalWidth: process.stdout.columns
|
|
9691
9865
|
});
|
|
9692
9866
|
process.stdout.write(output);
|
|
@@ -9729,24 +9903,30 @@ function formatVulnsTerminalError(mapped) {
|
|
|
9729
9903
|
if (available && available.length > 0) {
|
|
9730
9904
|
const sample = available.slice(0, 5).join(", ");
|
|
9731
9905
|
const more = available.length - 5;
|
|
9732
|
-
const suffix = more > 0 ? `,
|
|
9906
|
+
const suffix = more > 0 ? `, ... (+${more} more)` : "";
|
|
9733
9907
|
lines.push(` available: ${sample}${suffix}`);
|
|
9734
9908
|
}
|
|
9735
9909
|
return lines.join(`
|
|
9736
9910
|
`);
|
|
9737
9911
|
}
|
|
9738
9912
|
var PKG_VULNS_DESCRIPTION = `Show known vulnerabilities for a package. Lists CVE / OSV advisories
|
|
9739
|
-
with severity, affected version ranges, and fix versions.
|
|
9740
|
-
|
|
9913
|
+
with severity, affected version ranges, and fix versions. Default text is
|
|
9914
|
+
capped for readability; use --verbose for all selected advisory rows or --json
|
|
9915
|
+
for the complete structured envelope.
|
|
9741
9916
|
|
|
9742
9917
|
Package spec: <registry>:<name>[@<version>]. Supported registries:
|
|
9743
|
-
npm, pypi, hex, crates.
|
|
9918
|
+
npm, pypi, hex, crates, nuget, maven, packagist, rubygems, go. vcpkg and zig are not supported.
|
|
9919
|
+
Omit @<version> to check the latest release.
|
|
9920
|
+
Example: githits pkg vulns npm:lodash@4.17.20 --severity high
|
|
9744
9921
|
|
|
9745
9922
|
Severity filter (--severity) and withdrawn-advisory visibility
|
|
9746
9923
|
(--include-withdrawn) are passed through to the backend; the
|
|
9747
|
-
returned count reflects whatever survived the filter
|
|
9924
|
+
returned count reflects whatever survived the filter and active filters
|
|
9925
|
+
are echoed in text and JSON output. Use --scope non_affecting to list
|
|
9926
|
+
historical advisories that do not affect the inspected version, or --scope all
|
|
9927
|
+
to list affected and historical package advisories together.`;
|
|
9748
9928
|
function registerPkgVulnsCommand(pkgCommand) {
|
|
9749
|
-
return pkgCommand.command("vulns").summary("List known vulnerabilities for a package").description(PKG_VULNS_DESCRIPTION).argument("<spec>", "Package spec, e.g. npm:express or npm:express@4.18.0").option("-s, --severity <level>", "Only show advisories at or above this severity (low, medium, high, critical). Omit to see all.").option("--include-withdrawn", "Include retracted advisories (default: off)").option("-v, --verbose", "Show aliases, modified/withdrawn dates, and malicious-advisory markers").option("--json", "Emit the lean JSON envelope").action(async (spec, options) => {
|
|
9929
|
+
return pkgCommand.command("vulns").summary("List known vulnerabilities for a package").description(PKG_VULNS_DESCRIPTION).argument("<spec>", "Package spec, e.g. npm:express or npm:express@4.18.0").option("-s, --severity <level>", "Only show advisories at or above this severity (low, medium, high, critical). Omit to see all.").option("--scope <scope>", "Advisory rows to return: affected, non_affecting, all (default: affected)").option("--include-withdrawn", "Include retracted advisories (default: off)").option("-v, --verbose", "Show aliases, modified/withdrawn dates, and malicious-advisory markers").option("--json", "Emit the lean JSON envelope").action(async (spec, options) => {
|
|
9750
9930
|
const deps = await createContainer();
|
|
9751
9931
|
await pkgVulnsAction(spec, options, {
|
|
9752
9932
|
packageIntelligenceService: deps.packageIntelligenceService,
|
|
@@ -9763,7 +9943,7 @@ async function registerPkgCommandGroup(program, options = {}) {
|
|
|
9763
9943
|
if (!registration.shouldRegister) {
|
|
9764
9944
|
return;
|
|
9765
9945
|
}
|
|
9766
|
-
const pkgCommand = program.command("pkg").summary("Package metadata: info, vulnerabilities, dependencies, changelog").description("Inspect package metadata from npm, PyPI, Hex, Crates, NuGet, Maven, Packagist, RubyGems, Go, vcpkg, and Zig: overviews, advisories, dependency graphs, and changelogs. For source-level operations inside a dependency, use `githits code`.");
|
|
9946
|
+
const pkgCommand = program.command("pkg").summary("Package metadata: info, vulnerabilities, dependencies, changelog").description("Inspect package metadata from npm, PyPI, Hex, Crates, NuGet, Maven, Packagist, RubyGems, Go, vcpkg, and Zig: overviews, advisories, dependency graphs, and changelogs. Advisory data is unavailable for vcpkg and Zig. For source-level operations inside a dependency, use `githits code`.");
|
|
9767
9947
|
registerPkgInfoCommand(pkgCommand);
|
|
9768
9948
|
registerPkgVulnsCommand(pkgCommand);
|
|
9769
9949
|
registerPkgDepsCommand(pkgCommand);
|
|
@@ -9887,7 +10067,7 @@ function requireSearchService(deps) {
|
|
|
9887
10067
|
return deps.codeNavigationService;
|
|
9888
10068
|
}
|
|
9889
10069
|
async function loadContainer2() {
|
|
9890
|
-
const { createContainer: createContainer2 } = await import("./shared/chunk-
|
|
10070
|
+
const { createContainer: createContainer2 } = await import("./shared/chunk-kmka6wpx.js");
|
|
9891
10071
|
return createContainer2();
|
|
9892
10072
|
}
|
|
9893
10073
|
function parseTargetSpecs(specs) {
|