githits 0.4.5 → 0.4.6
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 +2 -1
- package/README.md +3 -2
- package/commands/help.md +2 -1
- package/dist/cli.js +710 -150
- package/dist/index.js +1 -1
- package/dist/shared/{chunk-zzmbjttb.js → chunk-2fdxv7pe.js} +2 -2
- package/dist/shared/{chunk-vfyz65v1.js → chunk-a1hzwt2m.js} +1 -1
- package/dist/shared/{chunk-ygqss6gp.js → chunk-f16s86ze.js} +413 -78
- package/gemini-extension.json +1 -1
- package/package.json +10 -10
- package/plugins/claude/.claude-plugin/plugin.json +1 -1
- package/plugins/claude/commands/help.md +2 -1
- package/skills/githits-code/SKILL.md +1 -1
- package/skills/githits-code/references/code-and-docs.md +2 -2
package/dist/cli.js
CHANGED
|
@@ -51,11 +51,11 @@ import {
|
|
|
51
51
|
shouldRunUpdateCheck,
|
|
52
52
|
startTelemetrySpan,
|
|
53
53
|
withTelemetrySpan
|
|
54
|
-
} from "./shared/chunk-
|
|
54
|
+
} from "./shared/chunk-f16s86ze.js";
|
|
55
55
|
import {
|
|
56
56
|
__require,
|
|
57
57
|
version
|
|
58
|
-
} from "./shared/chunk-
|
|
58
|
+
} from "./shared/chunk-a1hzwt2m.js";
|
|
59
59
|
|
|
60
60
|
// src/cli.ts
|
|
61
61
|
import { Command } from "commander";
|
|
@@ -583,6 +583,12 @@ function classify(error2) {
|
|
|
583
583
|
if (error2.availableVersions && error2.availableVersions.length > 0) {
|
|
584
584
|
details.availableVersions = error2.availableVersions;
|
|
585
585
|
}
|
|
586
|
+
if (error2.availableRefs && error2.availableRefs.length > 0) {
|
|
587
|
+
details.availableRefs = error2.availableRefs;
|
|
588
|
+
}
|
|
589
|
+
if (error2.targetResolution) {
|
|
590
|
+
details.targetResolution = error2.targetResolution;
|
|
591
|
+
}
|
|
586
592
|
return {
|
|
587
593
|
code: "INDEXING",
|
|
588
594
|
message: error2.message,
|
|
@@ -788,7 +794,7 @@ function parseCodeNavigationTargetSpec(spec) {
|
|
|
788
794
|
function parseRepoTarget(spec) {
|
|
789
795
|
const hashIndex = spec.lastIndexOf("#");
|
|
790
796
|
if (hashIndex === -1) {
|
|
791
|
-
|
|
797
|
+
return { repoUrl: spec };
|
|
792
798
|
}
|
|
793
799
|
const repoUrl = spec.slice(0, hashIndex);
|
|
794
800
|
const gitRef = spec.slice(hashIndex + 1);
|
|
@@ -827,6 +833,7 @@ function buildSearchHitFollowUpCommand(hit) {
|
|
|
827
833
|
version: loc.version,
|
|
828
834
|
repoUrl: loc.repoUrl,
|
|
829
835
|
gitRef: loc.gitRef,
|
|
836
|
+
requestedRef: loc.requestedRef,
|
|
830
837
|
filePath: loc.filePath,
|
|
831
838
|
startLine: loc.startLine,
|
|
832
839
|
endLine: loc.endLine,
|
|
@@ -863,9 +870,8 @@ function buildTargetSpec(input) {
|
|
|
863
870
|
return `${input.registry}:${input.packageName}${input.version ? `@${input.version}` : ""}`;
|
|
864
871
|
}
|
|
865
872
|
if (input.repoUrl) {
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
return `${input.repoUrl}#${input.gitRef}`;
|
|
873
|
+
const ref = input.gitRef ?? input.requestedRef;
|
|
874
|
+
return ref ? `${input.repoUrl}#${ref}` : input.repoUrl;
|
|
869
875
|
}
|
|
870
876
|
if (input.registry && input.packageName) {
|
|
871
877
|
return `${input.registry}:${input.packageName}${input.version ? `@${input.version}` : ""}`;
|
|
@@ -1061,6 +1067,161 @@ function shellQuote(value) {
|
|
|
1061
1067
|
return `'${value.replaceAll("'", `'"'"'`)}'`;
|
|
1062
1068
|
}
|
|
1063
1069
|
|
|
1070
|
+
// src/shared/target-resolution.ts
|
|
1071
|
+
function projectTargetResolution(resolution) {
|
|
1072
|
+
if (!resolution)
|
|
1073
|
+
return;
|
|
1074
|
+
return {
|
|
1075
|
+
...resolution.requested ? { requested: projectIdentity(resolution.requested) } : {},
|
|
1076
|
+
...resolution.resolvedRequested ? { resolvedRequested: projectIdentity(resolution.resolvedRequested) } : {},
|
|
1077
|
+
...resolution.served ? { served: projectIdentity(resolution.served) } : {},
|
|
1078
|
+
...resolution.freshness ? { freshness: resolution.freshness } : {},
|
|
1079
|
+
...resolution.freshnessReason ? { freshnessReason: resolution.freshnessReason } : {},
|
|
1080
|
+
...resolution.indexingRef ? { indexingRef: resolution.indexingRef } : {},
|
|
1081
|
+
availableVersions: resolution.availableVersions.map(projectArtifact),
|
|
1082
|
+
availableRefs: resolution.availableRefs.map(projectArtifact)
|
|
1083
|
+
};
|
|
1084
|
+
}
|
|
1085
|
+
function buildTargetResolutionNotes(resolution) {
|
|
1086
|
+
if (!resolution)
|
|
1087
|
+
return [];
|
|
1088
|
+
const lines = [];
|
|
1089
|
+
const requested = formatIdentity(resolution.requested);
|
|
1090
|
+
const fresh = formatIdentity(resolution.resolvedRequested);
|
|
1091
|
+
const served = formatIdentity(resolution.served);
|
|
1092
|
+
const reason = resolution.freshnessReason ? ` (${resolution.freshnessReason})` : "";
|
|
1093
|
+
switch (resolution.freshness) {
|
|
1094
|
+
case "fallback_recent": {
|
|
1095
|
+
const parts = ["using recent index"];
|
|
1096
|
+
if (served)
|
|
1097
|
+
parts.push(`served=${served}`);
|
|
1098
|
+
if (fresh && identitiesMateriallyDiffer(fresh, served)) {
|
|
1099
|
+
parts.push(`fresh=${fresh}`);
|
|
1100
|
+
}
|
|
1101
|
+
lines.push(`${parts.join(" | ")}${reason}`);
|
|
1102
|
+
break;
|
|
1103
|
+
}
|
|
1104
|
+
case "indexing": {
|
|
1105
|
+
const parts = ["indexing fresh target"];
|
|
1106
|
+
if (requested)
|
|
1107
|
+
parts.push(`requested=${requested}`);
|
|
1108
|
+
if (fresh)
|
|
1109
|
+
parts.push(`fresh=${fresh}`);
|
|
1110
|
+
if (resolution.indexingRef)
|
|
1111
|
+
parts.push(`indexingRef=${resolution.indexingRef}`);
|
|
1112
|
+
lines.push(`${parts.join(" | ")}${reason}`);
|
|
1113
|
+
break;
|
|
1114
|
+
}
|
|
1115
|
+
case "unavailable": {
|
|
1116
|
+
const parts = ["target unavailable"];
|
|
1117
|
+
if (requested)
|
|
1118
|
+
parts.push(`requested=${requested}`);
|
|
1119
|
+
lines.push(`${parts.join(" | ")}${reason}`);
|
|
1120
|
+
break;
|
|
1121
|
+
}
|
|
1122
|
+
case "current": {
|
|
1123
|
+
break;
|
|
1124
|
+
}
|
|
1125
|
+
default: {
|
|
1126
|
+
if (resolution.freshness || identitiesDiffer(requested, fresh, served)) {
|
|
1127
|
+
const parts = [
|
|
1128
|
+
`target resolution: ${resolution.freshness ?? "unknown"}`
|
|
1129
|
+
];
|
|
1130
|
+
if (served)
|
|
1131
|
+
parts.push(`served=${served}`);
|
|
1132
|
+
if (requested)
|
|
1133
|
+
parts.push(`requested=${requested}`);
|
|
1134
|
+
if (fresh && fresh !== served)
|
|
1135
|
+
parts.push(`fresh=${fresh}`);
|
|
1136
|
+
lines.push(`${parts.join(" | ")}${reason}`);
|
|
1137
|
+
}
|
|
1138
|
+
break;
|
|
1139
|
+
}
|
|
1140
|
+
}
|
|
1141
|
+
const candidates = buildRetryCandidateLine(resolution);
|
|
1142
|
+
if (candidates)
|
|
1143
|
+
lines.push(candidates);
|
|
1144
|
+
return lines;
|
|
1145
|
+
}
|
|
1146
|
+
function buildRetryCandidateLine(resolution) {
|
|
1147
|
+
if (!resolution)
|
|
1148
|
+
return;
|
|
1149
|
+
const parts = [];
|
|
1150
|
+
if (resolution.availableVersions.length > 0) {
|
|
1151
|
+
parts.push(`versions=${resolution.availableVersions.map(formatArtifact).join(",")}`);
|
|
1152
|
+
}
|
|
1153
|
+
if (resolution.availableRefs.length > 0) {
|
|
1154
|
+
parts.push(`refs=${resolution.availableRefs.map(formatArtifact).join(",")}`);
|
|
1155
|
+
}
|
|
1156
|
+
return parts.length > 0 ? `queryable now: ${parts.join(" | ")}` : undefined;
|
|
1157
|
+
}
|
|
1158
|
+
function buildResolutionFromRetryCandidates(target) {
|
|
1159
|
+
if (!target.availableVersions?.length && !target.availableRefs?.length) {
|
|
1160
|
+
return;
|
|
1161
|
+
}
|
|
1162
|
+
return {
|
|
1163
|
+
freshness: target.freshness,
|
|
1164
|
+
indexingRef: target.indexingRef,
|
|
1165
|
+
availableVersions: target.availableVersions ?? [],
|
|
1166
|
+
availableRefs: target.availableRefs ?? []
|
|
1167
|
+
};
|
|
1168
|
+
}
|
|
1169
|
+
function projectIdentity(identity) {
|
|
1170
|
+
const out = {};
|
|
1171
|
+
if (identity.kind)
|
|
1172
|
+
out.kind = identity.kind;
|
|
1173
|
+
if (identity.registry)
|
|
1174
|
+
out.registry = identity.registry;
|
|
1175
|
+
if (identity.packageName)
|
|
1176
|
+
out.packageName = identity.packageName;
|
|
1177
|
+
if (identity.version)
|
|
1178
|
+
out.version = identity.version;
|
|
1179
|
+
if (identity.repoUrl)
|
|
1180
|
+
out.repoUrl = identity.repoUrl;
|
|
1181
|
+
if (identity.gitRef)
|
|
1182
|
+
out.gitRef = identity.gitRef;
|
|
1183
|
+
if (identity.commitSha)
|
|
1184
|
+
out.commitSha = identity.commitSha;
|
|
1185
|
+
return out;
|
|
1186
|
+
}
|
|
1187
|
+
function projectArtifact(artifact) {
|
|
1188
|
+
return artifact.version ? { version: artifact.version, ref: artifact.ref } : { ref: artifact.ref };
|
|
1189
|
+
}
|
|
1190
|
+
function formatIdentity(identity) {
|
|
1191
|
+
if (!identity)
|
|
1192
|
+
return;
|
|
1193
|
+
if (identity.registry && identity.packageName) {
|
|
1194
|
+
const version2 = identity.version ? `@${identity.version}` : "";
|
|
1195
|
+
const commit = identity.commitSha ? `#${shortSha(identity.commitSha)}` : "";
|
|
1196
|
+
return `${identity.registry.toLowerCase()}:${identity.packageName}${version2}${commit}`;
|
|
1197
|
+
}
|
|
1198
|
+
if (identity.repoUrl) {
|
|
1199
|
+
const ref = identity.gitRef ? `#${identity.gitRef}` : "";
|
|
1200
|
+
const commit = identity.commitSha ? `@${shortSha(identity.commitSha)}` : "";
|
|
1201
|
+
return `${identity.repoUrl}${ref}${commit}`;
|
|
1202
|
+
}
|
|
1203
|
+
return identity.gitRef ?? identity.version ?? identity.commitSha ?? identity.kind;
|
|
1204
|
+
}
|
|
1205
|
+
function formatArtifact(artifact) {
|
|
1206
|
+
return artifact.version ? `${artifact.version}@${artifact.ref}` : artifact.ref;
|
|
1207
|
+
}
|
|
1208
|
+
function identitiesDiffer(requested, fresh, served) {
|
|
1209
|
+
if (!served)
|
|
1210
|
+
return Boolean(requested || fresh);
|
|
1211
|
+
return Boolean(requested && requested !== served || fresh && fresh !== served);
|
|
1212
|
+
}
|
|
1213
|
+
function identitiesMateriallyDiffer(left, right) {
|
|
1214
|
+
if (!left || !right)
|
|
1215
|
+
return Boolean(left || right);
|
|
1216
|
+
return stripShortCommit(left) !== stripShortCommit(right);
|
|
1217
|
+
}
|
|
1218
|
+
function stripShortCommit(value) {
|
|
1219
|
+
return value.replace(/[@#][0-9a-f]{7}$/i, "");
|
|
1220
|
+
}
|
|
1221
|
+
function shortSha(value) {
|
|
1222
|
+
return /^[0-9a-f]{12,}$/i.test(value) ? value.slice(0, 7) : value;
|
|
1223
|
+
}
|
|
1224
|
+
|
|
1064
1225
|
// src/shared/grep-repo-response.ts
|
|
1065
1226
|
var UTF8_ENCODER = new TextEncoder;
|
|
1066
1227
|
function buildGrepRepoSuccessPayload(result, options) {
|
|
@@ -1102,6 +1263,9 @@ function buildGrepRepoSuccessPayload(result, options) {
|
|
|
1102
1263
|
if (result.resolution) {
|
|
1103
1264
|
envelope.resolution = projectResolution(result.resolution);
|
|
1104
1265
|
}
|
|
1266
|
+
const targetResolution = projectTargetResolution(result.targetResolution);
|
|
1267
|
+
if (targetResolution)
|
|
1268
|
+
envelope.targetResolution = targetResolution;
|
|
1105
1269
|
const filter = buildFilterBlock(options);
|
|
1106
1270
|
if (filter)
|
|
1107
1271
|
envelope.filter = filter;
|
|
@@ -1189,8 +1353,11 @@ function buildFilterBlock(options) {
|
|
|
1189
1353
|
return Object.keys(filter).length > 0 ? filter : undefined;
|
|
1190
1354
|
}
|
|
1191
1355
|
function formatGrepRepoTerminal(envelope, options) {
|
|
1192
|
-
if (envelope.matches.length === 0) {
|
|
1193
|
-
return {
|
|
1356
|
+
if (envelope.matches.length === 0 && !options.verbose) {
|
|
1357
|
+
return {
|
|
1358
|
+
stdout: "",
|
|
1359
|
+
stderr: formatTerminalNotes(envelope, options.useColors)
|
|
1360
|
+
};
|
|
1194
1361
|
}
|
|
1195
1362
|
const blocks = buildRenderBlocks(envelope.matches);
|
|
1196
1363
|
return options.verbose ? formatVerbose(envelope, blocks, options) : formatPlain(envelope, blocks, options);
|
|
@@ -1247,6 +1414,10 @@ function formatVerbose(envelope, blocks, options) {
|
|
|
1247
1414
|
}
|
|
1248
1415
|
lines.push("");
|
|
1249
1416
|
const blocksByFile = groupBlocksByFile(blocks);
|
|
1417
|
+
if (blocksByFile.size === 0) {
|
|
1418
|
+
lines.push("No matches.");
|
|
1419
|
+
lines.push("");
|
|
1420
|
+
}
|
|
1250
1421
|
for (const [filePath, fileBlocks] of blocksByFile) {
|
|
1251
1422
|
lines.push(colorize(filePath, "bold", options.useColors));
|
|
1252
1423
|
const gutterWidth = widestLineNumberInBlocks(fileBlocks);
|
|
@@ -1418,6 +1589,9 @@ function formatTerminalNotes(envelope, useColors) {
|
|
|
1418
1589
|
if (envelope.hasMore && envelope.nextCursor) {
|
|
1419
1590
|
lines.push(dim(`More grep results available — rerun with --cursor ${shellQuote(envelope.nextCursor)}`, useColors));
|
|
1420
1591
|
}
|
|
1592
|
+
for (const note of buildTargetResolutionNotes(envelope.targetResolution)) {
|
|
1593
|
+
lines.push(dim(note, useColors));
|
|
1594
|
+
}
|
|
1421
1595
|
if (lines.length === 0)
|
|
1422
1596
|
return;
|
|
1423
1597
|
return `${lines.join(`
|
|
@@ -1548,6 +1722,9 @@ function buildTrailer(envelope) {
|
|
|
1548
1722
|
if (skipNotes.length > 0) {
|
|
1549
1723
|
lines.push(`Note: ${skipNotes.join(", ")}.`);
|
|
1550
1724
|
}
|
|
1725
|
+
for (const note of buildTargetResolutionNotes(envelope.targetResolution)) {
|
|
1726
|
+
lines.push(note);
|
|
1727
|
+
}
|
|
1551
1728
|
return lines;
|
|
1552
1729
|
}
|
|
1553
1730
|
function buildRenderBlocks2(matches) {
|
|
@@ -1668,6 +1845,7 @@ function renderListFilesText(envelope) {
|
|
|
1668
1845
|
lines.push("");
|
|
1669
1846
|
if (envelope.files.length === 0) {
|
|
1670
1847
|
lines.push(envelope.hint ?? "No files match the requested filter.");
|
|
1848
|
+
appendTargetResolutionNotes(lines, envelope);
|
|
1671
1849
|
return lines.join(`
|
|
1672
1850
|
`);
|
|
1673
1851
|
}
|
|
@@ -1682,9 +1860,18 @@ function renderListFilesText(envelope) {
|
|
|
1682
1860
|
lines.push("");
|
|
1683
1861
|
lines.push(envelope.hint);
|
|
1684
1862
|
}
|
|
1863
|
+
appendTargetResolutionNotes(lines, envelope);
|
|
1685
1864
|
return lines.join(`
|
|
1686
1865
|
`);
|
|
1687
1866
|
}
|
|
1867
|
+
function appendTargetResolutionNotes(lines, envelope) {
|
|
1868
|
+
const notes = buildTargetResolutionNotes(envelope.targetResolution);
|
|
1869
|
+
if (notes.length === 0)
|
|
1870
|
+
return;
|
|
1871
|
+
lines.push("");
|
|
1872
|
+
for (const note of notes)
|
|
1873
|
+
lines.push(note);
|
|
1874
|
+
}
|
|
1688
1875
|
function buildHeader2(envelope) {
|
|
1689
1876
|
const identity = buildIdentity(envelope);
|
|
1690
1877
|
const countValue = envelope.hasMore ? `${envelope.files.length}+` : String(envelope.total);
|
|
@@ -2203,7 +2390,7 @@ function buildDirectVersionLookup(graph) {
|
|
|
2203
2390
|
if (!fromRoot)
|
|
2204
2391
|
continue;
|
|
2205
2392
|
const node = graph.nodes[edge.toIndex];
|
|
2206
|
-
if (!node
|
|
2393
|
+
if (!node?.version)
|
|
2207
2394
|
continue;
|
|
2208
2395
|
if (!out.has(node.name)) {
|
|
2209
2396
|
out.set(node.name, node.version);
|
|
@@ -5176,6 +5363,9 @@ function buildReadFileSuccessPayload(result, options) {
|
|
|
5176
5363
|
} else if (result.content != null) {
|
|
5177
5364
|
envelope.content = result.content;
|
|
5178
5365
|
}
|
|
5366
|
+
const targetResolution = projectTargetResolution(result.targetResolution);
|
|
5367
|
+
if (targetResolution)
|
|
5368
|
+
envelope.targetResolution = targetResolution;
|
|
5179
5369
|
return envelope;
|
|
5180
5370
|
}
|
|
5181
5371
|
function formatReadFileTerminal(envelope, options) {
|
|
@@ -5230,10 +5420,19 @@ function formatVerboseBody(envelope, options) {
|
|
|
5230
5420
|
lines.push("");
|
|
5231
5421
|
lines.push(dim(envelope.hint, options.useColors));
|
|
5232
5422
|
}
|
|
5423
|
+
appendTargetResolutionNotes2(lines, envelope, options);
|
|
5233
5424
|
lines.push("");
|
|
5234
5425
|
return lines.join(`
|
|
5235
5426
|
`);
|
|
5236
5427
|
}
|
|
5428
|
+
function appendTargetResolutionNotes2(lines, envelope, options) {
|
|
5429
|
+
const notes = buildTargetResolutionNotes(envelope.targetResolution);
|
|
5430
|
+
if (notes.length === 0)
|
|
5431
|
+
return;
|
|
5432
|
+
lines.push("");
|
|
5433
|
+
for (const note of notes)
|
|
5434
|
+
lines.push(dim(note, options.useColors));
|
|
5435
|
+
}
|
|
5237
5436
|
function splitReadFileContentLines(envelope) {
|
|
5238
5437
|
if (!envelope.content)
|
|
5239
5438
|
return [];
|
|
@@ -5295,6 +5494,12 @@ function renderReadFileText(envelope) {
|
|
|
5295
5494
|
lines.push("");
|
|
5296
5495
|
lines.push(`hint: ${envelope.hint}`);
|
|
5297
5496
|
}
|
|
5497
|
+
const resolutionNotes = buildTargetResolutionNotes(envelope.targetResolution);
|
|
5498
|
+
if (resolutionNotes.length > 0) {
|
|
5499
|
+
lines.push("");
|
|
5500
|
+
for (const note of resolutionNotes)
|
|
5501
|
+
lines.push(note);
|
|
5502
|
+
}
|
|
5298
5503
|
return lines.join(`
|
|
5299
5504
|
`);
|
|
5300
5505
|
}
|
|
@@ -6316,6 +6521,15 @@ function compactProgressTarget(target) {
|
|
|
6316
6521
|
payload.indexingRef = target.indexingRef;
|
|
6317
6522
|
if (target.requestedRefKind)
|
|
6318
6523
|
payload.requestedRefKind = target.requestedRefKind;
|
|
6524
|
+
const targetResolution = projectTargetResolution(target.targetResolution);
|
|
6525
|
+
if (targetResolution)
|
|
6526
|
+
payload.targetResolution = targetResolution;
|
|
6527
|
+
if (target.availableVersions?.length) {
|
|
6528
|
+
payload.availableVersions = target.availableVersions;
|
|
6529
|
+
}
|
|
6530
|
+
if (target.availableRefs?.length) {
|
|
6531
|
+
payload.availableRefs = target.availableRefs;
|
|
6532
|
+
}
|
|
6319
6533
|
return Object.keys(payload).length > 0 ? payload : undefined;
|
|
6320
6534
|
}
|
|
6321
6535
|
function buildFilterEcho3(filters) {
|
|
@@ -6358,7 +6572,11 @@ function buildProgressFreshnessWarnings(progress) {
|
|
|
6358
6572
|
requestedTarget: target.requested,
|
|
6359
6573
|
freshTarget: target.resolvedRequested,
|
|
6360
6574
|
servedTarget: target.served
|
|
6361
|
-
})).filter((entry) => Boolean(entry));
|
|
6575
|
+
})).concat((progress?.targets ?? []).map((target) => progressTargetResolutionWarning(target)).filter((entry) => Boolean(entry))).filter((entry) => Boolean(entry));
|
|
6576
|
+
}
|
|
6577
|
+
function progressTargetResolutionWarning(target) {
|
|
6578
|
+
const notes = buildTargetResolutionNotes(target.targetResolution ?? buildResolutionFromRetryCandidates(target));
|
|
6579
|
+
return notes.length > 0 ? notes.join(" ") : undefined;
|
|
6362
6580
|
}
|
|
6363
6581
|
function freshnessWarning(input) {
|
|
6364
6582
|
if (!isTrustRelevantFreshness(input.freshness))
|
|
@@ -6377,7 +6595,7 @@ function labelsDiverge(input) {
|
|
|
6377
6595
|
const served = input.servedTarget;
|
|
6378
6596
|
if (!served)
|
|
6379
6597
|
return false;
|
|
6380
|
-
return Boolean(input.freshTarget && input.freshTarget !== served
|
|
6598
|
+
return Boolean(input.freshTarget && input.freshTarget !== served);
|
|
6381
6599
|
}
|
|
6382
6600
|
function warningForEntry(entry) {
|
|
6383
6601
|
const reasons = [];
|
|
@@ -6389,6 +6607,14 @@ function warningForEntry(entry) {
|
|
|
6389
6607
|
});
|
|
6390
6608
|
if (freshness)
|
|
6391
6609
|
return freshness;
|
|
6610
|
+
const terminalLifecycleReason = terminalLifecycleWarningReason(entry);
|
|
6611
|
+
if (terminalLifecycleReason) {
|
|
6612
|
+
reasons.push(terminalLifecycleReason);
|
|
6613
|
+
} else {
|
|
6614
|
+
const targetResolutionWarning = targetResolutionWarningForEntry(entry);
|
|
6615
|
+
if (targetResolutionWarning)
|
|
6616
|
+
reasons.push(targetResolutionWarning);
|
|
6617
|
+
}
|
|
6392
6618
|
if (entry.incompatibleQueryFeatures?.length) {
|
|
6393
6619
|
reasons.push(`incompatible query features [${entry.incompatibleQueryFeatures.join(", ")}]`);
|
|
6394
6620
|
}
|
|
@@ -6401,10 +6627,10 @@ function warningForEntry(entry) {
|
|
|
6401
6627
|
if (entry.ignoredFilters?.length) {
|
|
6402
6628
|
reasons.push(`ignored filters [${entry.ignoredFilters.join(", ")}]`);
|
|
6403
6629
|
}
|
|
6404
|
-
if (entry.indexingStatus) {
|
|
6630
|
+
if (!terminalLifecycleReason && reasons.length === 0 && entry.indexingStatus) {
|
|
6405
6631
|
reasons.push(`indexing status ${entry.indexingStatus}`);
|
|
6406
6632
|
}
|
|
6407
|
-
if (entry.codeIndexState) {
|
|
6633
|
+
if (!terminalLifecycleReason && reasons.length === 0 && entry.codeIndexState) {
|
|
6408
6634
|
if (entry.codeIndexState !== "STALE") {
|
|
6409
6635
|
reasons.push(`code index state ${entry.codeIndexState}`);
|
|
6410
6636
|
}
|
|
@@ -6418,6 +6644,18 @@ function warningForEntry(entry) {
|
|
|
6418
6644
|
}
|
|
6419
6645
|
return;
|
|
6420
6646
|
}
|
|
6647
|
+
function terminalLifecycleWarningReason(entry) {
|
|
6648
|
+
const states = Array.from(new Set([entry.indexingStatus, entry.codeIndexState].filter(Boolean)));
|
|
6649
|
+
const terminalStates = states.filter((state) => state !== "INDEXING" && state !== "STALE");
|
|
6650
|
+
if (terminalStates.length === 0)
|
|
6651
|
+
return;
|
|
6652
|
+
const status = terminalStates.join("/");
|
|
6653
|
+
return entry.note ? `${entry.note} (${status})` : `status ${status}`;
|
|
6654
|
+
}
|
|
6655
|
+
function targetResolutionWarningForEntry(entry) {
|
|
6656
|
+
const notes = buildTargetResolutionNotes(entry.targetResolution);
|
|
6657
|
+
return notes.length > 0 ? notes.join(" ") : undefined;
|
|
6658
|
+
}
|
|
6421
6659
|
function compactSourceStatus(sourceStatus) {
|
|
6422
6660
|
if (!sourceStatus || sourceStatus.length === 0)
|
|
6423
6661
|
return;
|
|
@@ -6447,6 +6685,13 @@ function compactSourceStatusEntry(entry) {
|
|
|
6447
6685
|
payload.codeIndexState = entry.codeIndexState;
|
|
6448
6686
|
interesting = true;
|
|
6449
6687
|
}
|
|
6688
|
+
const targetResolution = projectTargetResolution(entry.targetResolution);
|
|
6689
|
+
if (targetResolution) {
|
|
6690
|
+
payload.targetResolution = targetResolution;
|
|
6691
|
+
if (buildTargetResolutionNotes(targetResolution).length > 0) {
|
|
6692
|
+
interesting = true;
|
|
6693
|
+
}
|
|
6694
|
+
}
|
|
6450
6695
|
if (entry.indexingStatus && entry.indexingStatus !== "INDEXED") {
|
|
6451
6696
|
payload.indexingStatus = entry.indexingStatus;
|
|
6452
6697
|
interesting = true;
|
|
@@ -6484,7 +6729,7 @@ function assertSearchFollowUpInvariant(hit) {
|
|
|
6484
6729
|
if ((hit.resultType === "DOCUMENTATION_PAGE" || hit.resultType === "REPOSITORY_DOC") && !hit.locator.pageId) {
|
|
6485
6730
|
throw new MalformedCodeNavigationResponseError(`${hit.resultType} search hit missing required pageId.`);
|
|
6486
6731
|
}
|
|
6487
|
-
if (hit.resultType === "REPOSITORY_DOC" && (!hit.locator.repoUrl || !hit.locator.
|
|
6732
|
+
if (hit.resultType === "REPOSITORY_DOC" && (!hit.locator.repoUrl || !hit.locator.filePath)) {
|
|
6488
6733
|
throw new MalformedCodeNavigationResponseError("REPOSITORY_DOC search hit missing repo locator fields.");
|
|
6489
6734
|
}
|
|
6490
6735
|
}
|
|
@@ -6496,7 +6741,7 @@ function renderUnifiedSearchSuccess(payload) {
|
|
|
6496
6741
|
lines.push(buildHeader8(payload));
|
|
6497
6742
|
lines.push("");
|
|
6498
6743
|
if (payload.results.length === 0) {
|
|
6499
|
-
lines.push(payload.completed ? "No hits." :
|
|
6744
|
+
lines.push(payload.completed ? "No hits." : noHitsYetMessage(payload));
|
|
6500
6745
|
} else {
|
|
6501
6746
|
appendUnifiedSearchHits(lines, payload.results);
|
|
6502
6747
|
}
|
|
@@ -6509,6 +6754,18 @@ function renderUnifiedSearchSuccess(payload) {
|
|
|
6509
6754
|
return lines.join(`
|
|
6510
6755
|
`);
|
|
6511
6756
|
}
|
|
6757
|
+
function noHitsYetMessage(payload) {
|
|
6758
|
+
if (payload.completed)
|
|
6759
|
+
return "No hits.";
|
|
6760
|
+
const status = payload.progress?.status;
|
|
6761
|
+
if (status === "TIMEOUT")
|
|
6762
|
+
return "No hits yet - timed out waiting.";
|
|
6763
|
+
if (status === "FAILED")
|
|
6764
|
+
return "No hits - search failed.";
|
|
6765
|
+
if (status === "SEARCHING")
|
|
6766
|
+
return "No hits yet - searching.";
|
|
6767
|
+
return "No hits yet - indexing.";
|
|
6768
|
+
}
|
|
6512
6769
|
function renderUnifiedSearchError(payload) {
|
|
6513
6770
|
const lines = [];
|
|
6514
6771
|
const header = `search${SEP6}ERROR${SEP6}code=${payload.code}${payload.retryable ? `${SEP6}retryable` : ""}`;
|
|
@@ -6638,7 +6895,9 @@ function buildTrailer2(payload) {
|
|
|
6638
6895
|
lines.push(`More hits available.${nextOffsetHint}`);
|
|
6639
6896
|
}
|
|
6640
6897
|
if (!payload.completed && payload.searchRef) {
|
|
6641
|
-
|
|
6898
|
+
const status = payload.progress?.status;
|
|
6899
|
+
const action = status === "TIMEOUT" ? "Search timed out waiting for fresh data." : status === "FAILED" ? "Search failed before completion." : status === "SEARCHING" ? "Search in progress." : "Indexing in progress.";
|
|
6900
|
+
lines.push(`${action} Call search_status with searchRef=${payload.searchRef} to follow up.`);
|
|
6642
6901
|
}
|
|
6643
6902
|
if (payload.sourceStatus && payload.sourceStatus.length > 0) {
|
|
6644
6903
|
lines.push("source notes:");
|
|
@@ -6669,6 +6928,9 @@ function formatProgressTarget(target) {
|
|
|
6669
6928
|
parts.push(`intent=${target.requestedRefKind}`);
|
|
6670
6929
|
if (target.indexingRef)
|
|
6671
6930
|
parts.push(`indexingRef=${target.indexingRef}`);
|
|
6931
|
+
for (const note of buildTargetResolutionNotes(target.targetResolution ?? buildResolutionFromRetryCandidates(target))) {
|
|
6932
|
+
parts.push(note);
|
|
6933
|
+
}
|
|
6672
6934
|
return parts.length > 0 ? parts.join(SEP6) : "target progress unavailable";
|
|
6673
6935
|
}
|
|
6674
6936
|
function describeFreshness(value) {
|
|
@@ -6686,6 +6948,10 @@ function describeFreshness(value) {
|
|
|
6686
6948
|
}
|
|
6687
6949
|
}
|
|
6688
6950
|
function formatSourceStatus(entry) {
|
|
6951
|
+
const terminalReason = terminalLifecycleReason(entry);
|
|
6952
|
+
if (terminalReason) {
|
|
6953
|
+
return `${entry.source} (${entry.targetLabel})${SEP6}${terminalReason}`;
|
|
6954
|
+
}
|
|
6689
6955
|
const parts = [`${entry.source} (${entry.targetLabel})`];
|
|
6690
6956
|
if (entry.indexingStatus)
|
|
6691
6957
|
parts.push(`indexing=${entry.indexingStatus}`);
|
|
@@ -6705,8 +6971,19 @@ function formatSourceStatus(entry) {
|
|
|
6705
6971
|
}
|
|
6706
6972
|
if (entry.note)
|
|
6707
6973
|
parts.push(entry.note);
|
|
6974
|
+
for (const note of buildTargetResolutionNotes(entry.targetResolution)) {
|
|
6975
|
+
parts.push(note);
|
|
6976
|
+
}
|
|
6708
6977
|
return parts.join(SEP6);
|
|
6709
6978
|
}
|
|
6979
|
+
function terminalLifecycleReason(entry) {
|
|
6980
|
+
const states = Array.from(new Set([entry.indexingStatus, entry.codeIndexState].filter(Boolean)));
|
|
6981
|
+
const terminalStates = states.filter((state) => state !== "INDEXING" && state !== "STALE");
|
|
6982
|
+
if (terminalStates.length === 0)
|
|
6983
|
+
return;
|
|
6984
|
+
const status = terminalStates.join("/");
|
|
6985
|
+
return entry.note ? `${entry.note} (${status})` : `status ${status}`;
|
|
6986
|
+
}
|
|
6710
6987
|
function quote4(value) {
|
|
6711
6988
|
return value.includes('"') ? `'${value}'` : `"${value}"`;
|
|
6712
6989
|
}
|
|
@@ -6769,7 +7046,7 @@ function renderUnifiedSearchStatusText(payload) {
|
|
|
6769
7046
|
`);
|
|
6770
7047
|
}
|
|
6771
7048
|
function buildHeader9(payload) {
|
|
6772
|
-
const state = payload.completed ? "complete" : "
|
|
7049
|
+
const state = payload.completed ? "complete" : payload.progress?.status.toLowerCase() ?? "incomplete";
|
|
6773
7050
|
const parts = [`search_status${SEP7}${state}`];
|
|
6774
7051
|
if (payload.searchRef)
|
|
6775
7052
|
parts.push(`searchRef=${payload.searchRef}`);
|
|
@@ -6797,32 +7074,10 @@ function appendResult(lines, result) {
|
|
|
6797
7074
|
lines.push("");
|
|
6798
7075
|
lines.push("source notes:");
|
|
6799
7076
|
for (const entry of result.sourceStatus) {
|
|
6800
|
-
lines.push(` - ${
|
|
7077
|
+
lines.push(` - ${formatSourceStatus(entry)}`);
|
|
6801
7078
|
}
|
|
6802
7079
|
}
|
|
6803
7080
|
}
|
|
6804
|
-
function formatSourceStatus2(entry) {
|
|
6805
|
-
const parts = [`${entry.source} (${entry.targetLabel})`];
|
|
6806
|
-
if (entry.indexingStatus)
|
|
6807
|
-
parts.push(`indexing=${entry.indexingStatus}`);
|
|
6808
|
-
if (entry.codeIndexState)
|
|
6809
|
-
parts.push(`codeIndex=${entry.codeIndexState}`);
|
|
6810
|
-
if (entry.ignoredFilters?.length) {
|
|
6811
|
-
parts.push(`ignored=${entry.ignoredFilters.join(",")}`);
|
|
6812
|
-
}
|
|
6813
|
-
if (entry.incompatibleFilters?.length) {
|
|
6814
|
-
parts.push(`incompatible=${entry.incompatibleFilters.join(",")}`);
|
|
6815
|
-
}
|
|
6816
|
-
if (entry.ignoredQueryFeatures?.length) {
|
|
6817
|
-
parts.push(`ignoredQuery=${entry.ignoredQueryFeatures.join(",")}`);
|
|
6818
|
-
}
|
|
6819
|
-
if (entry.incompatibleQueryFeatures?.length) {
|
|
6820
|
-
parts.push(`incompatibleQuery=${entry.incompatibleQueryFeatures.join(",")}`);
|
|
6821
|
-
}
|
|
6822
|
-
if (entry.note)
|
|
6823
|
-
parts.push(entry.note);
|
|
6824
|
-
return parts.join(SEP7);
|
|
6825
|
-
}
|
|
6826
7081
|
function formatProgress(progress) {
|
|
6827
7082
|
const next = progress.next ? `; next: ${progress.next}` : "";
|
|
6828
7083
|
return `progress: ${progress.status}, ${progress.targetsReady}/${progress.targetsTotal} targets ready, ${progress.elapsedMs}ms elapsed${next}`;
|
|
@@ -7042,6 +7297,9 @@ function buildListFilesSuccessPayload(result, options) {
|
|
|
7042
7297
|
envelope.indexedVersion = result.indexedVersion;
|
|
7043
7298
|
if (result.resolution)
|
|
7044
7299
|
envelope.resolution = projectResolution2(result.resolution);
|
|
7300
|
+
const targetResolution = projectTargetResolution(result.targetResolution);
|
|
7301
|
+
if (targetResolution)
|
|
7302
|
+
envelope.targetResolution = targetResolution;
|
|
7045
7303
|
if (result.hint)
|
|
7046
7304
|
envelope.hint = result.hint;
|
|
7047
7305
|
const filter = buildFilterBlock2(options);
|
|
@@ -7152,6 +7410,7 @@ function formatVerbose2(envelope, options) {
|
|
|
7152
7410
|
if (envelope.resolution || envelope.indexedVersion) {
|
|
7153
7411
|
lines.push(buildResolutionLine(envelope, options));
|
|
7154
7412
|
}
|
|
7413
|
+
appendTargetResolutionNotes3(lines, envelope, options);
|
|
7155
7414
|
lines.push("");
|
|
7156
7415
|
const pathWidth = longestPathLength(envelope.files);
|
|
7157
7416
|
for (const file of envelope.files) {
|
|
@@ -7180,6 +7439,7 @@ function formatEmpty(envelope, options, verbose) {
|
|
|
7180
7439
|
if (envelope.resolution || envelope.indexedVersion) {
|
|
7181
7440
|
lines.push(buildResolutionLine(envelope, options));
|
|
7182
7441
|
}
|
|
7442
|
+
appendTargetResolutionNotes3(lines, envelope, options);
|
|
7183
7443
|
lines.push("");
|
|
7184
7444
|
lines.push(dim(hint, options.useColors));
|
|
7185
7445
|
lines.push("");
|
|
@@ -7202,6 +7462,11 @@ function buildResolutionLine(envelope, options) {
|
|
|
7202
7462
|
parts.push(`commit ${commit.slice(0, 7)}`);
|
|
7203
7463
|
return dim(parts.join(" · "), options.useColors);
|
|
7204
7464
|
}
|
|
7465
|
+
function appendTargetResolutionNotes3(lines, envelope, options) {
|
|
7466
|
+
const notes = buildTargetResolutionNotes(envelope.targetResolution);
|
|
7467
|
+
for (const note of notes)
|
|
7468
|
+
lines.push(dim(note, options.useColors));
|
|
7469
|
+
}
|
|
7205
7470
|
function buildIdentityLabel(envelope) {
|
|
7206
7471
|
if (envelope.registry && envelope.name) {
|
|
7207
7472
|
return `${envelope.name} · ${envelope.registry}`;
|
|
@@ -7251,13 +7516,10 @@ function resolveCliCodeNavTarget(spec, options) {
|
|
|
7251
7516
|
const hasRepoUrl = Boolean(options.repoUrl);
|
|
7252
7517
|
const hasGitRef = Boolean(options.gitRef);
|
|
7253
7518
|
if (hasSpec && (hasRepoUrl || hasGitRef)) {
|
|
7254
|
-
throw new InvalidPackageSpecError("Provide either a package spec (e.g. `npm:express`) or `--repo-url`
|
|
7519
|
+
throw new InvalidPackageSpecError("Provide either a package spec (e.g. `npm:express`) or `--repo-url` with optional `--git-ref`, not both.");
|
|
7255
7520
|
}
|
|
7256
7521
|
if (!hasSpec && !hasRepoUrl) {
|
|
7257
|
-
throw new InvalidPackageSpecError("A package spec (e.g. `npm:express`) or `--repo-url`
|
|
7258
|
-
}
|
|
7259
|
-
if (hasRepoUrl && !hasGitRef) {
|
|
7260
|
-
throw new InvalidPackageSpecError("`--repo-url` requires `--git-ref` for code files/read/grep (a tag, branch, commit, or `HEAD`).");
|
|
7522
|
+
throw new InvalidPackageSpecError("A package spec (e.g. `npm:express`) or `--repo-url` is required.");
|
|
7261
7523
|
}
|
|
7262
7524
|
if (hasSpec) {
|
|
7263
7525
|
const parsed = parsePackageSpec(spec);
|
|
@@ -7301,6 +7563,13 @@ function formatIndexingError(mapped) {
|
|
|
7301
7563
|
const suffix = more > 0 ? ` (+${more} more)` : "";
|
|
7302
7564
|
lines.push(` already-indexed versions: ${shown}${suffix}`);
|
|
7303
7565
|
}
|
|
7566
|
+
const refs = detail.availableRefs;
|
|
7567
|
+
if (refs && refs.length > 0) {
|
|
7568
|
+
const shown = refs.slice(0, 5).map((entry) => entry.ref).join(", ");
|
|
7569
|
+
const more = refs.length - 5;
|
|
7570
|
+
const suffix = more > 0 ? ` (+${more} more)` : "";
|
|
7571
|
+
lines.push(` already-indexed refs: ${shown}${suffix}`);
|
|
7572
|
+
}
|
|
7304
7573
|
return lines.join(`
|
|
7305
7574
|
`);
|
|
7306
7575
|
}
|
|
@@ -7439,7 +7708,7 @@ function resolvePositionals(firstArg, secondArg, hasRepoUrl) {
|
|
|
7439
7708
|
throw new InvalidPackageSpecError("In --repo-url mode, pass only [path-prefix] — the package spec is replaced by --repo-url.");
|
|
7440
7709
|
}
|
|
7441
7710
|
if (firstArg && REGISTRY_SPEC_HINT.test(firstArg)) {
|
|
7442
|
-
throw new InvalidPackageSpecError(`'${firstArg}' looks like a package spec. Provide either a package spec or \`--repo-url\`
|
|
7711
|
+
throw new InvalidPackageSpecError(`'${firstArg}' looks like a package spec. Provide either a package spec or \`--repo-url\` with optional \`--git-ref\`, not both.`);
|
|
7443
7712
|
}
|
|
7444
7713
|
return { spec: undefined, pathPrefix: firstArg };
|
|
7445
7714
|
}
|
|
@@ -7467,7 +7736,7 @@ On an INDEXING response, the dependency is being indexed on-demand
|
|
|
7467
7736
|
— retry with a longer --wait (up to 60000 ms) or pick one of the
|
|
7468
7737
|
already-indexed versions surfaced in the error detail.`;
|
|
7469
7738
|
function registerCodeFilesCommand(pkgCommand) {
|
|
7470
|
-
return pkgCommand.command("files").summary("List files in an indexed dependency").description(PKG_FILES_DESCRIPTION).argument("[spec-or-prefix]", "Spec mode: package spec (e.g. npm:express). Repo mode (with --repo-url): the path-prefix.").argument("[path-prefix]", "Spec mode only: literal directory prefix (not a glob). Ignored with --repo-url.").option("--repo-url <url>", "Repository URL addressing (
|
|
7739
|
+
return pkgCommand.command("files").summary("List files in an indexed dependency").description(PKG_FILES_DESCRIPTION).argument("[spec-or-prefix]", "Spec mode: package spec (e.g. npm:express). Repo mode (with --repo-url): the path-prefix.").argument("[path-prefix]", "Spec mode only: literal directory prefix (not a glob). Ignored with --repo-url.").option("--repo-url <url>", "Repository URL addressing (defaults to the repo default branch)").option("--git-ref <ref>", "Optional tag, commit, branch, or HEAD for --repo-url.").option("--path <path>", "Exact file selector").option("--glob <glob>", "Glob selector (repeatable)", collectRepeatable).option("--ext <ext>", "Extension filter without leading dot (repeatable)", collectRepeatable).option("--file-type <type>", "File type filter such as source or doc (repeatable)", collectRepeatable).option("--language <language>", "Language filter matching aigrep language names (repeatable)", collectRepeatable).option("--file-intent <intent>", "Inclusive file-intent filter. Repeat to include multiple intents: production, test, benchmark, example, generated, fixture, build, vendor", collectRepeatable).option("--exclude-intent <intent>", "Exclude these file intents after inclusive filtering (repeatable)", collectRepeatable).option("--exclude-docs", "Skip files classified as documentation").option("--exclude-tests", "Skip files classified as tests").option("--hidden", "Include dotfiles and dot-prefixed paths").option("--limit <n>", "Max entries (1-1000, default 200)").option("--wait <ms>", `Indexing wait timeout (0-${MAX_WAIT_TIMEOUT_MS}, default ${DEFAULT_WAIT_TIMEOUT_MS})`).option("-v, --verbose", "Annotate each path with language / file-type / byte size").option("--json", "Emit the JSON envelope").action(async (arg1, arg2, options) => {
|
|
7471
7740
|
const deps = await createContainer();
|
|
7472
7741
|
await pkgFilesAction(arg1, arg2, options, {
|
|
7473
7742
|
codeNavigationService: deps.codeNavigationService,
|
|
@@ -7544,7 +7813,7 @@ async function pkgGrepAction(first, second, third, options, deps) {
|
|
|
7544
7813
|
if (options.json) {
|
|
7545
7814
|
console.log(JSON.stringify(payload));
|
|
7546
7815
|
if (payload.totalMatches === 0)
|
|
7547
|
-
process.
|
|
7816
|
+
process.exitCode = 1;
|
|
7548
7817
|
return;
|
|
7549
7818
|
}
|
|
7550
7819
|
const rendered = formatGrepRepoTerminal(payload, {
|
|
@@ -7557,7 +7826,7 @@ async function pkgGrepAction(first, second, third, options, deps) {
|
|
|
7557
7826
|
if (rendered.stderr)
|
|
7558
7827
|
process.stderr.write(rendered.stderr);
|
|
7559
7828
|
if (payload.totalMatches === 0)
|
|
7560
|
-
process.
|
|
7829
|
+
process.exitCode = 1;
|
|
7561
7830
|
} catch (error2) {
|
|
7562
7831
|
handleCodeNavCommandError(error2, options.json ?? false, formatFileErrorWithFilesHint, 2);
|
|
7563
7832
|
}
|
|
@@ -7570,7 +7839,7 @@ function resolvePositionals2(first, second, third, hasRepoUrl) {
|
|
|
7570
7839
|
return { spec: undefined, pattern: first, pathPrefix: second };
|
|
7571
7840
|
}
|
|
7572
7841
|
if (first !== undefined && second === undefined) {
|
|
7573
|
-
throw new InvalidPackageSpecError("In spec mode, pass at least <spec> <pattern>. If you meant to target a repository instead, pass --repo-url <url> --git-ref <ref>.");
|
|
7842
|
+
throw new InvalidPackageSpecError("In spec mode, pass at least <spec> <pattern>. If you meant to target a repository instead, pass --repo-url <url> with optional --git-ref <ref>.");
|
|
7574
7843
|
}
|
|
7575
7844
|
return { spec: first, pattern: second, pathPrefix: third };
|
|
7576
7845
|
}
|
|
@@ -7595,7 +7864,7 @@ var PKG_GREP_DESCRIPTION = `Deterministic text grep over indexed dependency and
|
|
|
7595
7864
|
${CLI_GREP_PATTERN_NOTE}
|
|
7596
7865
|
Use \`githits search\` for discovery; use \`githits code grep\` when you know the text or regex to match.
|
|
7597
7866
|
|
|
7598
|
-
Addressing: <spec> (registry:name[@version]) OR --repo-url <url> --git-ref <ref
|
|
7867
|
+
Addressing: <spec> (registry:name[@version]) OR --repo-url <url> [--git-ref <ref>].
|
|
7599
7868
|
Omitted version means latest release.
|
|
7600
7869
|
In spec mode pass <spec> <pattern> [path-prefix]; in repo-URL mode pass only <pattern> [path-prefix].
|
|
7601
7870
|
|
|
@@ -7610,8 +7879,8 @@ for context, --verbose for grouped output, and --cursor to continue a paginated
|
|
|
7610
7879
|
grep run. --symbol-field hydrates enclosing symbol metadata (appears under each
|
|
7611
7880
|
match in --verbose output; full payload in --json).`;
|
|
7612
7881
|
function registerCodeGrepCommand(pkgCommand) {
|
|
7613
|
-
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 (
|
|
7614
|
-
const { createContainer: createContainer2 } = await import("./shared/chunk-
|
|
7882
|
+
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 (defaults to the repo default branch)").option("--git-ref <ref>", "Optional tag, commit, branch, or HEAD for --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) => {
|
|
7883
|
+
const { createContainer: createContainer2 } = await import("./shared/chunk-2fdxv7pe.js");
|
|
7615
7884
|
const deps = await createContainer2();
|
|
7616
7885
|
await pkgGrepAction(arg1, arg2, arg3, options, {
|
|
7617
7886
|
codeNavigationService: deps.codeNavigationService,
|
|
@@ -7845,7 +8114,7 @@ Binary files show a one-line sentinel instead of content. When a
|
|
|
7845
8114
|
path is missing, the response is a FILE_NOT_FOUND error — use
|
|
7846
8115
|
\`code files\` to discover available paths.`;
|
|
7847
8116
|
function registerCodeReadCommand(pkgCommand) {
|
|
7848
|
-
return pkgCommand.command("read").summary("Read a file from an indexed dependency").description(PKG_READ_DESCRIPTION).argument("[spec-or-path]", "In spec mode: package spec (e.g. npm:express). In --repo-url mode: the file path. See examples in `--help`.").argument("[path]", "File path (spec mode only — in --repo-url mode use the first positional).").option("--repo-url <url>", "Repository URL addressing (
|
|
8117
|
+
return pkgCommand.command("read").summary("Read a file from an indexed dependency").description(PKG_READ_DESCRIPTION).argument("[spec-or-path]", "In spec mode: package spec (e.g. npm:express). In --repo-url mode: the file path. See examples in `--help`.").argument("[path]", "File path (spec mode only — in --repo-url mode use the first positional).").option("--repo-url <url>", "Repository URL addressing (defaults to the repo default branch)").option("--git-ref <ref>", "Optional tag, commit, branch, or HEAD for --repo-url.").option("--lines <start-end>", "Line range (e.g. `10-40`, `10-` for open end, `-40` for open start)").option("--start <n>", "Starting line (1-indexed). Alternative to --lines.").option("--end <n>", "Ending line (inclusive). Alternative to --lines.").option("--wait <ms>", `Indexing wait timeout (0-${MAX_WAIT_TIMEOUT_MS}, default ${DEFAULT_WAIT_TIMEOUT_MS})`).option("-v, --verbose", "Render a header and a line-number gutter alongside the content").option("--json", "Emit the JSON envelope").action(async (spec, path, options) => {
|
|
7849
8118
|
const deps = await createContainer();
|
|
7850
8119
|
await pkgReadAction(spec, path, options, {
|
|
7851
8120
|
codeNavigationService: deps.codeNavigationService,
|
|
@@ -7862,7 +8131,7 @@ async function registerCodeCommandGroup(program, options = {}) {
|
|
|
7862
8131
|
if (!registration.shouldRegister) {
|
|
7863
8132
|
return;
|
|
7864
8133
|
}
|
|
7865
|
-
const codeCommand = program.command("code").summary("Source-level operations on indexed dependencies").description("List files, read files, and grep substrings inside indexed dependency source. Every command accepts either `<spec>` (registry:name[@version]) or `--repo-url <url> --git-ref <ref
|
|
8134
|
+
const codeCommand = program.command("code").summary("Source-level operations on indexed dependencies").description("List files, read files, and grep substrings inside indexed dependency source. Every command accepts either `<spec>` (registry:name[@version]) or `--repo-url <url> [--git-ref <ref>]`. Omitted package versions use the latest release; omitted repo refs use the default-branch intent. For package-level metadata use `githits pkg`.");
|
|
7866
8135
|
registerCodeFilesCommand(codeCommand);
|
|
7867
8136
|
registerCodeReadCommand(codeCommand);
|
|
7868
8137
|
registerCodeGrepCommand(codeCommand);
|
|
@@ -8071,7 +8340,7 @@ function registerExampleCommand(program) {
|
|
|
8071
8340
|
});
|
|
8072
8341
|
}
|
|
8073
8342
|
async function loadContainer() {
|
|
8074
|
-
const { createContainer: createContainer2 } = await import("./shared/chunk-
|
|
8343
|
+
const { createContainer: createContainer2 } = await import("./shared/chunk-2fdxv7pe.js");
|
|
8075
8344
|
return createContainer2();
|
|
8076
8345
|
}
|
|
8077
8346
|
// src/commands/feedback.ts
|
|
@@ -8363,6 +8632,10 @@ function removeServerConfig(existingContent, serversKey, serverName) {
|
|
|
8363
8632
|
};
|
|
8364
8633
|
}
|
|
8365
8634
|
function formatSetupPreview(config) {
|
|
8635
|
+
if (config.method === "composite") {
|
|
8636
|
+
return config.steps.map((step) => formatSetupPreview(step)).join(`
|
|
8637
|
+
`);
|
|
8638
|
+
}
|
|
8366
8639
|
if (config.method === "cli") {
|
|
8367
8640
|
return config.commands.map((cmd) => `Will run: ${cmd.command} ${cmd.args.join(" ")}`).join(`
|
|
8368
8641
|
`);
|
|
@@ -8373,6 +8646,10 @@ function formatSetupPreview(config) {
|
|
|
8373
8646
|
${snippet}`;
|
|
8374
8647
|
}
|
|
8375
8648
|
function formatUninstallPreview(config) {
|
|
8649
|
+
if (config.method === "composite") {
|
|
8650
|
+
return config.steps.map(({ step }) => formatUninstallPreview(step)).join(`
|
|
8651
|
+
`);
|
|
8652
|
+
}
|
|
8376
8653
|
if (config.method === "cli") {
|
|
8377
8654
|
return config.commands.map((cmd) => `Will run: ${cmd.command} ${cmd.args.join(" ")}`).join(`
|
|
8378
8655
|
`);
|
|
@@ -8433,6 +8710,26 @@ async function getConfigUninstallCheckStatus(config, fs) {
|
|
|
8433
8710
|
};
|
|
8434
8711
|
}
|
|
8435
8712
|
}
|
|
8713
|
+
async function isSetupAlreadyConfigured(config, fs, execService) {
|
|
8714
|
+
if (config.method === "config-file") {
|
|
8715
|
+
return isAlreadyConfigured(config, fs);
|
|
8716
|
+
}
|
|
8717
|
+
if (config.method === "cli") {
|
|
8718
|
+
if (!config.checkCommand) {
|
|
8719
|
+
return false;
|
|
8720
|
+
}
|
|
8721
|
+
return isCliAlreadyConfigured(config.checkCommand, execService);
|
|
8722
|
+
}
|
|
8723
|
+
for (const step of config.steps) {
|
|
8724
|
+
if (!await isSetupAlreadyConfigured(step, fs, execService)) {
|
|
8725
|
+
return false;
|
|
8726
|
+
}
|
|
8727
|
+
}
|
|
8728
|
+
return true;
|
|
8729
|
+
}
|
|
8730
|
+
async function isCliAlreadyConfigured(check, execService) {
|
|
8731
|
+
return await getCliCheckStatus(check, execService) === "configured";
|
|
8732
|
+
}
|
|
8436
8733
|
async function getCliCheckStatus(check, execService) {
|
|
8437
8734
|
try {
|
|
8438
8735
|
const result = await execService.exec(check.command, check.args);
|
|
@@ -8463,6 +8760,7 @@ var ALREADY_EXISTS_PATTERNS = [
|
|
|
8463
8760
|
var ALREADY_ABSENT_PATTERNS = [
|
|
8464
8761
|
/(?:plugin|extension|server|mcp server)\s+["']?githits["']?\s+(?:was\s+)?not\s+found/i,
|
|
8465
8762
|
/["']?githits["']?\s+(?:plugin|extension|server)?\s*(?:does\s+not\s+exist|is\s+not\s+installed|not\s+installed)/i,
|
|
8763
|
+
/(?:package\s+)?["']?pi-mcp-adapter["']?\s+(?:is\s+)?not\s+installed/i,
|
|
8466
8764
|
/unknown\s+(?:plugin|extension|server)\s+["']?githits["']?/i,
|
|
8467
8765
|
/marketplace\s+["']?githits-plugins["']?\s+(?:was\s+)?not\s+found/i
|
|
8468
8766
|
];
|
|
@@ -8563,8 +8861,7 @@ async function executeCliUninstall(uninstall, execService) {
|
|
|
8563
8861
|
let anyRemoved = false;
|
|
8564
8862
|
let anyNotConfigured = false;
|
|
8565
8863
|
const warnings = [];
|
|
8566
|
-
for (
|
|
8567
|
-
const cmd = uninstall.commands[index];
|
|
8864
|
+
for (const cmd of uninstall.commands) {
|
|
8568
8865
|
const result = await executeCliUninstallCommand(cmd, execService);
|
|
8569
8866
|
if (result.status === "failed") {
|
|
8570
8867
|
if (anyRemoved) {
|
|
@@ -8599,6 +8896,49 @@ async function executeCliUninstall(uninstall, execService) {
|
|
|
8599
8896
|
}
|
|
8600
8897
|
return { status: "removed", message: "Removed successfully" };
|
|
8601
8898
|
}
|
|
8899
|
+
async function executeCompositeUninstall(uninstall, fs, execService) {
|
|
8900
|
+
let anyRemoved = false;
|
|
8901
|
+
let anyNotConfigured = false;
|
|
8902
|
+
const warnings = [];
|
|
8903
|
+
for (const { step, failureMode } of uninstall.steps) {
|
|
8904
|
+
const result = await executeUninstallStep(step, fs, execService);
|
|
8905
|
+
if (result.status === "removed") {
|
|
8906
|
+
anyRemoved = true;
|
|
8907
|
+
warnings.push(...result.warnings ?? []);
|
|
8908
|
+
continue;
|
|
8909
|
+
}
|
|
8910
|
+
if (result.status === "not_configured") {
|
|
8911
|
+
if (anyRemoved) {
|
|
8912
|
+
warnings.push(result.message);
|
|
8913
|
+
} else {
|
|
8914
|
+
anyNotConfigured = true;
|
|
8915
|
+
}
|
|
8916
|
+
continue;
|
|
8917
|
+
}
|
|
8918
|
+
if (failureMode === "best-effort" && anyRemoved) {
|
|
8919
|
+
warnings.push(result.message);
|
|
8920
|
+
continue;
|
|
8921
|
+
}
|
|
8922
|
+
return result;
|
|
8923
|
+
}
|
|
8924
|
+
if (anyRemoved) {
|
|
8925
|
+
return {
|
|
8926
|
+
status: "removed",
|
|
8927
|
+
message: "Removed successfully",
|
|
8928
|
+
warnings: warnings.length > 0 ? warnings : undefined
|
|
8929
|
+
};
|
|
8930
|
+
}
|
|
8931
|
+
if (anyNotConfigured) {
|
|
8932
|
+
return {
|
|
8933
|
+
status: "not_configured",
|
|
8934
|
+
message: "GitHits not configured"
|
|
8935
|
+
};
|
|
8936
|
+
}
|
|
8937
|
+
return { status: "not_configured", message: "GitHits not configured" };
|
|
8938
|
+
}
|
|
8939
|
+
async function executeUninstallStep(step, fs, execService) {
|
|
8940
|
+
return step.method === "cli" ? executeCliUninstall(step, execService) : executeConfigFileUninstall(step, fs);
|
|
8941
|
+
}
|
|
8602
8942
|
async function executeConfigFileSetup(setup, fs) {
|
|
8603
8943
|
try {
|
|
8604
8944
|
const parentDir = fs.getDirname(setup.configPath);
|
|
@@ -8642,6 +8982,26 @@ async function executeConfigFileSetup(setup, fs) {
|
|
|
8642
8982
|
};
|
|
8643
8983
|
}
|
|
8644
8984
|
}
|
|
8985
|
+
async function executeCompositeSetup(setup, fs, execService) {
|
|
8986
|
+
let executedAny = false;
|
|
8987
|
+
for (const step of setup.steps) {
|
|
8988
|
+
if (await isSetupAlreadyConfigured(step, fs, execService)) {
|
|
8989
|
+
continue;
|
|
8990
|
+
}
|
|
8991
|
+
executedAny = true;
|
|
8992
|
+
const result = step.method === "cli" ? await executeCliSetup(step, execService) : await executeConfigFileSetup(step, fs);
|
|
8993
|
+
if (result.status === "failed") {
|
|
8994
|
+
return result;
|
|
8995
|
+
}
|
|
8996
|
+
}
|
|
8997
|
+
if (!executedAny) {
|
|
8998
|
+
return {
|
|
8999
|
+
status: "already_configured",
|
|
9000
|
+
message: "GitHits already configured"
|
|
9001
|
+
};
|
|
9002
|
+
}
|
|
9003
|
+
return { status: "success", message: "Configured successfully" };
|
|
9004
|
+
}
|
|
8645
9005
|
async function executeConfigFileUninstall(setup, fs) {
|
|
8646
9006
|
try {
|
|
8647
9007
|
let existingContent = "";
|
|
@@ -8728,6 +9088,25 @@ function getOpenCodeConfigDir(fs) {
|
|
|
8728
9088
|
}
|
|
8729
9089
|
return fs.joinPath(fs.getHomeDir(), ".config", "opencode");
|
|
8730
9090
|
}
|
|
9091
|
+
function expandHomePath(fs, path) {
|
|
9092
|
+
if (path === "~") {
|
|
9093
|
+
return fs.getHomeDir();
|
|
9094
|
+
}
|
|
9095
|
+
if (path.startsWith("~/")) {
|
|
9096
|
+
return fs.joinPath(fs.getHomeDir(), path.slice(2));
|
|
9097
|
+
}
|
|
9098
|
+
return path;
|
|
9099
|
+
}
|
|
9100
|
+
function getPiAgentDir(fs) {
|
|
9101
|
+
const configuredDir = process.env.PI_CODING_AGENT_DIR?.trim();
|
|
9102
|
+
if (configuredDir) {
|
|
9103
|
+
return expandHomePath(fs, configuredDir);
|
|
9104
|
+
}
|
|
9105
|
+
return fs.joinPath(fs.getHomeDir(), ".pi", "agent");
|
|
9106
|
+
}
|
|
9107
|
+
function getPiMcpConfigPath(fs) {
|
|
9108
|
+
return fs.joinPath(getPiAgentDir(fs), "mcp.json");
|
|
9109
|
+
}
|
|
8731
9110
|
function getOpenCodeDesktopDetectPaths(fs) {
|
|
8732
9111
|
const userDataRoot = getUserDataRoot(fs);
|
|
8733
9112
|
return [
|
|
@@ -8746,6 +9125,57 @@ async function isExecutableAvailable(exec, executable) {
|
|
|
8746
9125
|
return false;
|
|
8747
9126
|
}
|
|
8748
9127
|
}
|
|
9128
|
+
async function resolveExecutableFromPath(exec, executable) {
|
|
9129
|
+
return isExecutableAvailable(exec, executable);
|
|
9130
|
+
}
|
|
9131
|
+
var PI_GLOBAL_BIN_PROBES = [
|
|
9132
|
+
{ command: "npm", args: ["prefix", "-g"], output: "prefix" },
|
|
9133
|
+
{ command: "pnpm", args: ["bin", "-g"], output: "binDir" },
|
|
9134
|
+
{ command: "bun", args: ["pm", "bin", "-g"], output: "binDir" }
|
|
9135
|
+
];
|
|
9136
|
+
var PI_ADAPTER_CONFIGURED_PATTERN = /(?:^|\s|:)(?:npm:)?pi-mcp-adapter(?:[\s@:]|$)/i;
|
|
9137
|
+
function getPiExecutableNames() {
|
|
9138
|
+
return process.platform === "win32" ? ["pi.cmd", "pi.exe", "pi"] : ["pi"];
|
|
9139
|
+
}
|
|
9140
|
+
async function runGlobalBinProbe(exec, probe) {
|
|
9141
|
+
try {
|
|
9142
|
+
const result = await exec.exec(probe.command, [...probe.args]);
|
|
9143
|
+
if (result.exitCode !== 0) {
|
|
9144
|
+
return null;
|
|
9145
|
+
}
|
|
9146
|
+
const probePath = result.stdout.split(/\r?\n/).map((line) => line.trim()).find((line) => line.length > 0);
|
|
9147
|
+
if (!probePath) {
|
|
9148
|
+
return null;
|
|
9149
|
+
}
|
|
9150
|
+
if (probe.output === "prefix" && process.platform !== "win32") {
|
|
9151
|
+
return fsJoinPathLike(probePath, "bin");
|
|
9152
|
+
}
|
|
9153
|
+
return probePath;
|
|
9154
|
+
} catch {
|
|
9155
|
+
return null;
|
|
9156
|
+
}
|
|
9157
|
+
}
|
|
9158
|
+
function fsJoinPathLike(base, child) {
|
|
9159
|
+
return base.endsWith("/") ? `${base}${child}` : `${base}/${child}`;
|
|
9160
|
+
}
|
|
9161
|
+
async function detectPiExecutable(exec, fs) {
|
|
9162
|
+
if (await resolveExecutableFromPath(exec, "pi")) {
|
|
9163
|
+
return { command: "pi" };
|
|
9164
|
+
}
|
|
9165
|
+
for (const probe of PI_GLOBAL_BIN_PROBES) {
|
|
9166
|
+
const binDir = await runGlobalBinProbe(exec, probe);
|
|
9167
|
+
if (!binDir) {
|
|
9168
|
+
continue;
|
|
9169
|
+
}
|
|
9170
|
+
for (const executableName of getPiExecutableNames()) {
|
|
9171
|
+
const candidate = fs.joinPath(binDir, executableName);
|
|
9172
|
+
if (await fs.exists(candidate)) {
|
|
9173
|
+
return { command: candidate };
|
|
9174
|
+
}
|
|
9175
|
+
}
|
|
9176
|
+
}
|
|
9177
|
+
return null;
|
|
9178
|
+
}
|
|
8749
9179
|
var claudeCode = {
|
|
8750
9180
|
name: "Claude Code",
|
|
8751
9181
|
id: "claude-code",
|
|
@@ -8885,6 +9315,76 @@ var codexCli = {
|
|
|
8885
9315
|
]
|
|
8886
9316
|
})
|
|
8887
9317
|
};
|
|
9318
|
+
var pi = {
|
|
9319
|
+
name: "Pi",
|
|
9320
|
+
id: "pi",
|
|
9321
|
+
detectionMethod: "binary",
|
|
9322
|
+
setupMethod: "composite",
|
|
9323
|
+
detectCommand: detectPiExecutable,
|
|
9324
|
+
getSetupConfig: (fs, context) => {
|
|
9325
|
+
const piCommand = context?.command ?? "pi";
|
|
9326
|
+
return {
|
|
9327
|
+
method: "composite",
|
|
9328
|
+
steps: [
|
|
9329
|
+
{
|
|
9330
|
+
method: "cli",
|
|
9331
|
+
commands: [
|
|
9332
|
+
{
|
|
9333
|
+
command: piCommand,
|
|
9334
|
+
args: ["install", "npm:pi-mcp-adapter"]
|
|
9335
|
+
}
|
|
9336
|
+
],
|
|
9337
|
+
checkCommand: {
|
|
9338
|
+
command: piCommand,
|
|
9339
|
+
args: ["list"],
|
|
9340
|
+
configuredPattern: PI_ADAPTER_CONFIGURED_PATTERN
|
|
9341
|
+
}
|
|
9342
|
+
},
|
|
9343
|
+
{
|
|
9344
|
+
method: "config-file",
|
|
9345
|
+
configPath: getPiMcpConfigPath(fs),
|
|
9346
|
+
serversKey: "mcpServers",
|
|
9347
|
+
serverName: GITHITS_SERVER_NAME,
|
|
9348
|
+
serverConfig: {
|
|
9349
|
+
command: GITHITS_MCP_COMMAND,
|
|
9350
|
+
args: [...GITHITS_MCP_ARGS],
|
|
9351
|
+
lifecycle: "eager"
|
|
9352
|
+
}
|
|
9353
|
+
}
|
|
9354
|
+
]
|
|
9355
|
+
};
|
|
9356
|
+
},
|
|
9357
|
+
getUninstallConfig: (fs, context) => {
|
|
9358
|
+
const piCommand = context?.command ?? "pi";
|
|
9359
|
+
return {
|
|
9360
|
+
method: "composite",
|
|
9361
|
+
steps: [
|
|
9362
|
+
{
|
|
9363
|
+
failureMode: "required",
|
|
9364
|
+
step: {
|
|
9365
|
+
method: "config-file",
|
|
9366
|
+
configPath: getPiMcpConfigPath(fs),
|
|
9367
|
+
serversKey: "mcpServers",
|
|
9368
|
+
serverName: GITHITS_SERVER_NAME,
|
|
9369
|
+
serverConfig: {}
|
|
9370
|
+
}
|
|
9371
|
+
},
|
|
9372
|
+
{
|
|
9373
|
+
failureMode: "required",
|
|
9374
|
+
step: {
|
|
9375
|
+
method: "cli",
|
|
9376
|
+
commands: [
|
|
9377
|
+
{
|
|
9378
|
+
command: piCommand,
|
|
9379
|
+
args: ["remove", "npm:pi-mcp-adapter"]
|
|
9380
|
+
}
|
|
9381
|
+
]
|
|
9382
|
+
}
|
|
9383
|
+
}
|
|
9384
|
+
]
|
|
9385
|
+
};
|
|
9386
|
+
}
|
|
9387
|
+
};
|
|
8888
9388
|
var vscode = {
|
|
8889
9389
|
name: "VS Code / Copilot",
|
|
8890
9390
|
id: "vscode",
|
|
@@ -9009,6 +9509,7 @@ var agentDefinitions = [
|
|
|
9009
9509
|
cline,
|
|
9010
9510
|
claudeDesktop,
|
|
9011
9511
|
codexCli,
|
|
9512
|
+
pi,
|
|
9012
9513
|
geminiCli,
|
|
9013
9514
|
googleAntigravity,
|
|
9014
9515
|
openCode
|
|
@@ -9021,7 +9522,18 @@ async function scanAgents(definitions, fs, execService) {
|
|
|
9021
9522
|
};
|
|
9022
9523
|
for (const agent of definitions) {
|
|
9023
9524
|
let detected = false;
|
|
9024
|
-
|
|
9525
|
+
let setupContext;
|
|
9526
|
+
if (agent.detectCommand) {
|
|
9527
|
+
try {
|
|
9528
|
+
const resolvedCommand = await agent.detectCommand(execService, fs);
|
|
9529
|
+
if (resolvedCommand) {
|
|
9530
|
+
detected = true;
|
|
9531
|
+
setupContext = { command: resolvedCommand.command };
|
|
9532
|
+
}
|
|
9533
|
+
} catch {
|
|
9534
|
+
detected = false;
|
|
9535
|
+
}
|
|
9536
|
+
} else if (agent.detectionMethod === "binary" && agent.detectBinary) {
|
|
9025
9537
|
try {
|
|
9026
9538
|
detected = await agent.detectBinary(execService);
|
|
9027
9539
|
} catch {
|
|
@@ -9060,31 +9572,31 @@ async function scanAgents(definitions, fs, execService) {
|
|
|
9060
9572
|
result.notDetected.push(agent);
|
|
9061
9573
|
continue;
|
|
9062
9574
|
}
|
|
9063
|
-
|
|
9064
|
-
|
|
9065
|
-
|
|
9066
|
-
|
|
9067
|
-
|
|
9068
|
-
|
|
9069
|
-
|
|
9070
|
-
|
|
9071
|
-
const config = agent.getSetupConfig(fs);
|
|
9072
|
-
if (config.method === "cli" && config.checkCommand) {
|
|
9575
|
+
const config = agent.getSetupConfig(fs, setupContext);
|
|
9576
|
+
const scannedAgent = {
|
|
9577
|
+
...agent,
|
|
9578
|
+
resolvedSetupConfig: config,
|
|
9579
|
+
resolvedSetupContext: setupContext
|
|
9580
|
+
};
|
|
9581
|
+
if (agent.id === "gemini-cli" && config.method === "cli") {
|
|
9582
|
+
if (config.checkCommand) {
|
|
9073
9583
|
const checkStatus = await getCliCheckStatus(config.checkCommand, execService);
|
|
9074
9584
|
let configured = checkStatus === "configured";
|
|
9075
|
-
if (!configured &&
|
|
9076
|
-
|
|
9077
|
-
configured = await isGeminiExtensionInstalledFromFilesystem(fs);
|
|
9078
|
-
}
|
|
9585
|
+
if (!configured && checkStatus === "probe_failed") {
|
|
9586
|
+
configured = await isGeminiExtensionInstalledFromFilesystem(fs);
|
|
9079
9587
|
}
|
|
9080
9588
|
if (configured) {
|
|
9081
|
-
result.alreadyConfigured.push(
|
|
9589
|
+
result.alreadyConfigured.push(scannedAgent);
|
|
9082
9590
|
} else {
|
|
9083
|
-
result.needsSetup.push(
|
|
9591
|
+
result.needsSetup.push(scannedAgent);
|
|
9084
9592
|
}
|
|
9085
9593
|
} else {
|
|
9086
|
-
result.needsSetup.push(
|
|
9594
|
+
result.needsSetup.push(scannedAgent);
|
|
9087
9595
|
}
|
|
9596
|
+
} else if (await isSetupAlreadyConfigured(config, fs, execService)) {
|
|
9597
|
+
result.alreadyConfigured.push(scannedAgent);
|
|
9598
|
+
} else {
|
|
9599
|
+
result.needsSetup.push(scannedAgent);
|
|
9088
9600
|
}
|
|
9089
9601
|
}
|
|
9090
9602
|
return result;
|
|
@@ -9094,6 +9606,20 @@ class ExitPromptError extends Error {
|
|
|
9094
9606
|
name = "ExitPromptError";
|
|
9095
9607
|
}
|
|
9096
9608
|
// src/commands/init/init.ts
|
|
9609
|
+
function getResolvedSetupConfig(agent, fileSystemService) {
|
|
9610
|
+
return agent.resolvedSetupConfig ?? agent.getSetupConfig(fileSystemService, agent.resolvedSetupContext);
|
|
9611
|
+
}
|
|
9612
|
+
function getPiConfigFileUninstall(agent, fileSystemService) {
|
|
9613
|
+
if (agent.id !== "pi") {
|
|
9614
|
+
return null;
|
|
9615
|
+
}
|
|
9616
|
+
const uninstallConfig = agent.getUninstallConfig?.(fileSystemService);
|
|
9617
|
+
if (uninstallConfig?.method !== "composite") {
|
|
9618
|
+
return null;
|
|
9619
|
+
}
|
|
9620
|
+
const configStep = uninstallConfig.steps.map(({ step }) => step).find((step) => step.method === "config-file");
|
|
9621
|
+
return configStep ?? null;
|
|
9622
|
+
}
|
|
9097
9623
|
function printReadyNextSteps() {
|
|
9098
9624
|
console.log(" Setup complete. You're ready to use GitHits.");
|
|
9099
9625
|
console.log();
|
|
@@ -9135,28 +9661,54 @@ async function verifyAgentUnconfigured(agent, fileSystemService, execService) {
|
|
|
9135
9661
|
message: `${agent.name} verification failed: still configured after uninstall.`
|
|
9136
9662
|
};
|
|
9137
9663
|
}
|
|
9138
|
-
async function
|
|
9139
|
-
|
|
9140
|
-
|
|
9664
|
+
async function inspectSetupForUninstall(agent, config, fileSystemService, execService) {
|
|
9665
|
+
if (config.method === "config-file") {
|
|
9666
|
+
const check = await getConfigUninstallCheckStatus(config, fileSystemService);
|
|
9667
|
+
if (check.status === "configured")
|
|
9668
|
+
return "configured";
|
|
9669
|
+
if (check.status === "not_configured")
|
|
9670
|
+
return "not_configured";
|
|
9671
|
+
return { status: "failed", message: check.message };
|
|
9672
|
+
}
|
|
9673
|
+
if (config.method === "cli") {
|
|
9674
|
+
if (!config.checkCommand) {
|
|
9675
|
+
return {
|
|
9676
|
+
status: "failed",
|
|
9677
|
+
message: `${agent.name} does not have a verified uninstall check command.`
|
|
9678
|
+
};
|
|
9679
|
+
}
|
|
9680
|
+
const checkStatus = await getCliCheckStatus(config.checkCommand, execService);
|
|
9681
|
+
if (checkStatus === "configured")
|
|
9682
|
+
return "configured";
|
|
9683
|
+
if (checkStatus === "not_configured")
|
|
9684
|
+
return "not_configured";
|
|
9685
|
+
if (agent.id === "gemini-cli" && await isGeminiExtensionInstalledFromFilesystem(fileSystemService)) {
|
|
9686
|
+
return "configured";
|
|
9687
|
+
}
|
|
9141
9688
|
return {
|
|
9142
9689
|
status: "failed",
|
|
9143
|
-
message:
|
|
9690
|
+
message: `Cannot inspect ${agent.name}: ${config.checkCommand.command} ${config.checkCommand.args.join(" ")} failed.`
|
|
9144
9691
|
};
|
|
9145
9692
|
}
|
|
9146
|
-
const
|
|
9147
|
-
|
|
9148
|
-
|
|
9149
|
-
}
|
|
9150
|
-
|
|
9151
|
-
|
|
9693
|
+
const accumulated = {
|
|
9694
|
+
configured: false,
|
|
9695
|
+
notConfigured: false
|
|
9696
|
+
};
|
|
9697
|
+
for (const step of config.steps) {
|
|
9698
|
+
const check = await inspectSetupForUninstall(agent, step, fileSystemService, execService);
|
|
9699
|
+
if (check === "configured") {
|
|
9700
|
+
accumulated.configured = true;
|
|
9701
|
+
} else if (check === "not_configured") {
|
|
9702
|
+
accumulated.notConfigured = true;
|
|
9703
|
+
} else {
|
|
9704
|
+
accumulated.failure = check;
|
|
9705
|
+
}
|
|
9152
9706
|
}
|
|
9153
|
-
if (
|
|
9707
|
+
if (accumulated.failure)
|
|
9708
|
+
return accumulated.failure;
|
|
9709
|
+
if (accumulated.configured)
|
|
9154
9710
|
return "configured";
|
|
9155
|
-
|
|
9156
|
-
return {
|
|
9157
|
-
status: "failed",
|
|
9158
|
-
message: `Cannot inspect ${agent.name}: ${config.checkCommand.command} ${config.checkCommand.args.join(" ")} failed.`
|
|
9159
|
-
};
|
|
9711
|
+
return "not_configured";
|
|
9160
9712
|
}
|
|
9161
9713
|
async function scanAgentsForUninstall(fileSystemService, execService) {
|
|
9162
9714
|
const setupScan = await scanAgents(agentDefinitions, fileSystemService, execService);
|
|
@@ -9170,35 +9722,41 @@ async function scanAgentsForUninstall(fileSystemService, execService) {
|
|
|
9170
9722
|
...setupScan.alreadyConfigured,
|
|
9171
9723
|
...setupScan.needsSetup
|
|
9172
9724
|
]) {
|
|
9173
|
-
const config = agent
|
|
9174
|
-
|
|
9175
|
-
|
|
9176
|
-
|
|
9177
|
-
|
|
9178
|
-
|
|
9179
|
-
result.failed.push({
|
|
9180
|
-
id: agent.id,
|
|
9181
|
-
name: agent.name,
|
|
9182
|
-
status: "failed",
|
|
9183
|
-
message: check.message
|
|
9184
|
-
});
|
|
9185
|
-
} else {
|
|
9186
|
-
result.notConfigured.push(agent);
|
|
9187
|
-
}
|
|
9725
|
+
const config = getResolvedSetupConfig(agent, fileSystemService);
|
|
9726
|
+
const check = await inspectSetupForUninstall(agent, config, fileSystemService, execService);
|
|
9727
|
+
if (check === "configured") {
|
|
9728
|
+
result.configured.push(agent);
|
|
9729
|
+
} else if (check === "not_configured") {
|
|
9730
|
+
result.notConfigured.push(agent);
|
|
9188
9731
|
} else {
|
|
9189
|
-
|
|
9190
|
-
|
|
9191
|
-
|
|
9192
|
-
|
|
9193
|
-
|
|
9194
|
-
}
|
|
9195
|
-
|
|
9196
|
-
|
|
9197
|
-
|
|
9198
|
-
|
|
9199
|
-
|
|
9200
|
-
|
|
9201
|
-
|
|
9732
|
+
result.failed.push({
|
|
9733
|
+
id: agent.id,
|
|
9734
|
+
name: agent.name,
|
|
9735
|
+
status: "failed",
|
|
9736
|
+
message: check.message
|
|
9737
|
+
});
|
|
9738
|
+
}
|
|
9739
|
+
}
|
|
9740
|
+
for (const agent of setupScan.notDetected) {
|
|
9741
|
+
const piConfigUninstall = getPiConfigFileUninstall(agent, fileSystemService);
|
|
9742
|
+
if (!piConfigUninstall) {
|
|
9743
|
+
continue;
|
|
9744
|
+
}
|
|
9745
|
+
const check = await getConfigUninstallCheckStatus(piConfigUninstall, fileSystemService);
|
|
9746
|
+
if (check.status === "configured") {
|
|
9747
|
+
result.configured.push({
|
|
9748
|
+
...agent,
|
|
9749
|
+
resolvedUninstallConfig: piConfigUninstall,
|
|
9750
|
+
skipUninstallVerification: true
|
|
9751
|
+
});
|
|
9752
|
+
result.notDetected = result.notDetected.filter((a) => a.id !== agent.id);
|
|
9753
|
+
} else if (check.status === "failed") {
|
|
9754
|
+
result.failed.push({
|
|
9755
|
+
id: agent.id,
|
|
9756
|
+
name: agent.name,
|
|
9757
|
+
status: "failed",
|
|
9758
|
+
message: check.message
|
|
9759
|
+
});
|
|
9202
9760
|
}
|
|
9203
9761
|
}
|
|
9204
9762
|
return result;
|
|
@@ -9216,7 +9774,7 @@ async function initAction(options, deps) {
|
|
|
9216
9774
|
let loginResult;
|
|
9217
9775
|
try {
|
|
9218
9776
|
const loginDeps = await createLoginDeps();
|
|
9219
|
-
loginResult = await loginFlow({}, loginDeps);
|
|
9777
|
+
loginResult = loginDeps.hasValidToken ? { status: "already_authenticated", message: "Already logged in." } : await loginFlow({}, loginDeps);
|
|
9220
9778
|
} catch (error2) {
|
|
9221
9779
|
const msg = error2 instanceof Error ? error2.message : String(error2);
|
|
9222
9780
|
loginResult = { status: "failed", message: msg };
|
|
@@ -9288,7 +9846,7 @@ async function initAction(options, deps) {
|
|
|
9288
9846
|
for (const agent of toSetup) {
|
|
9289
9847
|
console.log(` Setting up ${colorize(agent.name, "bold", useColors)}...
|
|
9290
9848
|
`);
|
|
9291
|
-
const config = agent.getSetupConfig(fileSystemService);
|
|
9849
|
+
const config = agent.resolvedSetupConfig ?? agent.getSetupConfig(fileSystemService);
|
|
9292
9850
|
const preview2 = formatSetupPreview(config);
|
|
9293
9851
|
for (const line of preview2.split(`
|
|
9294
9852
|
`)) {
|
|
@@ -9317,7 +9875,7 @@ async function initAction(options, deps) {
|
|
|
9317
9875
|
alwaysMode = true;
|
|
9318
9876
|
}
|
|
9319
9877
|
}
|
|
9320
|
-
let result = config.method === "cli" ? await executeCliSetup(config, execService) : await executeConfigFileSetup(config, fileSystemService);
|
|
9878
|
+
let result = config.method === "cli" ? await executeCliSetup(config, execService) : config.method === "config-file" ? await executeConfigFileSetup(config, fileSystemService) : await executeCompositeSetup(config, fileSystemService, execService);
|
|
9321
9879
|
if (result.status === "success" || result.status === "already_configured") {
|
|
9322
9880
|
const verification = await verifyAgentConfigured(agent, fileSystemService, execService);
|
|
9323
9881
|
if (!verification.ok) {
|
|
@@ -9401,8 +9959,8 @@ async function initUninstallAction(options, deps) {
|
|
|
9401
9959
|
for (const agent of scan.configured) {
|
|
9402
9960
|
console.log(` Uninstalling from ${colorize(agent.name, "bold", useColors)}...
|
|
9403
9961
|
`);
|
|
9404
|
-
const setupConfig = agent
|
|
9405
|
-
const uninstallConfig = setupConfig.method === "config-file" ? setupConfig : agent.getUninstallConfig?.(fileSystemService);
|
|
9962
|
+
const setupConfig = getResolvedSetupConfig(agent, fileSystemService);
|
|
9963
|
+
const uninstallConfig = agent.resolvedUninstallConfig ?? (setupConfig.method === "config-file" ? setupConfig : agent.getUninstallConfig?.(fileSystemService, agent.resolvedSetupContext));
|
|
9406
9964
|
if (!uninstallConfig) {
|
|
9407
9965
|
outcomes.push({
|
|
9408
9966
|
id: agent.id,
|
|
@@ -9442,8 +10000,8 @@ async function initUninstallAction(options, deps) {
|
|
|
9442
10000
|
alwaysMode = true;
|
|
9443
10001
|
}
|
|
9444
10002
|
}
|
|
9445
|
-
let result = uninstallConfig.method === "cli" ? await executeCliUninstall(uninstallConfig, execService) : await executeConfigFileUninstall(uninstallConfig, fileSystemService);
|
|
9446
|
-
if (result.status === "removed") {
|
|
10003
|
+
let result = uninstallConfig.method === "cli" ? await executeCliUninstall(uninstallConfig, execService) : uninstallConfig.method === "config-file" ? await executeConfigFileUninstall(uninstallConfig, fileSystemService) : await executeCompositeUninstall(uninstallConfig, fileSystemService, execService);
|
|
10004
|
+
if (result.status === "removed" && !agent.skipUninstallVerification) {
|
|
9447
10005
|
const verification = await verifyAgentUnconfigured(agent, fileSystemService, execService);
|
|
9448
10006
|
if (!verification.ok) {
|
|
9449
10007
|
result = {
|
|
@@ -9523,10 +10081,11 @@ var INIT_DESCRIPTION = `Set up GitHits MCP server for your coding agents.
|
|
|
9523
10081
|
|
|
9524
10082
|
Authenticates with your GitHits account, then scans for available agents
|
|
9525
10083
|
(Claude Code, Cursor, Windsurf, VS Code, Cline, Claude Desktop, Codex CLI,
|
|
9526
|
-
Gemini CLI, Google Antigravity), checks which are already configured,
|
|
10084
|
+
Pi, Gemini CLI, Google Antigravity), checks which are already configured,
|
|
9527
10085
|
and sets up unconfigured ones with your confirmation.
|
|
9528
10086
|
|
|
9529
|
-
Supports CLI-based setup (Claude Code, Codex, Gemini CLI)
|
|
10087
|
+
Supports CLI-based setup (Claude Code, Codex, Gemini CLI), Pi package setup,
|
|
10088
|
+
and config
|
|
9530
10089
|
file editing (Cursor, Windsurf, VS Code, Cline, Claude Desktop,
|
|
9531
10090
|
Google Antigravity) with atomic writes.`;
|
|
9532
10091
|
var INIT_UNINSTALL_DESCRIPTION = `Remove GitHits MCP server configuration from your coding agents.
|
|
@@ -9543,7 +10102,7 @@ function registerInitCommand(program) {
|
|
|
9543
10102
|
fileSystemService,
|
|
9544
10103
|
promptService,
|
|
9545
10104
|
execService,
|
|
9546
|
-
createLoginDeps: () =>
|
|
10105
|
+
createLoginDeps: () => createContainer()
|
|
9547
10106
|
});
|
|
9548
10107
|
});
|
|
9549
10108
|
initCommand.command("uninstall").summary("Remove MCP server from your coding agents").description(INIT_UNINSTALL_DESCRIPTION).option("-y, --yes", "Skip prompts, uninstall from all configured agents").action(async (options) => {
|
|
@@ -9779,11 +10338,11 @@ var structuredCodeTargetSchema = z3.object({
|
|
|
9779
10338
|
package_name: z3.string().max(255).optional().describe("Package name. Required for package scope."),
|
|
9780
10339
|
version: z3.string().max(100).optional().describe("Package version, e.g. '4.18.2' (defaults to latest). For package scope only."),
|
|
9781
10340
|
repo_url: z3.string().optional().describe("Repository URL (GitHub). Required for repo scope. Example: https://github.com/expressjs/express"),
|
|
9782
|
-
git_ref: z3.string().optional().describe("Git ref - tag, branch, or
|
|
9783
|
-
}).describe("Target: provide registry + package_name (package scope) or repo_url
|
|
10341
|
+
git_ref: z3.string().optional().describe("Git ref - tag, branch, commit, or HEAD. Omit with repo_url to request the backend-resolved default branch.")
|
|
10342
|
+
}).describe("Target: provide registry + package_name (package scope) or repo_url with optional git_ref (repo scope; omitted ref means default branch intent).");
|
|
9784
10343
|
var codeTargetSchema = z3.union([
|
|
9785
10344
|
structuredCodeTargetSchema,
|
|
9786
|
-
z3.string().min(1).describe("Compact target string. Package: `npm:react@18.2.0` or `npm:react` for latest release. Repository: `https://github.com/facebook/react#HEAD`
|
|
10345
|
+
z3.string().min(1).describe("Compact target string. Package: `npm:react@18.2.0` or `npm:react` for latest release. Repository: `https://github.com/facebook/react#HEAD` or `https://github.com/facebook/react` for default branch intent.")
|
|
9787
10346
|
]);
|
|
9788
10347
|
function resolveCodeTarget(target) {
|
|
9789
10348
|
if (typeof target === "string") {
|
|
@@ -9796,10 +10355,10 @@ function resolveCodeTarget(target) {
|
|
|
9796
10355
|
const hasPackageTarget = Boolean(target.registry || target.package_name);
|
|
9797
10356
|
const hasRepoTarget = Boolean(target.repo_url || target.git_ref);
|
|
9798
10357
|
if (hasPackageTarget && hasRepoTarget) {
|
|
9799
|
-
return invalidTargetResult("Invalid target: provide either registry + package_name or repo_url
|
|
10358
|
+
return invalidTargetResult("Invalid target: provide either registry + package_name or repo_url with optional git_ref, not both.");
|
|
9800
10359
|
}
|
|
9801
10360
|
if (!hasPackageTarget && !hasRepoTarget) {
|
|
9802
|
-
return invalidTargetResult("Missing target: provide registry + package_name or repo_url
|
|
10361
|
+
return invalidTargetResult("Missing target: provide registry + package_name or repo_url.");
|
|
9803
10362
|
}
|
|
9804
10363
|
if (hasPackageTarget) {
|
|
9805
10364
|
if (!target.registry || !target.package_name) {
|
|
@@ -9811,11 +10370,8 @@ function resolveCodeTarget(target) {
|
|
|
9811
10370
|
version: target.version
|
|
9812
10371
|
};
|
|
9813
10372
|
}
|
|
9814
|
-
if (!target.repo_url
|
|
9815
|
-
|
|
9816
|
-
return invalidTargetResult("Incomplete repository target: repo_url is required.");
|
|
9817
|
-
}
|
|
9818
|
-
return invalidTargetResult("Incomplete repository target: git_ref is required for code_files/code_read/code_grep.");
|
|
10373
|
+
if (!target.repo_url) {
|
|
10374
|
+
return invalidTargetResult("Incomplete repository target: repo_url is required.");
|
|
9819
10375
|
}
|
|
9820
10376
|
return {
|
|
9821
10377
|
repoUrl: target.repo_url,
|
|
@@ -9861,7 +10417,7 @@ var schema3 = {
|
|
|
9861
10417
|
wait_timeout_ms: z4.number().optional(),
|
|
9862
10418
|
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.')
|
|
9863
10419
|
};
|
|
9864
|
-
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 `filePath` (or text file heading) chains into `code_read.path`; pick a window around `match.line` for `code_read.start_line` / `end_line`." + `
|
|
10420
|
+
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 `filePath` (or text file heading) chains into `code_read.path`; pick a window around `match.line` for `code_read.start_line` / `end_line`. " + "When fresh data is not ready within the wait window, responses may include `targetResolution` provenance and immediately-queryable alternatives in error details." + `
|
|
9865
10421
|
|
|
9866
10422
|
${CODE_GREP_GUARDRAIL}`;
|
|
9867
10423
|
function createGrepRepoTool(service) {
|
|
@@ -9955,10 +10511,10 @@ var schema4 = {
|
|
|
9955
10511
|
exclude_test_files: z5.boolean().optional(),
|
|
9956
10512
|
include_hidden: z5.boolean().optional(),
|
|
9957
10513
|
limit: z5.number().optional().describe("Max entries to return (1–1000, default 200). Out-of-range values return an `INVALID_ARGUMENT` envelope."),
|
|
9958
|
-
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`."),
|
|
10514
|
+
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/ref from `details.availableVersions` / `details.availableRefs`."),
|
|
9959
10515
|
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.')
|
|
9960
10516
|
};
|
|
9961
|
-
var DESCRIPTION4 = "List files in an indexed dependency. First choice for file/path " + "enumeration tasks such as files under a directory; use " + "`path_prefix` for directory prefixes (e.g. `lib/`) and optional " + "`extensions` for language filtering. 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}`. " + "
|
|
10517
|
+
var DESCRIPTION4 = "List files in an indexed dependency. First choice for file/path " + "enumeration tasks such as files under a directory; use " + "`path_prefix` for directory prefixes (e.g. `lib/`) and optional " + "`extensions` for language filtering. 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` + optional `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}`. " + "When fresh data is not ready within the wait window, responses may " + "include `targetResolution` provenance and immediately-queryable " + "alternatives. On an `INDEXING` error envelope, retry with a longer " + "`wait_timeout_ms` or use a version/ref from `details.availableVersions` " + "/ `details.availableRefs`.";
|
|
9962
10518
|
function createListFilesTool(service) {
|
|
9963
10519
|
return {
|
|
9964
10520
|
name: "code_files",
|
|
@@ -10721,10 +11277,10 @@ var schema11 = {
|
|
|
10721
11277
|
path: z12.string().describe("Exact file path to read, not a directory. Package addressing: package-relative. Repo addressing: repo-relative. Use `code_files` with `path_prefix` to list directories, then pass an emitted `path` here."),
|
|
10722
11278
|
start_line: z12.number().optional().describe(`Starting line (1-indexed). Omit to start at line 1. The MCP surface caps any single read at ${MCP_READ_MAX_SPAN} lines — pick a focused window from your prior \`search\` / \`code_grep\` hit.`),
|
|
10723
11279
|
end_line: z12.number().optional().describe(`Ending line (inclusive). Must be ≥ \`start_line\` when both are set. Omitting it implies \`start_line + ${MCP_READ_MAX_SPAN - 1}\` because the MCP surface caps each read at ${MCP_READ_MAX_SPAN} lines.`),
|
|
10724
|
-
wait_timeout_ms: z12.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`."),
|
|
11280
|
+
wait_timeout_ms: z12.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/ref from `details.availableVersions` / `details.availableRefs`."),
|
|
10725
11281
|
format: z12.enum(["json", "text", "text-v1"]).optional().describe('Response format. Default `text-v1` — line-numbered source content. Pass `format: "json"` for the structured envelope.')
|
|
10726
11282
|
};
|
|
10727
|
-
var DESCRIPTION11 = "Read one exact file from an indexed dependency; it does not list " + "directories. Use `code_files` with `path_prefix` for file/path " + "enumeration. **MCP cap: " + `${MCP_READ_MAX_SPAN} lines per call** — broader requests (or no ` + `range) silently truncate to the first ${MCP_READ_MAX_SPAN} lines ` + "from your start, with a `hint` describing what was returned vs. " + "requested. Pick a focused window from a `search` / `code_grep` " + "match. Response: `{path, language, totalLines, startLine, endLine, " + "content, isBinary, hint?}`. Binary files set `isBinary: true` and " + "omit `content`. Pass the same `path` emitted by `code_files`. " + "Address via `target.registry` + `target.package_name` (package " + "scope) or `target.repo_url` + `target.git_ref` (repo scope), " + "mutually exclusive. On `INDEXING` retry with a
|
|
11283
|
+
var DESCRIPTION11 = "Read one exact file from an indexed dependency; it does not list " + "directories. Use `code_files` with `path_prefix` for file/path " + "enumeration. **MCP cap: " + `${MCP_READ_MAX_SPAN} lines per call** — broader requests (or no ` + `range) silently truncate to the first ${MCP_READ_MAX_SPAN} lines ` + "from your start, with a `hint` describing what was returned vs. " + "requested. Pick a focused window from a `search` / `code_grep` " + "match. Response: `{path, language, totalLines, startLine, endLine, " + "content, isBinary, hint?}`. Binary files set `isBinary: true` and " + "omit `content`. Pass the same `path` emitted by `code_files`. " + "Address via `target.registry` + `target.package_name` (package " + "scope) or `target.repo_url` + optional `target.git_ref` (repo scope), " + "mutually exclusive. When fresh data is not ready within the wait " + "window, responses may include `targetResolution` provenance and " + "immediately-queryable alternatives. On `INDEXING` retry with a " + "longer `wait_timeout_ms` or use a version/ref from error details. " + "On `NOT_FOUND` / `FILE_NOT_FOUND` call " + "`code_files` to discover the actual path." + `
|
|
10728
11284
|
|
|
10729
11285
|
${CODE_READ_GUARDRAIL}`;
|
|
10730
11286
|
function deriveBoundedRange(startLine, endLine) {
|
|
@@ -11124,7 +11680,7 @@ var CORE_BLOCK = `GitHits provides verified, canonical code examples from global
|
|
|
11124
11680
|
\`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\`.`;
|
|
11125
11681
|
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.
|
|
11126
11682
|
|
|
11127
|
-
Targets: \`registry:name[@version]\` (\`registry:name\` = latest release).
|
|
11683
|
+
Targets: \`registry:name[@version]\` (\`registry:name\` = latest release). Repo targets can request the backend default-branch intent by omitting the ref (\`https://github.com/org/repo\` for \`search\`, or \`repo_url\` without \`git_ref\` for \`code_*\`); pass \`#HEAD\` / \`git_ref:"HEAD"\` when you specifically need latest HEAD. Default outputs are compact \`text-v1\`; pass \`format: "json"\` only for structured parsing.`;
|
|
11128
11684
|
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.';
|
|
11129
11685
|
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`.';
|
|
11130
11686
|
var SEARCH_STATUS_BULLET = "- `search_status` — follow up a prior `search` by `searchRef` to check progress, fetch partial hits, or fetch final results.";
|
|
@@ -11948,7 +12504,7 @@ function requireSearchService(deps) {
|
|
|
11948
12504
|
return deps.codeNavigationService;
|
|
11949
12505
|
}
|
|
11950
12506
|
async function loadContainer2() {
|
|
11951
|
-
const { createContainer: createContainer2 } = await import("./shared/chunk-
|
|
12507
|
+
const { createContainer: createContainer2 } = await import("./shared/chunk-2fdxv7pe.js");
|
|
11952
12508
|
return createContainer2();
|
|
11953
12509
|
}
|
|
11954
12510
|
function parseTargetSpecs(specs) {
|
|
@@ -12047,7 +12603,7 @@ function formatUnifiedSearchTerminal(payload) {
|
|
|
12047
12603
|
lines.push("");
|
|
12048
12604
|
lines.push("Partial results:");
|
|
12049
12605
|
}
|
|
12050
|
-
const sourceStatusNotes = formatSourceStatusNotes(payload.sourceStatus);
|
|
12606
|
+
const sourceStatusNotes = formatSourceStatusNotes(payload.sourceStatus, warnings);
|
|
12051
12607
|
if (payload.results.length === 0) {
|
|
12052
12608
|
lines.push("No results.");
|
|
12053
12609
|
if (sourceStatusNotes.length > 0) {
|
|
@@ -12159,13 +12715,17 @@ function formatSearchStatusPartialTerminal(payload) {
|
|
|
12159
12715
|
sourceStatus: payload.result.sourceStatus
|
|
12160
12716
|
});
|
|
12161
12717
|
}
|
|
12162
|
-
function formatSourceStatusNotes(sourceStatus) {
|
|
12718
|
+
function formatSourceStatusNotes(sourceStatus, warnings) {
|
|
12163
12719
|
const useColors = shouldUseColors();
|
|
12164
12720
|
if (!sourceStatus) {
|
|
12165
12721
|
return [];
|
|
12166
12722
|
}
|
|
12167
12723
|
const lines = [];
|
|
12168
12724
|
for (const entry of sourceStatus) {
|
|
12725
|
+
const warningPrefix = `Source '${entry.source.toLowerCase()}' for ${entry.targetLabel}:`;
|
|
12726
|
+
if (warnings?.some((warning2) => warning2.startsWith(warningPrefix))) {
|
|
12727
|
+
continue;
|
|
12728
|
+
}
|
|
12169
12729
|
const label = `${entry.source.toLowerCase()} on ${entry.targetLabel}`;
|
|
12170
12730
|
if (entry.ignoredFilters && entry.ignoredFilters.length > 0) {
|
|
12171
12731
|
lines.push(dim(`Note: ${label} ignored filters: ${entry.ignoredFilters.join(", ")}`, useColors));
|
|
@@ -12396,7 +12956,7 @@ function mergeRanges2(ranges) {
|
|
|
12396
12956
|
}
|
|
12397
12957
|
return merged;
|
|
12398
12958
|
}
|
|
12399
|
-
function formatUnifiedSearchMetadata(entry,
|
|
12959
|
+
function formatUnifiedSearchMetadata(entry, _useColors) {
|
|
12400
12960
|
if (entry.type !== "documentation_page" && entry.type !== "repository_doc") {
|
|
12401
12961
|
return [];
|
|
12402
12962
|
}
|