githits 0.2.3 → 0.3.1
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/GEMINI.md +4 -6
- package/README.md +31 -17
- package/commands/help.md +4 -4
- package/dist/cli.js +718 -238
- package/dist/index.js +1 -1
- package/dist/shared/{chunk-a9js75mw.js → chunk-0s7mxdt3.js} +1702 -678
- package/dist/shared/{chunk-js72s35a.js → chunk-m1xx8hzw.js} +1 -1
- package/dist/shared/chunk-zg5dnven.js +11 -0
- package/gemini-extension.json +1 -1
- package/package.json +4 -1
- package/plugins/claude/.claude-plugin/plugin.json +1 -1
- package/plugins/claude/commands/help.md +4 -4
- package/plugins/claude/skills/search/SKILL.md +2 -2
- package/skills/search/SKILL.md +2 -2
- package/dist/shared/chunk-9zze00cp.js +0 -11
package/dist/cli.js
CHANGED
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
|
+
AuthConfigError,
|
|
4
|
+
AuthStorageLockTimeoutError,
|
|
5
|
+
AuthStoragePolicyError,
|
|
3
6
|
AuthenticationError,
|
|
7
|
+
CLIENT_UPDATE_REQUIRED_REASON,
|
|
8
|
+
ClientUpdateRequiredError,
|
|
4
9
|
CodeNavigationAccessError,
|
|
5
10
|
CodeNavigationBackendError,
|
|
6
11
|
CodeNavigationFeatureFlagRequiredError,
|
|
@@ -16,6 +21,7 @@ import {
|
|
|
16
21
|
FileSystemServiceImpl,
|
|
17
22
|
MalformedCodeNavigationResponseError,
|
|
18
23
|
MalformedPackageIntelligenceResponseError,
|
|
24
|
+
NpmRegistryUpdateCheckService,
|
|
19
25
|
PackageIntelligenceAccessError,
|
|
20
26
|
PackageIntelligenceBackendError,
|
|
21
27
|
PackageIntelligenceChangelogSourceNotFoundError,
|
|
@@ -26,30 +32,199 @@ import {
|
|
|
26
32
|
PackageIntelligenceValidationError,
|
|
27
33
|
PackageIntelligenceVersionNotFoundError,
|
|
28
34
|
PromptServiceImpl,
|
|
35
|
+
createAuthCommandDependencies,
|
|
36
|
+
createAuthStatusDependencies,
|
|
29
37
|
createContainer,
|
|
30
38
|
debugLog,
|
|
31
39
|
endTelemetrySpan,
|
|
32
40
|
flushTelemetry,
|
|
33
|
-
|
|
41
|
+
formatRequiredUpdateNotice,
|
|
42
|
+
formatUpdateNotice,
|
|
34
43
|
getCodeNavigationUrl,
|
|
35
|
-
getEnvApiToken,
|
|
36
|
-
isCodeNavigationCliOverrideEnabled,
|
|
37
44
|
isTelemetryEnabled,
|
|
38
45
|
refreshExpiredToken,
|
|
39
|
-
resolveStartupCodeNavigationRegistrationState,
|
|
40
46
|
setClientMode,
|
|
41
47
|
setMcpClientVersionProvider,
|
|
48
|
+
shouldRunRequiredUpdateEnforcement,
|
|
49
|
+
shouldRunUpdateCheck,
|
|
42
50
|
startTelemetrySpan,
|
|
43
51
|
withTelemetrySpan
|
|
44
|
-
} from "./shared/chunk-
|
|
52
|
+
} from "./shared/chunk-0s7mxdt3.js";
|
|
45
53
|
import {
|
|
46
54
|
__require,
|
|
47
55
|
version
|
|
48
|
-
} from "./shared/chunk-
|
|
56
|
+
} from "./shared/chunk-m1xx8hzw.js";
|
|
49
57
|
|
|
50
58
|
// src/cli.ts
|
|
51
59
|
import { Command } from "commander";
|
|
52
60
|
|
|
61
|
+
// src/shared/require-auth.ts
|
|
62
|
+
class AuthRequiredError extends Error {
|
|
63
|
+
constructor(message) {
|
|
64
|
+
super(message);
|
|
65
|
+
this.name = "AuthRequiredError";
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
function requireAuth(deps, context) {
|
|
69
|
+
if (deps.hasValidToken)
|
|
70
|
+
return;
|
|
71
|
+
const suffix = context ? ` ${context}` : "";
|
|
72
|
+
console.log(`Authentication required${suffix}.
|
|
73
|
+
`);
|
|
74
|
+
if (deps.mcpUrl !== "https://mcp.githits.com") {
|
|
75
|
+
console.log(` Environment: ${deps.mcpUrl}`);
|
|
76
|
+
console.log(` You're using a custom environment.
|
|
77
|
+
`);
|
|
78
|
+
}
|
|
79
|
+
console.log("To authenticate:");
|
|
80
|
+
console.log(` githits login
|
|
81
|
+
`);
|
|
82
|
+
console.log("Or set GITHITS_API_TOKEN environment variable.");
|
|
83
|
+
console.log(`
|
|
84
|
+
Need help? support@githits.com`);
|
|
85
|
+
throw new AuthRequiredError(`Authentication required${suffix}`);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
// src/cli/errors.ts
|
|
89
|
+
function handleCliError(error, deps) {
|
|
90
|
+
if (error instanceof AuthRequiredError) {
|
|
91
|
+
deps.exit(1);
|
|
92
|
+
}
|
|
93
|
+
if (isUserFacingError(error)) {
|
|
94
|
+
deps.stderr.write(`${error.message}
|
|
95
|
+
|
|
96
|
+
`);
|
|
97
|
+
deps.exit(1);
|
|
98
|
+
}
|
|
99
|
+
throw error;
|
|
100
|
+
}
|
|
101
|
+
function isUserFacingError(error) {
|
|
102
|
+
return error instanceof AuthConfigError || error instanceof AuthStorageLockTimeoutError || error instanceof AuthStoragePolicyError;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
// src/cli/update-check.ts
|
|
106
|
+
function startUpdateCheckTask(service) {
|
|
107
|
+
const controller = new AbortController;
|
|
108
|
+
return {
|
|
109
|
+
promise: service.checkForUpdate(controller.signal),
|
|
110
|
+
abort: () => controller.abort()
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
function startRequiredUpdateRefreshTask(service) {
|
|
114
|
+
const controller = new AbortController;
|
|
115
|
+
return {
|
|
116
|
+
promise: service.refreshRequiredUpdateStatus(controller.signal),
|
|
117
|
+
abort: () => controller.abort()
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
function startUpdateCheckTaskForInvocation(options) {
|
|
121
|
+
if (!shouldRunUpdateCheck({
|
|
122
|
+
args: options.args,
|
|
123
|
+
env: options.env,
|
|
124
|
+
stderrIsTTY: options.stderrIsTTY,
|
|
125
|
+
stdinIsTTY: options.stdinIsTTY,
|
|
126
|
+
stdoutIsTTY: options.stdoutIsTTY
|
|
127
|
+
})) {
|
|
128
|
+
return;
|
|
129
|
+
}
|
|
130
|
+
return startUpdateCheckTask(options.createService());
|
|
131
|
+
}
|
|
132
|
+
function startRequiredUpdateRefreshTaskForInvocation(options) {
|
|
133
|
+
if (!shouldRunRequiredUpdateEnforcement({
|
|
134
|
+
args: options.args,
|
|
135
|
+
env: options.env
|
|
136
|
+
})) {
|
|
137
|
+
return;
|
|
138
|
+
}
|
|
139
|
+
return startRequiredUpdateRefreshTask(options.createService());
|
|
140
|
+
}
|
|
141
|
+
async function enforceCachedRequiredUpdateForInvocation(options) {
|
|
142
|
+
if (!shouldRunRequiredUpdateEnforcement({
|
|
143
|
+
args: options.args,
|
|
144
|
+
env: options.env
|
|
145
|
+
})) {
|
|
146
|
+
return;
|
|
147
|
+
}
|
|
148
|
+
const notice = await options.createService().getRequiredUpdateNotice();
|
|
149
|
+
if (!notice) {
|
|
150
|
+
return;
|
|
151
|
+
}
|
|
152
|
+
if (isJsonInvocation(options.args)) {
|
|
153
|
+
options.stderr.write(`${JSON.stringify(requiredUpdateEnvelope(notice))}
|
|
154
|
+
`);
|
|
155
|
+
} else {
|
|
156
|
+
options.stderr.write(`${formatRequiredUpdateNotice(notice)}
|
|
157
|
+
`);
|
|
158
|
+
}
|
|
159
|
+
options.exit(1);
|
|
160
|
+
}
|
|
161
|
+
async function runWithUpdateCheckFlush(action, task, options) {
|
|
162
|
+
try {
|
|
163
|
+
return await action();
|
|
164
|
+
} finally {
|
|
165
|
+
await flushRequiredUpdateRefresh(options.requiredUpdateRefreshTask, {
|
|
166
|
+
timeoutMs: options.timeoutMs
|
|
167
|
+
});
|
|
168
|
+
await flushUpdateCheckNotice(task, options);
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
async function flushRequiredUpdateRefresh(task, options = {}) {
|
|
172
|
+
if (!task) {
|
|
173
|
+
return;
|
|
174
|
+
}
|
|
175
|
+
const timeoutMs = options.timeoutMs ?? 50;
|
|
176
|
+
let timeout;
|
|
177
|
+
const timeoutPromise = new Promise((resolve) => {
|
|
178
|
+
timeout = setTimeout(() => resolve("timeout"), timeoutMs);
|
|
179
|
+
});
|
|
180
|
+
const result = await Promise.race([task.promise, timeoutPromise]);
|
|
181
|
+
if (timeout) {
|
|
182
|
+
clearTimeout(timeout);
|
|
183
|
+
}
|
|
184
|
+
if (result === "timeout") {
|
|
185
|
+
task.abort();
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
async function flushUpdateCheckNotice(task, options) {
|
|
189
|
+
if (!task) {
|
|
190
|
+
return;
|
|
191
|
+
}
|
|
192
|
+
const timeoutMs = options.timeoutMs ?? 50;
|
|
193
|
+
let timeout;
|
|
194
|
+
const timeoutPromise = new Promise((resolve) => {
|
|
195
|
+
timeout = setTimeout(() => resolve("timeout"), timeoutMs);
|
|
196
|
+
});
|
|
197
|
+
const result = await Promise.race([task.promise, timeoutPromise]);
|
|
198
|
+
if (timeout) {
|
|
199
|
+
clearTimeout(timeout);
|
|
200
|
+
}
|
|
201
|
+
if (result === "timeout") {
|
|
202
|
+
task.abort();
|
|
203
|
+
return;
|
|
204
|
+
}
|
|
205
|
+
if (!result) {
|
|
206
|
+
return;
|
|
207
|
+
}
|
|
208
|
+
options.stderr.write(`${formatUpdateNotice(result)}
|
|
209
|
+
`);
|
|
210
|
+
}
|
|
211
|
+
function isJsonInvocation(args) {
|
|
212
|
+
return args.includes("--json");
|
|
213
|
+
}
|
|
214
|
+
function requiredUpdateEnvelope(notice) {
|
|
215
|
+
return {
|
|
216
|
+
error: `Update required: ${notice.reason}`,
|
|
217
|
+
code: "UPDATE_REQUIRED",
|
|
218
|
+
retryable: false,
|
|
219
|
+
details: {
|
|
220
|
+
currentVersion: notice.currentVersion,
|
|
221
|
+
...notice.latestKnownVersion ? { latestKnownVersion: notice.latestKnownVersion } : {},
|
|
222
|
+
updateCommand: notice.updateCommand,
|
|
223
|
+
reason: notice.reason
|
|
224
|
+
}
|
|
225
|
+
};
|
|
226
|
+
}
|
|
227
|
+
|
|
53
228
|
// src/commands/auth-status.ts
|
|
54
229
|
function displayExpiry(expiresAt) {
|
|
55
230
|
if (!expiresAt) {
|
|
@@ -65,23 +240,12 @@ function displayExpiry(expiresAt) {
|
|
|
65
240
|
console.log(` Expires: in ${minutesLeft} minute${minutesLeft !== 1 ? "s" : ""}`);
|
|
66
241
|
}
|
|
67
242
|
}
|
|
68
|
-
function displayCodeNavigationStatus(capability, overrideEnabled) {
|
|
69
|
-
console.log(` Code navigation: ${capability}`);
|
|
70
|
-
console.log(` CLI override: ${overrideEnabled ? "enabled" : "disabled"}`);
|
|
71
|
-
}
|
|
72
243
|
async function authStatusAction(deps) {
|
|
73
|
-
const {
|
|
74
|
-
authStorage,
|
|
75
|
-
authService,
|
|
76
|
-
mcpUrl,
|
|
77
|
-
envApiToken,
|
|
78
|
-
codeNavigationCliOverrideEnabled
|
|
79
|
-
} = deps;
|
|
244
|
+
const { authStorage, authService, mcpUrl, envApiToken } = deps;
|
|
80
245
|
if (envApiToken) {
|
|
81
246
|
console.log(`Authenticated via environment variable.
|
|
82
247
|
`);
|
|
83
248
|
console.log(` Source: GITHITS_API_TOKEN`);
|
|
84
|
-
displayCodeNavigationStatus(getCodeNavigationCapability(envApiToken), codeNavigationCliOverrideEnabled);
|
|
85
249
|
return;
|
|
86
250
|
}
|
|
87
251
|
const auth = await authStorage.loadTokens(mcpUrl);
|
|
@@ -90,7 +254,6 @@ async function authStatusAction(deps) {
|
|
|
90
254
|
`);
|
|
91
255
|
console.log(` Environment: ${mcpUrl}
|
|
92
256
|
`);
|
|
93
|
-
displayCodeNavigationStatus("unknown", codeNavigationCliOverrideEnabled);
|
|
94
257
|
console.log("");
|
|
95
258
|
console.log("To authenticate:");
|
|
96
259
|
console.log(" githits login");
|
|
@@ -100,12 +263,10 @@ async function authStatusAction(deps) {
|
|
|
100
263
|
const refreshed = await refreshExpiredToken(authService, authStorage, mcpUrl);
|
|
101
264
|
if (refreshed) {
|
|
102
265
|
const refreshedAuth = await authStorage.loadTokens(mcpUrl);
|
|
103
|
-
const capability = getCodeNavigationCapability(refreshedAuth?.accessToken);
|
|
104
266
|
console.log(`Authenticated (token refreshed).
|
|
105
267
|
`);
|
|
106
268
|
console.log(` Environment: ${mcpUrl}`);
|
|
107
269
|
displayExpiry(refreshedAuth?.expiresAt ?? null);
|
|
108
|
-
displayCodeNavigationStatus(capability, codeNavigationCliOverrideEnabled);
|
|
109
270
|
console.log(`
|
|
110
271
|
Storage: ${authStorage.getStorageLocation()}`);
|
|
111
272
|
return;
|
|
@@ -115,7 +276,6 @@ async function authStatusAction(deps) {
|
|
|
115
276
|
console.log(` Environment: ${mcpUrl}`);
|
|
116
277
|
console.log(` Expired: ${new Date(auth.expiresAt).toLocaleDateString()}
|
|
117
278
|
`);
|
|
118
|
-
displayCodeNavigationStatus("unknown", codeNavigationCliOverrideEnabled);
|
|
119
279
|
console.log("");
|
|
120
280
|
console.log("Run `githits login` to re-authenticate.");
|
|
121
281
|
return;
|
|
@@ -124,35 +284,26 @@ async function authStatusAction(deps) {
|
|
|
124
284
|
`);
|
|
125
285
|
console.log(` Environment: ${mcpUrl}`);
|
|
126
286
|
displayExpiry(auth.expiresAt);
|
|
127
|
-
displayCodeNavigationStatus(getCodeNavigationCapability(auth.accessToken), codeNavigationCliOverrideEnabled);
|
|
128
287
|
console.log(`
|
|
129
288
|
Storage: ${authStorage.getStorageLocation()}`);
|
|
130
289
|
}
|
|
131
290
|
var STATUS_DESCRIPTION = `Show current authentication status.
|
|
132
291
|
|
|
133
292
|
Displays details about the stored token including environment
|
|
134
|
-
and expiration.
|
|
293
|
+
and expiration. If GITHITS_API_TOKEN is set, reports that source
|
|
294
|
+
without reading local OAuth storage. Useful for debugging authentication issues.`;
|
|
135
295
|
function registerAuthStatusCommand(program) {
|
|
136
296
|
program.command("status").summary("Show authentication status").description(STATUS_DESCRIPTION).action(async () => {
|
|
137
|
-
const deps = await
|
|
297
|
+
const deps = await createAuthStatusDependencies();
|
|
138
298
|
await authStatusAction(deps);
|
|
139
299
|
});
|
|
140
300
|
}
|
|
141
301
|
// src/commands/gated-command-group.ts
|
|
142
302
|
async function resolveGatedCommandGroupRegistrationState(options = {}) {
|
|
143
303
|
const codeNavigationUrl = options.codeNavigationUrl ?? getCodeNavigationUrl();
|
|
144
|
-
if (!codeNavigationUrl) {
|
|
145
|
-
return { codeNavigationUrl: undefined, shouldRegister: false };
|
|
146
|
-
}
|
|
147
|
-
const overrideEnabled = options.overrideEnabled ?? isCodeNavigationCliOverrideEnabled();
|
|
148
|
-
const registrationState = options.capability !== undefined || options.expiredStoredAuth !== undefined ? {
|
|
149
|
-
capability: options.capability ?? "unknown",
|
|
150
|
-
expiredStoredAuth: options.expiredStoredAuth ?? false
|
|
151
|
-
} : await resolveStartupCodeNavigationRegistrationState();
|
|
152
|
-
const envTokenPresent = options.envTokenPresent ?? Boolean(getEnvApiToken());
|
|
153
304
|
return {
|
|
154
305
|
codeNavigationUrl,
|
|
155
|
-
shouldRegister:
|
|
306
|
+
shouldRegister: codeNavigationUrl.length > 0
|
|
156
307
|
};
|
|
157
308
|
}
|
|
158
309
|
|
|
@@ -346,6 +497,9 @@ function mapCodeNavigationError(error2) {
|
|
|
346
497
|
return mapped;
|
|
347
498
|
}
|
|
348
499
|
function classify(error2) {
|
|
500
|
+
if (error2 instanceof ClientUpdateRequiredError) {
|
|
501
|
+
return buildUpdateRequiredError(error2.reason, error2.currentVersion);
|
|
502
|
+
}
|
|
349
503
|
if (error2 instanceof CodeNavigationVersionNotFoundError) {
|
|
350
504
|
const details = {};
|
|
351
505
|
if (error2.packageName)
|
|
@@ -413,7 +567,8 @@ function classify(error2) {
|
|
|
413
567
|
return {
|
|
414
568
|
code: "AUTH_REQUIRED",
|
|
415
569
|
message: error2.message,
|
|
416
|
-
retryable: false
|
|
570
|
+
retryable: false,
|
|
571
|
+
details: { action: "Run `githits login`, then retry this tool call." }
|
|
417
572
|
};
|
|
418
573
|
}
|
|
419
574
|
if (error2 instanceof CodeNavigationNetworkError) {
|
|
@@ -456,6 +611,27 @@ function classify(error2) {
|
|
|
456
611
|
}
|
|
457
612
|
return { code: "UNKNOWN", message: "Unknown error", retryable: false };
|
|
458
613
|
}
|
|
614
|
+
function buildUpdateRequiredError(reason = CLIENT_UPDATE_REQUIRED_REASON, currentVersion) {
|
|
615
|
+
return {
|
|
616
|
+
code: "UPDATE_REQUIRED",
|
|
617
|
+
message: `Update required: ${reason}`,
|
|
618
|
+
retryable: false,
|
|
619
|
+
details: {
|
|
620
|
+
reason,
|
|
621
|
+
updateCommand: "npm i -g githits@latest",
|
|
622
|
+
...currentVersion ? { currentVersion } : {}
|
|
623
|
+
}
|
|
624
|
+
};
|
|
625
|
+
}
|
|
626
|
+
function formatMappedErrorForTerminal(mapped) {
|
|
627
|
+
if (mapped.code !== "UPDATE_REQUIRED") {
|
|
628
|
+
return mapped.message;
|
|
629
|
+
}
|
|
630
|
+
const detail = mapped.details ?? {};
|
|
631
|
+
const updateCommand = typeof detail.updateCommand === "string" ? detail.updateCommand : "npm i -g githits@latest";
|
|
632
|
+
return [mapped.message, "", "Update with:", ` ${updateCommand}`].join(`
|
|
633
|
+
`);
|
|
634
|
+
}
|
|
459
635
|
function classifyBackendError(error2) {
|
|
460
636
|
const details = {};
|
|
461
637
|
if (typeof error2.status === "number")
|
|
@@ -2305,6 +2481,9 @@ function mapPackageIntelligenceError(error2) {
|
|
|
2305
2481
|
return mapped;
|
|
2306
2482
|
}
|
|
2307
2483
|
function classify2(error2) {
|
|
2484
|
+
if (error2 instanceof ClientUpdateRequiredError) {
|
|
2485
|
+
return buildUpdateRequiredError(error2.reason, error2.currentVersion);
|
|
2486
|
+
}
|
|
2308
2487
|
if (error2 instanceof PackageIntelligenceTargetNotFoundError || error2 instanceof PackageIntelligenceChangelogSourceNotFoundError) {
|
|
2309
2488
|
return {
|
|
2310
2489
|
code: "NOT_FOUND",
|
|
@@ -2350,7 +2529,8 @@ function classify2(error2) {
|
|
|
2350
2529
|
return {
|
|
2351
2530
|
code: "AUTH_REQUIRED",
|
|
2352
2531
|
message: error2.message,
|
|
2353
|
-
retryable: false
|
|
2532
|
+
retryable: false,
|
|
2533
|
+
details: { action: "Run `githits login`, then retry this tool call." }
|
|
2354
2534
|
};
|
|
2355
2535
|
}
|
|
2356
2536
|
if (error2 instanceof PackageIntelligenceNetworkError) {
|
|
@@ -2864,19 +3044,20 @@ function isSeverityLabel(value) {
|
|
|
2864
3044
|
function buildPackageVulnerabilitiesSuccessPayload(report, options = {}) {
|
|
2865
3045
|
const pkg = report.package;
|
|
2866
3046
|
const security = report.security;
|
|
2867
|
-
const
|
|
3047
|
+
const dedupedAdvisories = dedupAdvisoriesByAlias(security?.vulnerabilities ?? []);
|
|
3048
|
+
const total = security?.affectedVulnerabilityCount ?? dedupedAdvisories.length;
|
|
2868
3049
|
const payload = {
|
|
2869
3050
|
registry: lowerRegistry3(pkg.registry),
|
|
2870
3051
|
name: pkg.name,
|
|
2871
3052
|
version: pkg.version,
|
|
2872
|
-
summary: buildSummary(total, security)
|
|
3053
|
+
summary: buildSummary(total, security, dedupedAdvisories)
|
|
2873
3054
|
};
|
|
2874
3055
|
const requestedEcho = deriveRequestedVersion2(options.requestedVersion, pkg.version);
|
|
2875
3056
|
if (requestedEcho !== undefined) {
|
|
2876
3057
|
payload.requestedVersion = requestedEcho;
|
|
2877
3058
|
}
|
|
2878
3059
|
if (total > 0) {
|
|
2879
|
-
const sortedAdvisories = sortAdvisories(
|
|
3060
|
+
const sortedAdvisories = sortAdvisories(dedupedAdvisories.map(buildAdvisory));
|
|
2880
3061
|
if (sortedAdvisories.length > 0) {
|
|
2881
3062
|
payload.advisories = sortedAdvisories;
|
|
2882
3063
|
}
|
|
@@ -2915,14 +3096,19 @@ function parseVersionForSort(v) {
|
|
|
2915
3096
|
});
|
|
2916
3097
|
return { main, pre };
|
|
2917
3098
|
}
|
|
2918
|
-
function buildSummary(total, security) {
|
|
3099
|
+
function buildSummary(total, security, dedupedAdvisories) {
|
|
2919
3100
|
const summary = { total };
|
|
2920
|
-
if (
|
|
2921
|
-
|
|
3101
|
+
if (security) {
|
|
3102
|
+
summary.affectedVulnerabilityCount = security.affectedVulnerabilityCount;
|
|
3103
|
+
summary.nonAffectingVulnerabilityCount = security.nonAffectingVulnerabilityCount;
|
|
3104
|
+
summary.allVulnerabilityCount = security.allVulnerabilityCount;
|
|
3105
|
+
}
|
|
2922
3106
|
if (typeof security?.currentVersionAffected === "boolean") {
|
|
2923
3107
|
summary.affected = security.currentVersionAffected;
|
|
2924
3108
|
}
|
|
2925
|
-
|
|
3109
|
+
if (total === 0)
|
|
3110
|
+
return summary;
|
|
3111
|
+
const bySeverity = computeBySeverity(dedupedAdvisories);
|
|
2926
3112
|
const anyCounted = Object.values(bySeverity).some((n) => n > 0);
|
|
2927
3113
|
if (anyCounted) {
|
|
2928
3114
|
const trimmed = {};
|
|
@@ -2977,6 +3163,231 @@ function vulnSeverityLabel(score) {
|
|
|
2977
3163
|
return "medium";
|
|
2978
3164
|
return "low";
|
|
2979
3165
|
}
|
|
3166
|
+
function dedupAdvisoriesByAlias(advisories) {
|
|
3167
|
+
if (advisories.length === 0)
|
|
3168
|
+
return [];
|
|
3169
|
+
const parent = new Map;
|
|
3170
|
+
const find = (id) => {
|
|
3171
|
+
let root = id;
|
|
3172
|
+
let next = parent.get(root);
|
|
3173
|
+
while (next !== undefined && next !== root) {
|
|
3174
|
+
root = next;
|
|
3175
|
+
next = parent.get(root);
|
|
3176
|
+
}
|
|
3177
|
+
let cursor = id;
|
|
3178
|
+
while (cursor !== root) {
|
|
3179
|
+
const parentOfCursor = parent.get(cursor);
|
|
3180
|
+
if (parentOfCursor === undefined)
|
|
3181
|
+
break;
|
|
3182
|
+
parent.set(cursor, root);
|
|
3183
|
+
cursor = parentOfCursor;
|
|
3184
|
+
}
|
|
3185
|
+
return root;
|
|
3186
|
+
};
|
|
3187
|
+
const union = (a, b) => {
|
|
3188
|
+
const ra = find(a);
|
|
3189
|
+
const rb = find(b);
|
|
3190
|
+
if (ra !== rb)
|
|
3191
|
+
parent.set(ra, rb);
|
|
3192
|
+
};
|
|
3193
|
+
const ensure = (id) => {
|
|
3194
|
+
if (!parent.has(id))
|
|
3195
|
+
parent.set(id, id);
|
|
3196
|
+
};
|
|
3197
|
+
const advisoryKeys = [];
|
|
3198
|
+
for (let i = 0;i < advisories.length; i++) {
|
|
3199
|
+
const advisory = advisories[i];
|
|
3200
|
+
if (!advisory) {
|
|
3201
|
+
advisoryKeys.push(`__synthetic_${i}`);
|
|
3202
|
+
continue;
|
|
3203
|
+
}
|
|
3204
|
+
const ids = [];
|
|
3205
|
+
if (advisory.osvId)
|
|
3206
|
+
ids.push(advisory.osvId);
|
|
3207
|
+
for (const alias of advisory.aliases ?? []) {
|
|
3208
|
+
if (alias)
|
|
3209
|
+
ids.push(alias);
|
|
3210
|
+
}
|
|
3211
|
+
if (ids.length === 0) {
|
|
3212
|
+
const synthetic = `__synthetic_${i}`;
|
|
3213
|
+
ensure(synthetic);
|
|
3214
|
+
advisoryKeys.push(synthetic);
|
|
3215
|
+
continue;
|
|
3216
|
+
}
|
|
3217
|
+
for (const id of ids)
|
|
3218
|
+
ensure(id);
|
|
3219
|
+
for (let j = 1;j < ids.length; j++) {
|
|
3220
|
+
const a = ids[j - 1];
|
|
3221
|
+
const b = ids[j];
|
|
3222
|
+
if (a !== undefined && b !== undefined)
|
|
3223
|
+
union(a, b);
|
|
3224
|
+
}
|
|
3225
|
+
advisoryKeys.push(ids[0]);
|
|
3226
|
+
}
|
|
3227
|
+
const clusters = new Map;
|
|
3228
|
+
for (let i = 0;i < advisories.length; i++) {
|
|
3229
|
+
const advisory = advisories[i];
|
|
3230
|
+
if (!advisory)
|
|
3231
|
+
continue;
|
|
3232
|
+
const key = advisoryKeys[i];
|
|
3233
|
+
if (key === undefined)
|
|
3234
|
+
continue;
|
|
3235
|
+
const root = find(key);
|
|
3236
|
+
const bucket = clusters.get(root);
|
|
3237
|
+
if (bucket)
|
|
3238
|
+
bucket.push(advisory);
|
|
3239
|
+
else
|
|
3240
|
+
clusters.set(root, [advisory]);
|
|
3241
|
+
}
|
|
3242
|
+
const merged = [];
|
|
3243
|
+
for (const cluster of clusters.values()) {
|
|
3244
|
+
merged.push(mergeAdvisoryCluster(cluster));
|
|
3245
|
+
}
|
|
3246
|
+
return merged;
|
|
3247
|
+
}
|
|
3248
|
+
function mergeAdvisoryCluster(cluster) {
|
|
3249
|
+
if (cluster.length === 1) {
|
|
3250
|
+
const only = cluster[0];
|
|
3251
|
+
if (!only)
|
|
3252
|
+
throw new Error("empty advisory cluster");
|
|
3253
|
+
return only;
|
|
3254
|
+
}
|
|
3255
|
+
const canonical = pickCanonical(cluster);
|
|
3256
|
+
const aliasSet = new Set;
|
|
3257
|
+
for (const member of cluster) {
|
|
3258
|
+
if (member.osvId)
|
|
3259
|
+
aliasSet.add(member.osvId);
|
|
3260
|
+
for (const alias of member.aliases ?? []) {
|
|
3261
|
+
if (alias)
|
|
3262
|
+
aliasSet.add(alias);
|
|
3263
|
+
}
|
|
3264
|
+
}
|
|
3265
|
+
if (canonical.osvId)
|
|
3266
|
+
aliasSet.delete(canonical.osvId);
|
|
3267
|
+
const aliases = Array.from(aliasSet).sort();
|
|
3268
|
+
const affectedRangesSet = new Set;
|
|
3269
|
+
const matchedAffectedRangesSet = new Set;
|
|
3270
|
+
const fixedInSet = new Set;
|
|
3271
|
+
const duplicateIdsSet = new Set;
|
|
3272
|
+
let isMalicious = false;
|
|
3273
|
+
let affectsInspectedVersion = false;
|
|
3274
|
+
let affectedVersionRangesTruncated = false;
|
|
3275
|
+
let affectedVersionRangesCount = 0;
|
|
3276
|
+
let latestModifiedAt = canonical.modifiedAt;
|
|
3277
|
+
let withdrawnAt;
|
|
3278
|
+
let allWithdrawn = true;
|
|
3279
|
+
let maxSeverityScore = typeof canonical.severityScore === "number" ? canonical.severityScore : 0;
|
|
3280
|
+
for (const member of cluster) {
|
|
3281
|
+
for (const range of member.affectedVersionRanges ?? []) {
|
|
3282
|
+
affectedRangesSet.add(range);
|
|
3283
|
+
}
|
|
3284
|
+
for (const range of member.matchedAffectedVersionRanges ?? []) {
|
|
3285
|
+
matchedAffectedRangesSet.add(range);
|
|
3286
|
+
}
|
|
3287
|
+
for (const fix of member.fixedInVersions ?? []) {
|
|
3288
|
+
fixedInSet.add(fix);
|
|
3289
|
+
}
|
|
3290
|
+
for (const duplicateId of member.duplicateIds ?? []) {
|
|
3291
|
+
duplicateIdsSet.add(duplicateId);
|
|
3292
|
+
}
|
|
3293
|
+
if (member.isMalicious === true)
|
|
3294
|
+
isMalicious = true;
|
|
3295
|
+
if (member.affectsInspectedVersion === true)
|
|
3296
|
+
affectsInspectedVersion = true;
|
|
3297
|
+
if (member.affectedVersionRangesTruncated === true) {
|
|
3298
|
+
affectedVersionRangesTruncated = true;
|
|
3299
|
+
}
|
|
3300
|
+
if (typeof member.affectedVersionRangesCount === "number") {
|
|
3301
|
+
affectedVersionRangesCount = Math.max(affectedVersionRangesCount, member.affectedVersionRangesCount);
|
|
3302
|
+
}
|
|
3303
|
+
if (member.modifiedAt) {
|
|
3304
|
+
if (!latestModifiedAt || member.modifiedAt > latestModifiedAt) {
|
|
3305
|
+
latestModifiedAt = member.modifiedAt;
|
|
3306
|
+
}
|
|
3307
|
+
}
|
|
3308
|
+
if (member.withdrawnAt) {
|
|
3309
|
+
if (!withdrawnAt || member.withdrawnAt > withdrawnAt) {
|
|
3310
|
+
withdrawnAt = member.withdrawnAt;
|
|
3311
|
+
}
|
|
3312
|
+
} else {
|
|
3313
|
+
allWithdrawn = false;
|
|
3314
|
+
}
|
|
3315
|
+
if (!member.withdrawnAt && typeof member.severityScore === "number" && member.severityScore > maxSeverityScore) {
|
|
3316
|
+
maxSeverityScore = member.severityScore;
|
|
3317
|
+
}
|
|
3318
|
+
}
|
|
3319
|
+
const merged = {
|
|
3320
|
+
...canonical,
|
|
3321
|
+
aliases
|
|
3322
|
+
};
|
|
3323
|
+
if (maxSeverityScore > 0) {
|
|
3324
|
+
merged.severityScore = maxSeverityScore;
|
|
3325
|
+
}
|
|
3326
|
+
if (affectedRangesSet.size > 0) {
|
|
3327
|
+
merged.affectedVersionRanges = Array.from(affectedRangesSet);
|
|
3328
|
+
}
|
|
3329
|
+
const exactOrLowerBoundCount = Math.max(affectedVersionRangesCount, affectedRangesSet.size);
|
|
3330
|
+
if (exactOrLowerBoundCount > 0) {
|
|
3331
|
+
merged.affectedVersionRangesCount = exactOrLowerBoundCount;
|
|
3332
|
+
}
|
|
3333
|
+
if (affectedVersionRangesTruncated) {
|
|
3334
|
+
merged.affectedVersionRangesTruncated = true;
|
|
3335
|
+
}
|
|
3336
|
+
if (matchedAffectedRangesSet.size > 0) {
|
|
3337
|
+
merged.matchedAffectedVersionRanges = Array.from(matchedAffectedRangesSet);
|
|
3338
|
+
}
|
|
3339
|
+
if (affectsInspectedVersion)
|
|
3340
|
+
merged.affectsInspectedVersion = true;
|
|
3341
|
+
if (duplicateIdsSet.size > 0) {
|
|
3342
|
+
merged.duplicateIds = Array.from(duplicateIdsSet).sort();
|
|
3343
|
+
}
|
|
3344
|
+
if (fixedInSet.size > 0) {
|
|
3345
|
+
merged.fixedInVersions = Array.from(fixedInSet);
|
|
3346
|
+
}
|
|
3347
|
+
if (isMalicious)
|
|
3348
|
+
merged.isMalicious = true;
|
|
3349
|
+
if (latestModifiedAt) {
|
|
3350
|
+
merged.modifiedAt = latestModifiedAt;
|
|
3351
|
+
} else {
|
|
3352
|
+
delete merged.modifiedAt;
|
|
3353
|
+
}
|
|
3354
|
+
if (allWithdrawn && withdrawnAt) {
|
|
3355
|
+
merged.withdrawnAt = withdrawnAt;
|
|
3356
|
+
} else {
|
|
3357
|
+
delete merged.withdrawnAt;
|
|
3358
|
+
}
|
|
3359
|
+
return merged;
|
|
3360
|
+
}
|
|
3361
|
+
function pickCanonical(cluster) {
|
|
3362
|
+
const ranked = cluster.slice().sort((a, b) => {
|
|
3363
|
+
const aHasScore = typeof a.severityScore === "number" && a.severityScore > 0 ? 1 : 0;
|
|
3364
|
+
const bHasScore = typeof b.severityScore === "number" && b.severityScore > 0 ? 1 : 0;
|
|
3365
|
+
if (aHasScore !== bHasScore)
|
|
3366
|
+
return bHasScore - aHasScore;
|
|
3367
|
+
const aRank = idPrefixRank(a.osvId);
|
|
3368
|
+
const bRank = idPrefixRank(b.osvId);
|
|
3369
|
+
if (aRank !== bRank)
|
|
3370
|
+
return aRank - bRank;
|
|
3371
|
+
const aId = a.osvId ?? "";
|
|
3372
|
+
const bId = b.osvId ?? "";
|
|
3373
|
+
if (aId !== bId)
|
|
3374
|
+
return aId < bId ? -1 : 1;
|
|
3375
|
+
return 0;
|
|
3376
|
+
});
|
|
3377
|
+
const winner = ranked[0];
|
|
3378
|
+
if (!winner)
|
|
3379
|
+
throw new Error("empty cluster passed to pickCanonical");
|
|
3380
|
+
return winner;
|
|
3381
|
+
}
|
|
3382
|
+
function idPrefixRank(id) {
|
|
3383
|
+
if (!id)
|
|
3384
|
+
return 99;
|
|
3385
|
+
if (id.startsWith("GHSA-"))
|
|
3386
|
+
return 0;
|
|
3387
|
+
if (id.startsWith("RUSTSEC-"))
|
|
3388
|
+
return 2;
|
|
3389
|
+
return 1;
|
|
3390
|
+
}
|
|
2980
3391
|
function buildAdvisory(advisory) {
|
|
2981
3392
|
const lean = {};
|
|
2982
3393
|
if (advisory.osvId)
|
|
@@ -2996,6 +3407,21 @@ function buildAdvisory(advisory) {
|
|
|
2996
3407
|
if (advisory.affectedVersionRanges && advisory.affectedVersionRanges.length > 0) {
|
|
2997
3408
|
lean.affectedRanges = advisory.affectedVersionRanges.slice();
|
|
2998
3409
|
}
|
|
3410
|
+
if (typeof advisory.affectedVersionRangesCount === "number") {
|
|
3411
|
+
lean.affectedVersionRangesCount = advisory.affectedVersionRangesCount;
|
|
3412
|
+
}
|
|
3413
|
+
if (advisory.affectedVersionRangesTruncated === true) {
|
|
3414
|
+
lean.affectedVersionRangesTruncated = true;
|
|
3415
|
+
}
|
|
3416
|
+
if (typeof advisory.affectsInspectedVersion === "boolean") {
|
|
3417
|
+
lean.affectsInspectedVersion = advisory.affectsInspectedVersion;
|
|
3418
|
+
}
|
|
3419
|
+
if (advisory.matchedAffectedVersionRanges && advisory.matchedAffectedVersionRanges.length > 0) {
|
|
3420
|
+
lean.matchedAffectedVersionRanges = advisory.matchedAffectedVersionRanges.slice();
|
|
3421
|
+
}
|
|
3422
|
+
if (advisory.duplicateIds && advisory.duplicateIds.length > 0) {
|
|
3423
|
+
lean.duplicateIds = advisory.duplicateIds.slice();
|
|
3424
|
+
}
|
|
2999
3425
|
if (advisory.fixedInVersions && advisory.fixedInVersions.length > 0) {
|
|
3000
3426
|
lean.fixedIn = advisory.fixedInVersions.slice();
|
|
3001
3427
|
}
|
|
@@ -3078,7 +3504,7 @@ function formatPackageVulnerabilitiesTerminal(report, options = {}) {
|
|
|
3078
3504
|
const lines = [headerLine];
|
|
3079
3505
|
if (requestedLine)
|
|
3080
3506
|
lines.push(requestedLine);
|
|
3081
|
-
lines.push(
|
|
3507
|
+
lines.push(formatNoAffectedVulnerabilitiesLine(payload));
|
|
3082
3508
|
return `${lines.join(`
|
|
3083
3509
|
`)}
|
|
3084
3510
|
`;
|
|
@@ -3112,15 +3538,25 @@ function formatHeader(payload, useColors) {
|
|
|
3112
3538
|
function formatSummaryLine(payload, useColors) {
|
|
3113
3539
|
const n = payload.summary.total;
|
|
3114
3540
|
const noun = n === 1 ? "vulnerability" : "vulnerabilities";
|
|
3115
|
-
const
|
|
3541
|
+
const verb = n === 1 ? "affects" : "affect";
|
|
3542
|
+
const base = `${n} ${noun} ${verb} this version`;
|
|
3116
3543
|
if (payload.summary.affected === true) {
|
|
3117
|
-
return colorize(
|
|
3544
|
+
return colorize(base, "yellow", useColors);
|
|
3118
3545
|
}
|
|
3119
3546
|
if (payload.summary.affected === false) {
|
|
3120
|
-
return
|
|
3547
|
+
return base;
|
|
3121
3548
|
}
|
|
3122
3549
|
return base;
|
|
3123
3550
|
}
|
|
3551
|
+
function formatNoAffectedVulnerabilitiesLine(payload) {
|
|
3552
|
+
const historical = payload.summary.nonAffectingVulnerabilityCount ?? 0;
|
|
3553
|
+
if (historical > 0) {
|
|
3554
|
+
const noun = historical === 1 ? "historical advisory" : "historical advisories";
|
|
3555
|
+
const verb = historical === 1 ? "does" : "do";
|
|
3556
|
+
return `No vulnerabilities affect this version (${historical} ${noun} ${verb} not apply).`;
|
|
3557
|
+
}
|
|
3558
|
+
return "No known vulnerabilities affect this version.";
|
|
3559
|
+
}
|
|
3124
3560
|
function formatBreakdownLine(summary, useColors) {
|
|
3125
3561
|
if (summary.total <= 1)
|
|
3126
3562
|
return;
|
|
@@ -3206,7 +3642,7 @@ function formatAdvisoryLines(advisory, labelWidth, verbose, useColors, rangeLimi
|
|
|
3206
3642
|
lines.push(` ${label.padEnd(detailWidth)} ${value}`);
|
|
3207
3643
|
};
|
|
3208
3644
|
if (advisory.affectedRanges && advisory.affectedRanges.length > 0) {
|
|
3209
|
-
pushRow("affected", formatRangeList(advisory.affectedRanges, verbose, useColors, rangeLimit));
|
|
3645
|
+
pushRow("affected", formatRangeList(advisory.affectedRanges, verbose, useColors, rangeLimit, advisory.affectedVersionRangesCount, advisory.affectedVersionRangesTruncated));
|
|
3210
3646
|
}
|
|
3211
3647
|
if (advisory.fixedIn && advisory.fixedIn.length > 0) {
|
|
3212
3648
|
pushRow("fixed in", advisory.fixedIn.join(", "));
|
|
@@ -3233,13 +3669,23 @@ function formatAdvisoryLines(advisory, labelWidth, verbose, useColors, rangeLimi
|
|
|
3233
3669
|
}
|
|
3234
3670
|
return lines;
|
|
3235
3671
|
}
|
|
3236
|
-
function formatRangeList(ranges, verbose, useColors, limit) {
|
|
3672
|
+
function formatRangeList(ranges, verbose, useColors, limit, totalCount, backendTruncated) {
|
|
3673
|
+
const actualTotal = Math.max(totalCount ?? ranges.length, ranges.length);
|
|
3674
|
+
const backendHidden = backendTruncated === true ? actualTotal - ranges.length : 0;
|
|
3675
|
+
const appendBackendHint = (shown2) => {
|
|
3676
|
+
if (backendHidden > 0) {
|
|
3677
|
+
const hint2 = dim(`… (+${backendHidden} ranges omitted by service)`, useColors);
|
|
3678
|
+
return shown2.length > 0 ? `${shown2}, ${hint2}` : hint2;
|
|
3679
|
+
}
|
|
3680
|
+
return shown2;
|
|
3681
|
+
};
|
|
3237
3682
|
if (verbose || ranges.length <= limit) {
|
|
3238
|
-
return ranges.join(", ");
|
|
3683
|
+
return appendBackendHint(ranges.join(", "));
|
|
3239
3684
|
}
|
|
3240
3685
|
const shown = ranges.slice(0, limit).join(", ");
|
|
3241
|
-
const
|
|
3242
|
-
const
|
|
3686
|
+
const localHidden = ranges.length - limit;
|
|
3687
|
+
const hintText = backendHidden > 0 ? `… (+${localHidden} more with -v; +${backendHidden} omitted by service)` : `… (+${localHidden} more; use -v)`;
|
|
3688
|
+
const hint = dim(hintText, useColors);
|
|
3243
3689
|
return `${shown}, ${hint}`;
|
|
3244
3690
|
}
|
|
3245
3691
|
function resolveAffectedRangesLimit(terminalWidth) {
|
|
@@ -3254,8 +3700,8 @@ function formatUpgradeFooter(paths) {
|
|
|
3254
3700
|
if (!paths || paths.length === 0)
|
|
3255
3701
|
return;
|
|
3256
3702
|
if (paths.length === 1)
|
|
3257
|
-
return `
|
|
3258
|
-
return `
|
|
3703
|
+
return `Fix version: ${paths[0]}.`;
|
|
3704
|
+
return `Fix versions: ${paths.join(", ")}.`;
|
|
3259
3705
|
}
|
|
3260
3706
|
// src/shared/parse-lines-option.ts
|
|
3261
3707
|
function parseLinesOption(raw) {
|
|
@@ -3408,37 +3854,12 @@ function buildHeader3(envelope, useColors) {
|
|
|
3408
3854
|
const prefix = envelope.registry && envelope.name ? `${envelope.registry}:${envelope.name}${envelope.version ? `@${envelope.version}` : ""}` : "documentation";
|
|
3409
3855
|
return `${colorize(`${prefix} ${badge}`, "bold", useColors)}${title ? ` - ${title}` : ""}`;
|
|
3410
3856
|
}
|
|
3411
|
-
// src/shared/require-auth.ts
|
|
3412
|
-
class AuthRequiredError extends Error {
|
|
3413
|
-
constructor(message) {
|
|
3414
|
-
super(message);
|
|
3415
|
-
this.name = "AuthRequiredError";
|
|
3416
|
-
}
|
|
3417
|
-
}
|
|
3418
|
-
function requireAuth(deps, context) {
|
|
3419
|
-
if (deps.hasValidToken)
|
|
3420
|
-
return;
|
|
3421
|
-
const suffix = context ? ` ${context}` : "";
|
|
3422
|
-
console.log(`Authentication required${suffix}.
|
|
3423
|
-
`);
|
|
3424
|
-
if (deps.mcpUrl !== "https://mcp.githits.com") {
|
|
3425
|
-
console.log(` Environment: ${deps.mcpUrl}`);
|
|
3426
|
-
console.log(` You're using a custom environment.
|
|
3427
|
-
`);
|
|
3428
|
-
}
|
|
3429
|
-
console.log("To authenticate:");
|
|
3430
|
-
console.log(` githits login
|
|
3431
|
-
`);
|
|
3432
|
-
console.log("Or set GITHITS_API_TOKEN environment variable.");
|
|
3433
|
-
console.log(`
|
|
3434
|
-
Need help? support@githits.com`);
|
|
3435
|
-
throw new AuthRequiredError(`Authentication required${suffix}`);
|
|
3436
|
-
}
|
|
3437
3857
|
// src/shared/unified-search-request.ts
|
|
3858
|
+
var DEFAULT_UNIFIED_SEARCH_LIMIT = 10;
|
|
3438
3859
|
function buildUnifiedSearchParams(input) {
|
|
3439
3860
|
const targets = resolveTargets(input.target, input.targets);
|
|
3440
3861
|
const rawQuery = normaliseRequiredQuery(input.query);
|
|
3441
|
-
const limit = input.limit ??
|
|
3862
|
+
const limit = input.limit ?? DEFAULT_UNIFIED_SEARCH_LIMIT;
|
|
3442
3863
|
const offset = input.offset ?? 0;
|
|
3443
3864
|
const waitTimeoutMs = input.waitTimeoutMs ?? DEFAULT_WAIT_TIMEOUT_MS;
|
|
3444
3865
|
const qualifierClauses = buildQualifierClauses({
|
|
@@ -3544,7 +3965,7 @@ function buildFilters(input) {
|
|
|
3544
3965
|
return Object.keys(filters).length > 0 ? filters : undefined;
|
|
3545
3966
|
}
|
|
3546
3967
|
// src/shared/unified-search-response.ts
|
|
3547
|
-
var DEFAULT_LIMIT2 =
|
|
3968
|
+
var DEFAULT_LIMIT2 = DEFAULT_UNIFIED_SEARCH_LIMIT;
|
|
3548
3969
|
var DEFAULT_OFFSET = 0;
|
|
3549
3970
|
function buildUnifiedSearchSuccessPayload(params, rawQuery, compiledQuery, outcome) {
|
|
3550
3971
|
const warnings = outcome.state === "completed" ? outcome.result.queryWarnings : outcome.result?.queryWarnings ?? outcome.progress?.queryWarnings ?? [];
|
|
@@ -3567,6 +3988,9 @@ function buildUnifiedSearchSuccessPayload(params, rawQuery, compiledQuery, outco
|
|
|
3567
3988
|
const sourceStatus2 = compactSourceStatus(result?.sourceStatus);
|
|
3568
3989
|
if (sourceStatus2)
|
|
3569
3990
|
payload.sourceStatus = sourceStatus2;
|
|
3991
|
+
const combinedWarnings2 = combineWarnings(warnings, sourceStatus2);
|
|
3992
|
+
if (combinedWarnings2.length > 0)
|
|
3993
|
+
payload.warnings = combinedWarnings2;
|
|
3570
3994
|
return payload;
|
|
3571
3995
|
}
|
|
3572
3996
|
const completed = {
|
|
@@ -3583,8 +4007,18 @@ function buildUnifiedSearchSuccessPayload(params, rawQuery, compiledQuery, outco
|
|
|
3583
4007
|
const sourceStatus = compactSourceStatus(outcome.result.sourceStatus);
|
|
3584
4008
|
if (sourceStatus)
|
|
3585
4009
|
completed.sourceStatus = sourceStatus;
|
|
4010
|
+
const combinedWarnings = combineWarnings(warnings, sourceStatus);
|
|
4011
|
+
if (combinedWarnings.length > 0)
|
|
4012
|
+
completed.warnings = combinedWarnings;
|
|
3586
4013
|
return completed;
|
|
3587
4014
|
}
|
|
4015
|
+
function combineWarnings(parserWarnings, sourceStatus) {
|
|
4016
|
+
const out = [];
|
|
4017
|
+
if (parserWarnings.length > 0)
|
|
4018
|
+
out.push(...parserWarnings);
|
|
4019
|
+
out.push(...buildSourceStatusWarnings(sourceStatus));
|
|
4020
|
+
return out;
|
|
4021
|
+
}
|
|
3588
4022
|
function buildUnifiedSearchErrorPayload(error2) {
|
|
3589
4023
|
const mapped = mapCodeNavigationError(error2);
|
|
3590
4024
|
const payload = {
|
|
@@ -3629,15 +4063,16 @@ function buildUnifiedSearchStatusResultPayload(result) {
|
|
|
3629
4063
|
if (result.page.hasMore) {
|
|
3630
4064
|
payload.nextOffset = result.page.offset + result.page.returned;
|
|
3631
4065
|
}
|
|
3632
|
-
if (result.queryWarnings.length > 0) {
|
|
3633
|
-
payload.warnings = result.queryWarnings;
|
|
3634
|
-
}
|
|
3635
4066
|
if (result.sources.length > 0) {
|
|
3636
4067
|
payload.sources = result.sources.map((entry) => entry.toLowerCase());
|
|
3637
4068
|
}
|
|
3638
4069
|
const sourceStatus = compactSourceStatus(result.sourceStatus);
|
|
3639
4070
|
if (sourceStatus)
|
|
3640
4071
|
payload.sourceStatus = sourceStatus;
|
|
4072
|
+
const combinedWarnings = combineWarnings(result.queryWarnings, sourceStatus);
|
|
4073
|
+
if (combinedWarnings.length > 0) {
|
|
4074
|
+
payload.warnings = combinedWarnings;
|
|
4075
|
+
}
|
|
3641
4076
|
return payload;
|
|
3642
4077
|
}
|
|
3643
4078
|
function buildQueryEcho(params, rawQuery, compiledQuery, warnings) {
|
|
@@ -3763,6 +4198,46 @@ function compactProgress(progress) {
|
|
|
3763
4198
|
payload.expiresAt = progress.expiresAt;
|
|
3764
4199
|
return payload;
|
|
3765
4200
|
}
|
|
4201
|
+
function buildSourceStatusWarnings(sourceStatus) {
|
|
4202
|
+
if (!sourceStatus || sourceStatus.length === 0)
|
|
4203
|
+
return [];
|
|
4204
|
+
const warnings = [];
|
|
4205
|
+
for (const entry of sourceStatus) {
|
|
4206
|
+
const message = warningForEntry(entry);
|
|
4207
|
+
if (message !== undefined)
|
|
4208
|
+
warnings.push(message);
|
|
4209
|
+
}
|
|
4210
|
+
return warnings;
|
|
4211
|
+
}
|
|
4212
|
+
function warningForEntry(entry) {
|
|
4213
|
+
const reasons = [];
|
|
4214
|
+
if (entry.incompatibleQueryFeatures?.length) {
|
|
4215
|
+
reasons.push(`incompatible query features [${entry.incompatibleQueryFeatures.join(", ")}]`);
|
|
4216
|
+
}
|
|
4217
|
+
if (entry.ignoredQueryFeatures?.length) {
|
|
4218
|
+
reasons.push(`ignored query features [${entry.ignoredQueryFeatures.join(", ")}]`);
|
|
4219
|
+
}
|
|
4220
|
+
if (entry.incompatibleFilters?.length) {
|
|
4221
|
+
reasons.push(`incompatible filters [${entry.incompatibleFilters.join(", ")}]`);
|
|
4222
|
+
}
|
|
4223
|
+
if (entry.ignoredFilters?.length) {
|
|
4224
|
+
reasons.push(`ignored filters [${entry.ignoredFilters.join(", ")}]`);
|
|
4225
|
+
}
|
|
4226
|
+
if (entry.indexingStatus) {
|
|
4227
|
+
reasons.push(`indexing status ${entry.indexingStatus}`);
|
|
4228
|
+
}
|
|
4229
|
+
if (entry.codeIndexState) {
|
|
4230
|
+
reasons.push(`code index state ${entry.codeIndexState}`);
|
|
4231
|
+
}
|
|
4232
|
+
const prefix = `Source '${entry.source}' for ${entry.targetLabel}`;
|
|
4233
|
+
if (reasons.length > 0) {
|
|
4234
|
+
return `${prefix}: ${reasons.join("; ")}`;
|
|
4235
|
+
}
|
|
4236
|
+
if (entry.note) {
|
|
4237
|
+
return `${prefix}: ${entry.note}`;
|
|
4238
|
+
}
|
|
4239
|
+
return;
|
|
4240
|
+
}
|
|
3766
4241
|
function compactSourceStatus(sourceStatus) {
|
|
3767
4242
|
if (!sourceStatus || sourceStatus.length === 0)
|
|
3768
4243
|
return;
|
|
@@ -3962,6 +4437,12 @@ function formatScore(score) {
|
|
|
3962
4437
|
}
|
|
3963
4438
|
function buildTrailer2(payload) {
|
|
3964
4439
|
const lines = [];
|
|
4440
|
+
if (payload.warnings && payload.warnings.length > 0) {
|
|
4441
|
+
lines.push("warnings:");
|
|
4442
|
+
for (const warning2 of payload.warnings) {
|
|
4443
|
+
lines.push(` - ${warning2}`);
|
|
4444
|
+
}
|
|
4445
|
+
}
|
|
3965
4446
|
if (payload.hasMore) {
|
|
3966
4447
|
const nextOffsetHint = typeof payload.nextOffset === "number" ? ` Pass offset=${payload.nextOffset} for the next page or limit=N to widen.` : " Pass limit=N to widen.";
|
|
3967
4448
|
lines.push(`More hits available.${nextOffsetHint}`);
|
|
@@ -4308,6 +4789,9 @@ function parseIntCliOption(raw, name, min, max) {
|
|
|
4308
4789
|
return parsed;
|
|
4309
4790
|
}
|
|
4310
4791
|
function formatIndexingError(mapped) {
|
|
4792
|
+
if (mapped.code === "UPDATE_REQUIRED") {
|
|
4793
|
+
return formatMappedErrorForTerminal(mapped);
|
|
4794
|
+
}
|
|
4311
4795
|
if (mapped.code !== "INDEXING")
|
|
4312
4796
|
return mapped.message;
|
|
4313
4797
|
const detail = mapped.details ?? {};
|
|
@@ -4325,6 +4809,9 @@ function formatIndexingError(mapped) {
|
|
|
4325
4809
|
`);
|
|
4326
4810
|
}
|
|
4327
4811
|
function formatFileErrorWithFilesHint(mapped) {
|
|
4812
|
+
if (mapped.code === "UPDATE_REQUIRED") {
|
|
4813
|
+
return formatMappedErrorForTerminal(mapped);
|
|
4814
|
+
}
|
|
4328
4815
|
if (mapped.code === "FILE_NOT_FOUND") {
|
|
4329
4816
|
return `${mapped.message}
|
|
4330
4817
|
Use \`code files\` to list available paths.`;
|
|
@@ -4590,7 +5077,7 @@ grep run. --symbol-field hydrates enclosing symbol metadata (appears under each
|
|
|
4590
5077
|
match in --verbose output; full payload in --json).`;
|
|
4591
5078
|
function registerCodeGrepCommand(pkgCommand) {
|
|
4592
5079
|
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)", collectRepeatable, []).option("--ext <ext>", "Extension filter without leading dot (repeatable)", collectRepeatable, []).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}`, collectRepeatable, []).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) => {
|
|
4593
|
-
const { createContainer: createContainer2 } = await import("./shared/chunk-
|
|
5080
|
+
const { createContainer: createContainer2 } = await import("./shared/chunk-zg5dnven.js");
|
|
4594
5081
|
const deps = await createContainer2();
|
|
4595
5082
|
await pkgGrepAction(arg1, arg2, arg3, options, {
|
|
4596
5083
|
codeNavigationService: deps.codeNavigationService,
|
|
@@ -4974,7 +5461,7 @@ function handleDocsListError(error2, json) {
|
|
|
4974
5461
|
...mapped.details ? { details: mapped.details } : {}
|
|
4975
5462
|
}));
|
|
4976
5463
|
} else {
|
|
4977
|
-
console.error(mapped
|
|
5464
|
+
console.error(formatMappedErrorForTerminal(mapped));
|
|
4978
5465
|
}
|
|
4979
5466
|
process.exit(1);
|
|
4980
5467
|
}
|
|
@@ -5030,7 +5517,7 @@ function handleDocsReadError(error2, json) {
|
|
|
5030
5517
|
...mapped.details ? { details: mapped.details } : {}
|
|
5031
5518
|
}));
|
|
5032
5519
|
} else {
|
|
5033
|
-
console.error(mapped
|
|
5520
|
+
console.error(formatMappedErrorForTerminal(mapped));
|
|
5034
5521
|
}
|
|
5035
5522
|
process.exit(1);
|
|
5036
5523
|
}
|
|
@@ -5109,7 +5596,7 @@ function registerExampleCommand(program) {
|
|
|
5109
5596
|
});
|
|
5110
5597
|
}
|
|
5111
5598
|
async function loadContainer() {
|
|
5112
|
-
const { createContainer: createContainer2 } = await import("./shared/chunk-
|
|
5599
|
+
const { createContainer: createContainer2 } = await import("./shared/chunk-zg5dnven.js");
|
|
5113
5600
|
return createContainer2();
|
|
5114
5601
|
}
|
|
5115
5602
|
// src/commands/feedback.ts
|
|
@@ -5883,6 +6370,33 @@ var TIMEOUT_MS = 5 * 60 * 1000;
|
|
|
5883
6370
|
function randomPort() {
|
|
5884
6371
|
return Math.floor(Math.random() * 2000) + 8000;
|
|
5885
6372
|
}
|
|
6373
|
+
async function preflightAuthPersistence(authStorage, mcpUrl) {
|
|
6374
|
+
const probeUrl = `${mcpUrl.replace(/\/+$/, "")}/__githits_storage_probe__`;
|
|
6375
|
+
const probeClient = {
|
|
6376
|
+
clientId: "__githits_storage_probe__",
|
|
6377
|
+
clientSecret: "__githits_storage_probe__",
|
|
6378
|
+
redirectUri: "http://127.0.0.1:1/callback",
|
|
6379
|
+
registeredAt: new Date(0).toISOString()
|
|
6380
|
+
};
|
|
6381
|
+
const probeTokens = {
|
|
6382
|
+
accessToken: "__githits_storage_probe__",
|
|
6383
|
+
refreshToken: "__githits_storage_probe__",
|
|
6384
|
+
expiresAt: new Date(0).toISOString(),
|
|
6385
|
+
createdAt: new Date(0).toISOString()
|
|
6386
|
+
};
|
|
6387
|
+
try {
|
|
6388
|
+
await authStorage.saveAuthSession(probeUrl, probeClient, probeTokens);
|
|
6389
|
+
await authStorage.clearAuthSession(probeUrl);
|
|
6390
|
+
return null;
|
|
6391
|
+
} catch (error2) {
|
|
6392
|
+
await authStorage.clearAuthSession(probeUrl).catch(() => {});
|
|
6393
|
+
const message = error2 instanceof Error ? error2.message : String(error2);
|
|
6394
|
+
return {
|
|
6395
|
+
status: "failed",
|
|
6396
|
+
message: `Cannot persist OAuth credentials: ${message}`
|
|
6397
|
+
};
|
|
6398
|
+
}
|
|
6399
|
+
}
|
|
5886
6400
|
async function loginFlow(options, deps) {
|
|
5887
6401
|
const { authService, authStorage, browserService, mcpUrl } = deps;
|
|
5888
6402
|
if (options.port !== undefined && (Number.isNaN(options.port) || options.port < 1 || options.port > 65535)) {
|
|
@@ -5906,6 +6420,9 @@ async function loginFlow(options, deps) {
|
|
|
5906
6420
|
if (!existing) {
|
|
5907
6421
|
await authStorage.clearClient(mcpUrl);
|
|
5908
6422
|
}
|
|
6423
|
+
const persistenceError = await preflightAuthPersistence(authStorage, mcpUrl);
|
|
6424
|
+
if (persistenceError)
|
|
6425
|
+
return persistenceError;
|
|
5909
6426
|
console.log("Discovering OAuth endpoints...");
|
|
5910
6427
|
const metadata = await authService.discoverEndpoints(mcpUrl);
|
|
5911
6428
|
let client = await authStorage.loadClient(mcpUrl);
|
|
@@ -5926,7 +6443,6 @@ async function loginFlow(options, deps) {
|
|
|
5926
6443
|
redirectUri,
|
|
5927
6444
|
registeredAt: new Date().toISOString()
|
|
5928
6445
|
};
|
|
5929
|
-
await authStorage.saveClient(mcpUrl, client);
|
|
5930
6446
|
}
|
|
5931
6447
|
port = options.port;
|
|
5932
6448
|
} else {
|
|
@@ -5948,7 +6464,6 @@ async function loginFlow(options, deps) {
|
|
|
5948
6464
|
redirectUri,
|
|
5949
6465
|
registeredAt: new Date().toISOString()
|
|
5950
6466
|
};
|
|
5951
|
-
await authStorage.saveClient(mcpUrl, client);
|
|
5952
6467
|
}
|
|
5953
6468
|
const { verifier, challenge, state } = authService.generatePkceParams();
|
|
5954
6469
|
const authUrl = authService.buildAuthUrl({
|
|
@@ -6013,7 +6528,7 @@ async function loginFlow(options, deps) {
|
|
|
6013
6528
|
};
|
|
6014
6529
|
}
|
|
6015
6530
|
const expiresAt = new Date(Date.now() + tokenResponse.expiresIn * 1000).toISOString();
|
|
6016
|
-
await authStorage.
|
|
6531
|
+
await authStorage.saveAuthSession(mcpUrl, client, {
|
|
6017
6532
|
accessToken: tokenResponse.accessToken,
|
|
6018
6533
|
refreshToken: tokenResponse.refreshToken,
|
|
6019
6534
|
expiresAt,
|
|
@@ -6051,13 +6566,15 @@ You're ready to use githits with your AI assistant.`);
|
|
|
6051
6566
|
var LOGIN_DESCRIPTION = `Authenticate with your GitHits account via browser.
|
|
6052
6567
|
|
|
6053
6568
|
Opens your browser to complete authentication securely using OAuth.
|
|
6054
|
-
|
|
6569
|
+
OAuth credentials are stored in the system keychain by default. If your
|
|
6570
|
+
machine has no usable keychain, use GITHITS_API_TOKEN or explicitly configure
|
|
6571
|
+
auth.storage = "file". File storage is plaintext on disk.
|
|
6055
6572
|
|
|
6056
6573
|
Use --no-browser in environments without a display (CI, SSH sessions)
|
|
6057
6574
|
to get a URL you can open on another device.`;
|
|
6058
6575
|
function registerLoginCommand(program) {
|
|
6059
6576
|
program.command("login").summary("Authenticate with your GitHits account").description(LOGIN_DESCRIPTION).option("--no-browser", "Print URL instead of opening browser").option("--port <port>", "Port for local callback server", parseInt).option("--force", "Re-authenticate even if already logged in").action(async (options) => {
|
|
6060
|
-
const deps = await
|
|
6577
|
+
const deps = await createAuthCommandDependencies();
|
|
6061
6578
|
await loginAction(options, deps);
|
|
6062
6579
|
});
|
|
6063
6580
|
}
|
|
@@ -6252,7 +6769,7 @@ function registerInitCommand(program) {
|
|
|
6252
6769
|
fileSystemService,
|
|
6253
6770
|
promptService,
|
|
6254
6771
|
execService,
|
|
6255
|
-
createLoginDeps: () =>
|
|
6772
|
+
createLoginDeps: () => createAuthCommandDependencies()
|
|
6256
6773
|
});
|
|
6257
6774
|
});
|
|
6258
6775
|
}
|
|
@@ -6302,17 +6819,7 @@ function registerLanguagesCommand(program) {
|
|
|
6302
6819
|
async function logoutAction(deps) {
|
|
6303
6820
|
const { authStorage, mcpUrl } = deps;
|
|
6304
6821
|
const auth = await authStorage.loadTokens(mcpUrl);
|
|
6305
|
-
|
|
6306
|
-
try {
|
|
6307
|
-
await authStorage.clearTokens(mcpUrl);
|
|
6308
|
-
} catch (error2) {
|
|
6309
|
-
firstError = error2;
|
|
6310
|
-
}
|
|
6311
|
-
try {
|
|
6312
|
-
await authStorage.clearClient(mcpUrl);
|
|
6313
|
-
} catch (error2) {
|
|
6314
|
-
firstError ??= error2;
|
|
6315
|
-
}
|
|
6822
|
+
await authStorage.clearAuthSession(mcpUrl);
|
|
6316
6823
|
if (!auth) {
|
|
6317
6824
|
console.log(`Not currently logged in.
|
|
6318
6825
|
`);
|
|
@@ -6322,17 +6829,16 @@ async function logoutAction(deps) {
|
|
|
6322
6829
|
`);
|
|
6323
6830
|
console.log(` Environment: ${mcpUrl}`);
|
|
6324
6831
|
}
|
|
6325
|
-
if (firstError)
|
|
6326
|
-
throw firstError;
|
|
6327
6832
|
}
|
|
6328
6833
|
var LOGOUT_DESCRIPTION = `Remove stored credentials.
|
|
6329
6834
|
|
|
6330
6835
|
Clears all locally stored authentication data including tokens and
|
|
6331
6836
|
client registrations. OAuth tokens expire naturally; this
|
|
6332
|
-
removes
|
|
6837
|
+
removes local copies from the keychain, explicit file storage, and
|
|
6838
|
+
legacy auth file storage.`;
|
|
6333
6839
|
function registerLogoutCommand(program) {
|
|
6334
6840
|
program.command("logout").summary("Remove stored credentials").description(LOGOUT_DESCRIPTION).action(async () => {
|
|
6335
|
-
const deps = await
|
|
6841
|
+
const deps = await createAuthCommandDependencies();
|
|
6336
6842
|
await logoutAction(deps);
|
|
6337
6843
|
});
|
|
6338
6844
|
}
|
|
@@ -6368,8 +6874,9 @@ function classify3(operation, error2) {
|
|
|
6368
6874
|
if (error2 instanceof AuthenticationError) {
|
|
6369
6875
|
return {
|
|
6370
6876
|
error: error2.message,
|
|
6371
|
-
code: "
|
|
6372
|
-
retryable: false
|
|
6877
|
+
code: "AUTH_REQUIRED",
|
|
6878
|
+
retryable: false,
|
|
6879
|
+
details: { action: "Run `githits login`, then retry this tool call." }
|
|
6373
6880
|
};
|
|
6374
6881
|
}
|
|
6375
6882
|
const message = error2 instanceof Error ? error2.message : "Unknown error";
|
|
@@ -6816,17 +7323,15 @@ function buildPackageChangelogSuccessPayload(report, options) {
|
|
|
6816
7323
|
}
|
|
6817
7324
|
return lean;
|
|
6818
7325
|
});
|
|
6819
|
-
if (report.source == null) {
|
|
6820
|
-
throw new Error("Changelog envelope builder received a null source — should have been promoted to NOT_FOUND at the service boundary.");
|
|
6821
|
-
}
|
|
6822
7326
|
const envelope = {
|
|
6823
|
-
source: report.source,
|
|
6824
7327
|
mode: options.mode,
|
|
6825
7328
|
entries: {
|
|
6826
7329
|
count: items.length,
|
|
6827
7330
|
items
|
|
6828
7331
|
}
|
|
6829
7332
|
};
|
|
7333
|
+
if (report.source)
|
|
7334
|
+
envelope.source = report.source;
|
|
6830
7335
|
if (options.registry)
|
|
6831
7336
|
envelope.registry = options.registry;
|
|
6832
7337
|
if (options.name)
|
|
@@ -6905,7 +7410,7 @@ function appendBodyLines(lines, body, options) {
|
|
|
6905
7410
|
}
|
|
6906
7411
|
function buildSummaryLine(envelope, options) {
|
|
6907
7412
|
const identity = envelope.registry && envelope.name ? `${envelope.name} · ${envelope.registry}` : envelope.repoUrl ?? "(unknown)";
|
|
6908
|
-
const sourceLabel = humanizeSource(envelope.source);
|
|
7413
|
+
const sourceLabel = envelope.source ? humanizeSource(envelope.source) : "package versions";
|
|
6909
7414
|
const modeLabel = envelope.mode === "range" ? rangeLabel(envelope) : latestLabel(envelope);
|
|
6910
7415
|
const countLabel = `${envelope.entries.count} ${plural2("entry", "entries", envelope.entries.count)}`;
|
|
6911
7416
|
const parts = [identity, `source: ${sourceLabel}`, modeLabel, countLabel];
|
|
@@ -6974,7 +7479,7 @@ var schema6 = {
|
|
|
6974
7479
|
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."),
|
|
6975
7480
|
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.")
|
|
6976
7481
|
};
|
|
6977
|
-
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
|
|
7482
|
+
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"`), ' + "`entries: { count, items }` with full markdown bodies. Set " + "`include_bodies: false` for a version / date / URL timeline only. " + "Package-version entries without changelog text succeed with `source` " + "omitted; no-source plus no entries returns `NOT_FOUND`. Supports npm, " + "PyPI, Hex, Crates, vcpkg, Zig, NuGet, Maven, Packagist.";
|
|
6978
7483
|
function createPackageChangelogTool(service) {
|
|
6979
7484
|
return {
|
|
6980
7485
|
name: "pkg_changelog",
|
|
@@ -7141,7 +7646,7 @@ var schema9 = {
|
|
|
7141
7646
|
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."),
|
|
7142
7647
|
include_withdrawn: z10.boolean().optional().describe("Include retracted advisories (default: false).")
|
|
7143
7648
|
};
|
|
7144
|
-
var DESCRIPTION9 = "Check known vulnerabilities for a package on npm, PyPI, Hex, or " + "Crates (other registries are not yet supported for vulnerability " + "data). Returns a count summary, each advisory with OSV ID, " + "severity, affected ranges and fix versions
|
|
7649
|
+
var DESCRIPTION9 = "Check known vulnerabilities for a package on npm, PyPI, Hex, or " + "Crates (other registries are not yet 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. Pass `version` to inspect a specific release; otherwise " + "the latest is checked. Use `min_severity` to filter to a threshold " + "(`low`, `medium`, `high`, `critical`) and `include_withdrawn` to " + "also see retracted advisories.";
|
|
7145
7650
|
function createPackageVulnerabilitiesTool(service) {
|
|
7146
7651
|
return {
|
|
7147
7652
|
name: "pkg_vulns",
|
|
@@ -7368,7 +7873,7 @@ var schema12 = {
|
|
|
7368
7873
|
name: z13.string().optional(),
|
|
7369
7874
|
language: z13.string().optional(),
|
|
7370
7875
|
allow_partial_results: z13.boolean().optional().describe("Default false waits for all sources; if the wait window expires, returns only searchRef/progress. When true, includes hits from sources that finished so far and still returns searchRef for continuation. Partial payloads support normal pagination via nextOffset."),
|
|
7371
|
-
limit: z13.coerce.number().int().min(1).max(100).optional(),
|
|
7876
|
+
limit: z13.coerce.number().int().min(1).max(100).optional().describe("Maximum results to return (default 10, max 100)."),
|
|
7372
7877
|
offset: z13.coerce.number().int().min(0).optional(),
|
|
7373
7878
|
wait_timeout_ms: z13.coerce.number().int().min(0).max(60000).optional(),
|
|
7374
7879
|
format: z13.enum(["json", "text", "text-v1"]).optional().describe('Response format. Default `text-v1` — compact line-oriented output tuned for agent context efficiency. Pass `format: "json"` for the structured envelope (programmatic consumers, parity testing). `text` is an alias for `text-v1`. The text format is a public, snapshot-tested contract.')
|
|
@@ -7473,67 +7978,46 @@ function createSearchStatusTool(service) {
|
|
|
7473
7978
|
};
|
|
7474
7979
|
}
|
|
7475
7980
|
// src/commands/mcp-instructions.ts
|
|
7476
|
-
var CORE_BLOCK = `GitHits
|
|
7981
|
+
var CORE_BLOCK = `GitHits provides verified, canonical code examples from global open source. Use it when you're stuck, repeated attempts failed, you need up-to-date API usage, the question is comparative across OSS projects (e.g. "how does X vs Y handle Z"), the answer requires reading how a real codebase implements a feature, or the user mentions GitHits.
|
|
7477
7982
|
|
|
7478
|
-
|
|
7479
|
-
var PACKAGE_TOOLS_PREAMBLE = `
|
|
7983
|
+
Example workflow: call \`get_example\` with one focused question; pass \`language\` only when you know the exact language name, otherwise call \`search_language\` first. Send \`feedback\` on the returned solution_id. Reuse prior results before searching again.`;
|
|
7984
|
+
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.
|
|
7480
7985
|
|
|
7481
7986
|
Package spec: \`registry:name[@version]\`.`;
|
|
7482
7987
|
var PKG_INFO_BULLET = "- `pkg_info` — instant package overview: latest version, license, downloads, quickstart, and active advisory count.";
|
|
7483
|
-
var DOCS_LIST_BULLET = "- `docs_list` — browse
|
|
7988
|
+
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.";
|
|
7484
7989
|
var DOCS_READ_BULLET = "- `docs_read` — read a documentation page by pageId. Works for both hosted docs and repo-backed docs.";
|
|
7485
|
-
var PKG_VULNS_BULLET = "- `pkg_vulns` — known CVE / OSV advisories for npm, PyPI, Hex, or Crates packages
|
|
7486
|
-
var PKG_DEPS_BULLET = "- `pkg_deps` — direct runtime deps plus
|
|
7487
|
-
var PKG_CHANGELOG_BULLET = "- `pkg_changelog` — release notes for a package or GitHub repo, newest-first. Default latest mode returns
|
|
7488
|
-
var SEARCH_BULLET = '- `search` — unified search across indexed dependency code, docs, and
|
|
7489
|
-
var SEARCH_STATUS_BULLET = "- `search_status` — follow up a prior
|
|
7490
|
-
var CODE_FILES_BULLET = '- `code_files` —
|
|
7491
|
-
var CODE_READ_BULLET = "- `code_read` —
|
|
7492
|
-
var CODE_GREP_BULLET =
|
|
7990
|
+
var PKG_VULNS_BULLET = "- `pkg_vulns` — known CVE / OSV advisories for npm, PyPI, Hex, or Crates packages, optionally pinned to `@version`. Filter with `min_severity`; include retracted advisories with `include_withdrawn`.";
|
|
7991
|
+
var PKG_DEPS_BULLET = "- `pkg_deps` — direct runtime deps plus lifecycle/feature groups when available. Use `lifecycle` to filter groups, `include_transitive` for the full graph, and `include_importers` for provenance. Supports npm, PyPI, Hex, Crates, vcpkg, and Zig.";
|
|
7992
|
+
var PKG_CHANGELOG_BULLET = "- `pkg_changelog` — release notes for a package or GitHub repo, newest-first. Default latest mode returns recent entries with markdown bodies; `from_version` switches to range mode. Set `include_bodies: false` for a compact timeline.";
|
|
7993
|
+
var SEARCH_BULLET = '- `search` — unified search across indexed dependency code, docs, and symbols. Omit `sources` for AUTO. Default output is compact `text-v1`; pass `format: "json"` for locators, highlights, and source status. Complete by default; opt into partial hits with `allow_partial_results: true`. Incomplete responses carry a `searchRef`.';
|
|
7994
|
+
var SEARCH_STATUS_BULLET = "- `search_status` — follow up a prior `search` by `searchRef` to check progress, fetch partial hits, or fetch final results.";
|
|
7995
|
+
var CODE_FILES_BULLET = '- `code_files` — list files in an indexed dependency. Use `path_prefix` to scope to a directory. Returned paths feed into `code_read` and help scope `code_grep`; pass `format: "json"` for language/type/size metadata.';
|
|
7996
|
+
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.";
|
|
7997
|
+
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`.";
|
|
7493
7998
|
var SEARCH_VS_SYMBOLS_TIP = 'Prefer `get_example` for canonical example retrieval; prefer unified `search` for indexed dependency and repository discovery; use `sources:["symbol"]` when you want symbol-shaped results. Use `code_grep` for deterministic text matching and `code_read` for focused-window inspection of a known file.';
|
|
7494
|
-
var REFERENCE_FIRST_TIP = "Strategy — reference-first, content-second. Locate symbols and lines with `search` / `code_grep` first, then read only the
|
|
7495
|
-
var MULTI_TURN_TIP = '**Delegate multi-call work to a sub-agent.** Code-navigation
|
|
7496
|
-
function
|
|
7497
|
-
return deps.codeNavigationCliOverrideEnabled || deps.codeNavigationCapability === "enabled" || deps.codeNavigationCapability === "unknown" && deps.envApiToken !== undefined;
|
|
7498
|
-
}
|
|
7499
|
-
function buildMcpInstructions(deps) {
|
|
7999
|
+
var REFERENCE_FIRST_TIP = "Strategy — reference-first, content-second. Locate symbols and lines with `search` / `code_grep` first, then read only the needed window with `code_read` using explicit `start_line` / `end_line` values, typically 80-150 lines around the match. The MCP `code_read` surface caps each call at 150 lines.";
|
|
8000
|
+
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.';
|
|
8001
|
+
function buildMcpInstructions(_deps) {
|
|
7500
8002
|
const sections = [CORE_BLOCK];
|
|
7501
|
-
if (!isPackageToolsCapabilityOpen(deps)) {
|
|
7502
|
-
return sections.join(`
|
|
7503
|
-
|
|
7504
|
-
`);
|
|
7505
|
-
}
|
|
7506
8003
|
const bullets = [];
|
|
7507
|
-
|
|
7508
|
-
|
|
7509
|
-
|
|
7510
|
-
|
|
7511
|
-
|
|
7512
|
-
|
|
7513
|
-
|
|
7514
|
-
|
|
7515
|
-
|
|
7516
|
-
|
|
7517
|
-
|
|
7518
|
-
bullets.push(CODE_FILES_BULLET);
|
|
7519
|
-
bullets.push(CODE_READ_BULLET);
|
|
7520
|
-
bullets.push(CODE_GREP_BULLET);
|
|
7521
|
-
}
|
|
7522
|
-
if (bullets.length === 0) {
|
|
7523
|
-
return sections.join(`
|
|
7524
|
-
|
|
7525
|
-
`);
|
|
7526
|
-
}
|
|
8004
|
+
bullets.push(DOCS_LIST_BULLET);
|
|
8005
|
+
bullets.push(DOCS_READ_BULLET);
|
|
8006
|
+
bullets.push(PKG_INFO_BULLET);
|
|
8007
|
+
bullets.push(PKG_VULNS_BULLET);
|
|
8008
|
+
bullets.push(PKG_DEPS_BULLET);
|
|
8009
|
+
bullets.push(PKG_CHANGELOG_BULLET);
|
|
8010
|
+
bullets.push(SEARCH_BULLET);
|
|
8011
|
+
bullets.push(SEARCH_STATUS_BULLET);
|
|
8012
|
+
bullets.push(CODE_FILES_BULLET);
|
|
8013
|
+
bullets.push(CODE_READ_BULLET);
|
|
8014
|
+
bullets.push(CODE_GREP_BULLET);
|
|
7527
8015
|
const parts = [PACKAGE_TOOLS_PREAMBLE];
|
|
7528
|
-
|
|
7529
|
-
parts.push(MULTI_TURN_TIP);
|
|
7530
|
-
}
|
|
8016
|
+
parts.push(MULTI_TURN_TIP);
|
|
7531
8017
|
parts.push(bullets.join(`
|
|
7532
8018
|
`));
|
|
7533
|
-
|
|
7534
|
-
|
|
7535
|
-
parts.push(SEARCH_VS_SYMBOLS_TIP);
|
|
7536
|
-
}
|
|
8019
|
+
parts.push(REFERENCE_FIRST_TIP);
|
|
8020
|
+
parts.push(SEARCH_VS_SYMBOLS_TIP);
|
|
7537
8021
|
sections.push(parts.join(`
|
|
7538
8022
|
|
|
7539
8023
|
`));
|
|
@@ -7549,22 +8033,17 @@ function getMcpToolDefinitions(deps) {
|
|
|
7549
8033
|
eraseTool(createSearchLanguageTool(deps.githitsService)),
|
|
7550
8034
|
eraseTool(createFeedbackTool(deps.githitsService))
|
|
7551
8035
|
];
|
|
7552
|
-
|
|
7553
|
-
|
|
7554
|
-
|
|
7555
|
-
|
|
7556
|
-
|
|
7557
|
-
|
|
7558
|
-
|
|
7559
|
-
|
|
7560
|
-
|
|
7561
|
-
|
|
7562
|
-
|
|
7563
|
-
tools.push(eraseTool(createPackageSummaryTool(deps.packageIntelligenceService)));
|
|
7564
|
-
tools.push(eraseTool(createPackageVulnerabilitiesTool(deps.packageIntelligenceService)));
|
|
7565
|
-
tools.push(eraseTool(createPackageDependenciesTool(deps.packageIntelligenceService)));
|
|
7566
|
-
tools.push(eraseTool(createPackageChangelogTool(deps.packageIntelligenceService)));
|
|
7567
|
-
}
|
|
8036
|
+
tools.push(eraseTool(createSearchTool(deps.codeNavigationService)));
|
|
8037
|
+
tools.push(eraseTool(createSearchStatusTool(deps.codeNavigationService)));
|
|
8038
|
+
tools.push(eraseTool(createListFilesTool(deps.codeNavigationService)));
|
|
8039
|
+
tools.push(eraseTool(createReadFileTool(deps.codeNavigationService)));
|
|
8040
|
+
tools.push(eraseTool(createGrepRepoTool(deps.codeNavigationService)));
|
|
8041
|
+
tools.push(eraseTool(createListPackageDocsTool(deps.packageIntelligenceService)));
|
|
8042
|
+
tools.push(eraseTool(createReadPackageDocTool(deps.packageIntelligenceService)));
|
|
8043
|
+
tools.push(eraseTool(createPackageSummaryTool(deps.packageIntelligenceService)));
|
|
8044
|
+
tools.push(eraseTool(createPackageVulnerabilitiesTool(deps.packageIntelligenceService)));
|
|
8045
|
+
tools.push(eraseTool(createPackageDependenciesTool(deps.packageIntelligenceService)));
|
|
8046
|
+
tools.push(eraseTool(createPackageChangelogTool(deps.packageIntelligenceService)));
|
|
7568
8047
|
return tools;
|
|
7569
8048
|
}
|
|
7570
8049
|
function eraseTool(tool) {
|
|
@@ -7632,7 +8111,7 @@ function registerMcpCommand(program) {
|
|
|
7632
8111
|
When run interactively (TTY), shows setup instructions.
|
|
7633
8112
|
When run via stdio (non-TTY), starts the MCP server.
|
|
7634
8113
|
|
|
7635
|
-
|
|
8114
|
+
Authenticated tool calls require a valid GitHits token.`).action(async () => {
|
|
7636
8115
|
if (process.stdout.isTTY && process.stdin.isTTY) {
|
|
7637
8116
|
showMcpSetupInstructions();
|
|
7638
8117
|
return;
|
|
@@ -7721,6 +8200,9 @@ function handlePkgChangelogCommandError(error2, json) {
|
|
|
7721
8200
|
process.exit(1);
|
|
7722
8201
|
}
|
|
7723
8202
|
function formatChangelogTerminalError(mapped) {
|
|
8203
|
+
if (mapped.code === "UPDATE_REQUIRED") {
|
|
8204
|
+
return formatMappedErrorForTerminal(mapped);
|
|
8205
|
+
}
|
|
7724
8206
|
if (mapped.code !== "VERSION_NOT_FOUND")
|
|
7725
8207
|
return mapped.message;
|
|
7726
8208
|
const detail = mapped.details ?? {};
|
|
@@ -7844,6 +8326,9 @@ function handlePkgDepsCommandError(error2, json) {
|
|
|
7844
8326
|
process.exit(1);
|
|
7845
8327
|
}
|
|
7846
8328
|
function formatDepsTerminalError(mapped) {
|
|
8329
|
+
if (mapped.code === "UPDATE_REQUIRED") {
|
|
8330
|
+
return formatMappedErrorForTerminal(mapped);
|
|
8331
|
+
}
|
|
7847
8332
|
if (mapped.code !== "VERSION_NOT_FOUND")
|
|
7848
8333
|
return mapped.message;
|
|
7849
8334
|
const detail = mapped.details ?? {};
|
|
@@ -7930,7 +8415,7 @@ function handlePkgInfoCommandError(error2, json) {
|
|
|
7930
8415
|
}));
|
|
7931
8416
|
process.exit(1);
|
|
7932
8417
|
}
|
|
7933
|
-
console.error(mapped
|
|
8418
|
+
console.error(formatMappedErrorForTerminal(mapped));
|
|
7934
8419
|
process.exit(1);
|
|
7935
8420
|
}
|
|
7936
8421
|
var PKG_INFO_DESCRIPTION = `Get a package overview — latest version, license, description,
|
|
@@ -8003,6 +8488,9 @@ function handlePkgVulnsCommandError(error2, json) {
|
|
|
8003
8488
|
process.exit(1);
|
|
8004
8489
|
}
|
|
8005
8490
|
function formatVulnsTerminalError(mapped) {
|
|
8491
|
+
if (mapped.code === "UPDATE_REQUIRED") {
|
|
8492
|
+
return formatMappedErrorForTerminal(mapped);
|
|
8493
|
+
}
|
|
8006
8494
|
if (mapped.code !== "VERSION_NOT_FOUND")
|
|
8007
8495
|
return mapped.message;
|
|
8008
8496
|
const detail = mapped.details ?? {};
|
|
@@ -8027,8 +8515,8 @@ function formatVulnsTerminalError(mapped) {
|
|
|
8027
8515
|
`);
|
|
8028
8516
|
}
|
|
8029
8517
|
var PKG_VULNS_DESCRIPTION = `Show known vulnerabilities for a package. Lists CVE / OSV advisories
|
|
8030
|
-
with severity, affected version ranges, fix versions
|
|
8031
|
-
|
|
8518
|
+
with severity, affected version ranges, and fix versions.
|
|
8519
|
+
Malicious-package advisories are flagged prominently.
|
|
8032
8520
|
|
|
8033
8521
|
Package spec: <registry>:<name>[@<version>]. Supported registries:
|
|
8034
8522
|
npm, pypi, hex, crates. Omit @<version> to check the latest release.
|
|
@@ -8155,7 +8643,7 @@ function registerSearchCommand(program) {
|
|
|
8155
8643
|
"fixture",
|
|
8156
8644
|
"build",
|
|
8157
8645
|
"vendor"
|
|
8158
|
-
])).option("--public", "Filter to public symbols when supported").option("--name <name>", "Structured name qualifier").option("--lang <language>", "Structured language qualifier").option("--allow-partial", "Include hits already available while indexing continues; a searchRef is still returned so search-status can fetch the rest").option("--limit <n>", "Max results (1-100)").option("--offset <n>", "Result offset").option("--wait <seconds>", "Max seconds to wait before returning a searchRef (0-60; default: 20)").option("--json", "Output as JSON").action(async (query, options) => {
|
|
8646
|
+
])).option("--public", "Filter to public symbols when supported").option("--name <name>", "Structured name qualifier").option("--lang <language>", "Structured language qualifier").option("--allow-partial", "Include hits already available while indexing continues; a searchRef is still returned so search-status can fetch the rest").option("--limit <n>", "Max results (1-100, default: 10)").option("--offset <n>", "Result offset").option("--wait <seconds>", "Max seconds to wait before returning a searchRef (0-60; default: 20)").option("--json", "Output as JSON").action(async (query, options) => {
|
|
8159
8647
|
const deps = await loadContainer2();
|
|
8160
8648
|
await searchAction(query, options, deps);
|
|
8161
8649
|
});
|
|
@@ -8169,14 +8657,6 @@ async function registerUnifiedSearchCommands(program, options = {}) {
|
|
|
8169
8657
|
if (!codeNavigationUrl) {
|
|
8170
8658
|
return;
|
|
8171
8659
|
}
|
|
8172
|
-
const overrideEnabled = options.overrideEnabled ?? isCodeNavigationCliOverrideEnabled();
|
|
8173
|
-
const registrationState = options.capability !== undefined || options.expiredStoredAuth !== undefined ? {
|
|
8174
|
-
capability: options.capability ?? "unknown",
|
|
8175
|
-
expiredStoredAuth: options.expiredStoredAuth ?? false
|
|
8176
|
-
} : await loadStartupCodeNavigationRegistrationState();
|
|
8177
|
-
if (!overrideEnabled && registrationState.capability !== "enabled" && !registrationState.expiredStoredAuth) {
|
|
8178
|
-
return;
|
|
8179
|
-
}
|
|
8180
8660
|
registerSearchCommand(program);
|
|
8181
8661
|
}
|
|
8182
8662
|
function requireSearchService(deps) {
|
|
@@ -8186,13 +8666,9 @@ function requireSearchService(deps) {
|
|
|
8186
8666
|
return deps.codeNavigationService;
|
|
8187
8667
|
}
|
|
8188
8668
|
async function loadContainer2() {
|
|
8189
|
-
const { createContainer: createContainer2 } = await import("./shared/chunk-
|
|
8669
|
+
const { createContainer: createContainer2 } = await import("./shared/chunk-zg5dnven.js");
|
|
8190
8670
|
return createContainer2();
|
|
8191
8671
|
}
|
|
8192
|
-
async function loadStartupCodeNavigationRegistrationState() {
|
|
8193
|
-
const { resolveStartupCodeNavigationRegistrationState: resolveStartupCodeNavigationRegistrationState2 } = await import("./shared/chunk-9zze00cp.js");
|
|
8194
|
-
return resolveStartupCodeNavigationRegistrationState2();
|
|
8195
|
-
}
|
|
8196
8672
|
function parseTargetSpecs(specs) {
|
|
8197
8673
|
if (!specs || specs.length === 0) {
|
|
8198
8674
|
throw new InvalidArgumentError("Provide at least one --in target.");
|
|
@@ -8525,7 +9001,32 @@ function formatUnifiedSearchMetadata(entry, useColors) {
|
|
|
8525
9001
|
}
|
|
8526
9002
|
// src/cli.ts
|
|
8527
9003
|
var program = new Command;
|
|
9004
|
+
var argv = process.argv.slice(2);
|
|
8528
9005
|
var commandSpans = new WeakMap;
|
|
9006
|
+
var createUpdateCheckService = () => new NpmRegistryUpdateCheckService({
|
|
9007
|
+
currentVersion: version,
|
|
9008
|
+
fileSystemService: new FileSystemServiceImpl
|
|
9009
|
+
});
|
|
9010
|
+
await enforceCachedRequiredUpdateForInvocation({
|
|
9011
|
+
args: argv,
|
|
9012
|
+
env: process.env,
|
|
9013
|
+
createService: createUpdateCheckService,
|
|
9014
|
+
stderr: process.stderr,
|
|
9015
|
+
exit: process.exit
|
|
9016
|
+
});
|
|
9017
|
+
var updateCheckTask = startUpdateCheckTaskForInvocation({
|
|
9018
|
+
args: argv,
|
|
9019
|
+
env: process.env,
|
|
9020
|
+
stderrIsTTY: process.stderr.isTTY === true,
|
|
9021
|
+
stdinIsTTY: process.stdin.isTTY === true,
|
|
9022
|
+
stdoutIsTTY: process.stdout.isTTY === true,
|
|
9023
|
+
createService: createUpdateCheckService
|
|
9024
|
+
});
|
|
9025
|
+
var requiredUpdateRefreshTask = startRequiredUpdateRefreshTaskForInvocation({
|
|
9026
|
+
args: argv,
|
|
9027
|
+
env: process.env,
|
|
9028
|
+
createService: createUpdateCheckService
|
|
9029
|
+
});
|
|
8529
9030
|
if (isTelemetryEnabled()) {
|
|
8530
9031
|
process.once("exit", (exitCode) => {
|
|
8531
9032
|
flushTelemetry(exitCode);
|
|
@@ -8556,25 +9057,29 @@ registerMcpCommand(program);
|
|
|
8556
9057
|
registerExampleCommand(program);
|
|
8557
9058
|
registerLanguagesCommand(program);
|
|
8558
9059
|
registerFeedbackCommand(program);
|
|
8559
|
-
var argv = process.argv.slice(2);
|
|
8560
9060
|
var registrationArgv = stripRootRegistrationOptions(argv);
|
|
8561
|
-
var shouldLoadGatedHelpRegistration = needsGatedHelpRegistration(registrationArgv);
|
|
8562
|
-
var helpRegistrationOptions = shouldLoadGatedHelpRegistration ? await loadHelpRegistrationOptions(registrationArgv) : undefined;
|
|
8563
9061
|
if (shouldEagerLoadSearchCommands(registrationArgv)) {
|
|
8564
|
-
await withTelemetrySpan("cli.register.search", () => registerUnifiedSearchCommands(program
|
|
9062
|
+
await withTelemetrySpan("cli.register.search", () => registerUnifiedSearchCommands(program));
|
|
8565
9063
|
}
|
|
8566
9064
|
if (shouldEagerLoadGatedCommandGroup(registrationArgv, "code")) {
|
|
8567
|
-
await withTelemetrySpan("cli.register.code-group", () => registerCodeCommandGroup(program
|
|
9065
|
+
await withTelemetrySpan("cli.register.code-group", () => registerCodeCommandGroup(program));
|
|
8568
9066
|
}
|
|
8569
9067
|
if (shouldEagerLoadGatedCommandGroup(registrationArgv, "pkg")) {
|
|
8570
|
-
await withTelemetrySpan("cli.register.pkg-group", () => registerPkgCommandGroup(program
|
|
9068
|
+
await withTelemetrySpan("cli.register.pkg-group", () => registerPkgCommandGroup(program));
|
|
8571
9069
|
}
|
|
8572
9070
|
if (shouldEagerLoadGatedCommandGroup(registrationArgv, "docs")) {
|
|
8573
|
-
await withTelemetrySpan("cli.register.docs-group", () => registerDocsCommandGroup(program
|
|
9071
|
+
await withTelemetrySpan("cli.register.docs-group", () => registerDocsCommandGroup(program));
|
|
8574
9072
|
}
|
|
8575
9073
|
var authCommand = program.command("auth").summary("Manage authentication").description("Manage authentication with GitHits.");
|
|
8576
9074
|
registerAuthStatusCommand(authCommand);
|
|
8577
|
-
|
|
9075
|
+
try {
|
|
9076
|
+
await runWithUpdateCheckFlush(() => withTelemetrySpan("cli.parse", () => program.parseAsync()), updateCheckTask, { stderr: process.stderr, requiredUpdateRefreshTask });
|
|
9077
|
+
} catch (error2) {
|
|
9078
|
+
handleCliError(error2, {
|
|
9079
|
+
stderr: process.stderr,
|
|
9080
|
+
exit: process.exit
|
|
9081
|
+
});
|
|
9082
|
+
}
|
|
8578
9083
|
function stripRootRegistrationOptions(args) {
|
|
8579
9084
|
return args.filter((arg) => arg !== "--no-color");
|
|
8580
9085
|
}
|
|
@@ -8586,34 +9091,9 @@ function shouldEagerLoadSearchCommands(args) {
|
|
|
8586
9091
|
const [firstArg] = args;
|
|
8587
9092
|
return args.length === 0 || firstArg === "search" || firstArg === "search-status" || firstArg === "--help" || firstArg === "-h" || firstArg === "help" && (!args[1] || isSearchHelpTarget(args[1]));
|
|
8588
9093
|
}
|
|
8589
|
-
function isHelpInvocation(args) {
|
|
8590
|
-
return args.length === 0 || args[0] === "help" || args.includes("--help") || args.includes("-h");
|
|
8591
|
-
}
|
|
8592
|
-
function needsGatedHelpRegistration(args) {
|
|
8593
|
-
if (!isHelpInvocation(args)) {
|
|
8594
|
-
return false;
|
|
8595
|
-
}
|
|
8596
|
-
const [firstArg, secondArg] = args;
|
|
8597
|
-
if (firstArg === "help") {
|
|
8598
|
-
return isSearchHelpTarget(secondArg) || secondArg === "code" || secondArg === "pkg" || secondArg === "docs";
|
|
8599
|
-
}
|
|
8600
|
-
return isSearchHelpTarget(firstArg) || firstArg === "code" || firstArg === "pkg" || firstArg === "docs";
|
|
8601
|
-
}
|
|
8602
9094
|
function isSearchHelpTarget(value) {
|
|
8603
9095
|
return value === "search" || value === "search-status";
|
|
8604
9096
|
}
|
|
8605
|
-
async function loadHelpRegistrationOptions(args) {
|
|
8606
|
-
const { resolveStartupCodeNavigationRegistrationState: resolveStartupCodeNavigationRegistrationState2 } = await import("./shared/chunk-9zze00cp.js");
|
|
8607
|
-
const registrationState = await resolveStartupCodeNavigationRegistrationState2();
|
|
8608
|
-
return {
|
|
8609
|
-
capability: registrationState.capability,
|
|
8610
|
-
expiredStoredAuth: shouldUseExpiredStoredAuthFallbackForHelp(args) ? registrationState.expiredStoredAuth : false
|
|
8611
|
-
};
|
|
8612
|
-
}
|
|
8613
|
-
function shouldUseExpiredStoredAuthFallbackForHelp(args) {
|
|
8614
|
-
const [firstArg, secondArg] = args;
|
|
8615
|
-
return firstArg === "search" || firstArg === "search-status" || firstArg === "code" || firstArg === "pkg" || firstArg === "docs" || firstArg === "help" && (isSearchHelpTarget(secondArg) || secondArg === "code" || secondArg === "pkg" || secondArg === "docs");
|
|
8616
|
-
}
|
|
8617
9097
|
function getTelemetryCommandName(command) {
|
|
8618
9098
|
const names = [];
|
|
8619
9099
|
let current = command;
|