githits 0.1.9 → 0.1.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/marketplace.json +1 -1
- package/.claude-plugin/plugin.json +1 -1
- package/.plugin/plugin.json +1 -1
- package/README.md +1 -0
- package/dist/cli.js +815 -449
- package/dist/index.js +1 -1
- package/dist/shared/{chunk-ey1zffpv.js → chunk-5g0k8452.js} +1 -1
- package/gemini-extension.json +1 -1
- package/package.json +1 -1
- package/plugins/claude/.claude-plugin/plugin.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
version
|
|
4
|
-
} from "./shared/chunk-
|
|
4
|
+
} from "./shared/chunk-5g0k8452.js";
|
|
5
5
|
|
|
6
6
|
// src/cli.ts
|
|
7
7
|
import { Command } from "commander";
|
|
@@ -616,6 +616,158 @@ function isAreaEnabled(area) {
|
|
|
616
616
|
return scopes.includes(area) || scopes.includes("*");
|
|
617
617
|
}
|
|
618
618
|
|
|
619
|
+
// src/shared/request-headers.ts
|
|
620
|
+
import { createHash as createHash2, randomUUID } from "node:crypto";
|
|
621
|
+
var MAX_HEADER_BYTES = 256;
|
|
622
|
+
var SESSION_ENV_VARS = [
|
|
623
|
+
"TERM_SESSION_ID",
|
|
624
|
+
"ITERM_SESSION_ID",
|
|
625
|
+
"WEZTERM_PANE",
|
|
626
|
+
"KITTY_PID",
|
|
627
|
+
"ALACRITTY_SOCKET",
|
|
628
|
+
"WT_SESSION",
|
|
629
|
+
"VSCODE_PID",
|
|
630
|
+
"SUPERSET_PANE_ID",
|
|
631
|
+
"SUPERSET_WORKSPACE_ID",
|
|
632
|
+
"STARSHIP_SESSION_KEY",
|
|
633
|
+
"SSH_CONNECTION"
|
|
634
|
+
];
|
|
635
|
+
var cachedSessionId;
|
|
636
|
+
function resolveRawSessionId(env = process.env, ppid = process.ppid) {
|
|
637
|
+
for (const key of SESSION_ENV_VARS) {
|
|
638
|
+
const value = env[key];
|
|
639
|
+
if (value && value.trim().length > 0) {
|
|
640
|
+
return value.trim();
|
|
641
|
+
}
|
|
642
|
+
}
|
|
643
|
+
if (typeof ppid === "number" && !Number.isNaN(ppid) && ppid > 0) {
|
|
644
|
+
return String(ppid);
|
|
645
|
+
}
|
|
646
|
+
return randomUUID();
|
|
647
|
+
}
|
|
648
|
+
function getSessionId(env, ppid) {
|
|
649
|
+
if (cachedSessionId !== undefined && env === undefined && ppid === undefined) {
|
|
650
|
+
return cachedSessionId;
|
|
651
|
+
}
|
|
652
|
+
const raw = resolveRawSessionId(env, ppid);
|
|
653
|
+
const hashed = hashValue(raw);
|
|
654
|
+
if (env === undefined && ppid === undefined) {
|
|
655
|
+
cachedSessionId = hashed;
|
|
656
|
+
}
|
|
657
|
+
return hashed;
|
|
658
|
+
}
|
|
659
|
+
function hashValue(input) {
|
|
660
|
+
return createHash2("sha256").update(input).digest("hex").slice(0, 16);
|
|
661
|
+
}
|
|
662
|
+
var AGENT_PROBES = [
|
|
663
|
+
{ envVar: "OPENCODE", name: "opencode" },
|
|
664
|
+
{ envVar: "CLAUDECODE", name: "claude-code" },
|
|
665
|
+
{ envVar: "CURSOR_TRACE_ID", name: "cursor" },
|
|
666
|
+
{ envVar: "WINDSURF_CONFIG_DIR", name: "windsurf" },
|
|
667
|
+
{ envVar: "ZED_TERM", name: "zed" },
|
|
668
|
+
{ envVar: "VSCODE_PID", name: "vscode" }
|
|
669
|
+
];
|
|
670
|
+
function parseAgentString(raw) {
|
|
671
|
+
const trimmed = raw.trim();
|
|
672
|
+
if (trimmed.length === 0)
|
|
673
|
+
return;
|
|
674
|
+
const slashIndex = trimmed.indexOf("/");
|
|
675
|
+
if (slashIndex === -1)
|
|
676
|
+
return { name: trimmed };
|
|
677
|
+
const name = trimmed.slice(0, slashIndex);
|
|
678
|
+
const ver = trimmed.slice(slashIndex + 1);
|
|
679
|
+
if (name.length === 0)
|
|
680
|
+
return;
|
|
681
|
+
return { name, version: ver || undefined };
|
|
682
|
+
}
|
|
683
|
+
function formatAgentInfo(info) {
|
|
684
|
+
return info.version ? `${info.name}/${info.version}` : info.name;
|
|
685
|
+
}
|
|
686
|
+
function resolveAgentInfo(env = process.env) {
|
|
687
|
+
const explicit = env.GITHITS_AGENT;
|
|
688
|
+
if (explicit && explicit.trim().length > 0) {
|
|
689
|
+
return parseAgentString(explicit);
|
|
690
|
+
}
|
|
691
|
+
for (const probe of AGENT_PROBES) {
|
|
692
|
+
const value = env[probe.envVar];
|
|
693
|
+
if (value && value.trim().length > 0) {
|
|
694
|
+
return { name: probe.name };
|
|
695
|
+
}
|
|
696
|
+
}
|
|
697
|
+
return;
|
|
698
|
+
}
|
|
699
|
+
var currentAgentInfo;
|
|
700
|
+
var agentInfoInitialized = false;
|
|
701
|
+
var agentInfoExplicitlySet = false;
|
|
702
|
+
var mcpClientVersionProvider;
|
|
703
|
+
function setMcpClientVersionProvider(provider) {
|
|
704
|
+
mcpClientVersionProvider = provider;
|
|
705
|
+
}
|
|
706
|
+
function getAgentInfo(env) {
|
|
707
|
+
if (agentInfoExplicitlySet) {
|
|
708
|
+
return currentAgentInfo;
|
|
709
|
+
}
|
|
710
|
+
if (mcpClientVersionProvider) {
|
|
711
|
+
try {
|
|
712
|
+
const fromProvider = mcpClientVersionProvider();
|
|
713
|
+
if (fromProvider && fromProvider.name.trim().length > 0) {
|
|
714
|
+
return fromProvider;
|
|
715
|
+
}
|
|
716
|
+
} catch {}
|
|
717
|
+
}
|
|
718
|
+
if (!agentInfoInitialized || env !== undefined) {
|
|
719
|
+
currentAgentInfo = resolveAgentInfo(env);
|
|
720
|
+
if (env === undefined) {
|
|
721
|
+
agentInfoInitialized = true;
|
|
722
|
+
}
|
|
723
|
+
}
|
|
724
|
+
return currentAgentInfo;
|
|
725
|
+
}
|
|
726
|
+
var CONTROL_CHARS = /[\x00-\x1f\x7f-\x9f]/g;
|
|
727
|
+
function sanitizeHeaderValue(value) {
|
|
728
|
+
if (value === undefined || value === null || typeof value !== "string") {
|
|
729
|
+
return;
|
|
730
|
+
}
|
|
731
|
+
const cleaned = value.replace(CONTROL_CHARS, "").trim();
|
|
732
|
+
if (cleaned.length === 0)
|
|
733
|
+
return;
|
|
734
|
+
if (Buffer.byteLength(cleaned, "utf8") > MAX_HEADER_BYTES)
|
|
735
|
+
return;
|
|
736
|
+
return cleaned;
|
|
737
|
+
}
|
|
738
|
+
var BASE_CLIENT_NAME = "githits-cli";
|
|
739
|
+
var clientName = BASE_CLIENT_NAME;
|
|
740
|
+
function setClientMode(mode) {
|
|
741
|
+
clientName = `${BASE_CLIENT_NAME}/${mode}`;
|
|
742
|
+
}
|
|
743
|
+
function buildClientHeaders(env, ppid) {
|
|
744
|
+
try {
|
|
745
|
+
const headers = {};
|
|
746
|
+
const name = sanitizeHeaderValue(clientName);
|
|
747
|
+
if (name) {
|
|
748
|
+
headers["x-githits-client-name"] = name;
|
|
749
|
+
}
|
|
750
|
+
const clientVersion = sanitizeHeaderValue(version);
|
|
751
|
+
if (clientVersion) {
|
|
752
|
+
headers["x-githits-client-version"] = clientVersion;
|
|
753
|
+
}
|
|
754
|
+
const agentInfo = getAgentInfo(env);
|
|
755
|
+
if (agentInfo) {
|
|
756
|
+
const agentValue = sanitizeHeaderValue(formatAgentInfo(agentInfo));
|
|
757
|
+
if (agentValue) {
|
|
758
|
+
headers["x-githits-agent"] = agentValue;
|
|
759
|
+
}
|
|
760
|
+
}
|
|
761
|
+
const sessionId = sanitizeHeaderValue(getSessionId(env, ppid));
|
|
762
|
+
if (sessionId) {
|
|
763
|
+
headers["x-githits-session-id"] = sessionId;
|
|
764
|
+
}
|
|
765
|
+
return headers;
|
|
766
|
+
} catch {
|
|
767
|
+
return {};
|
|
768
|
+
}
|
|
769
|
+
}
|
|
770
|
+
|
|
619
771
|
// src/shared/pkgseer-graphql.ts
|
|
620
772
|
class PkgseerTransportError extends Error {
|
|
621
773
|
constructor(message, options) {
|
|
@@ -634,6 +786,7 @@ async function postPkgseerGraphql(request) {
|
|
|
634
786
|
response = await fetchFn(`${baseUrl(request.endpointUrl)}/api/graphql`, {
|
|
635
787
|
method: "POST",
|
|
636
788
|
headers: {
|
|
789
|
+
...buildClientHeaders(),
|
|
637
790
|
Authorization: `Bearer ${request.token}`,
|
|
638
791
|
"Content-Type": "application/json",
|
|
639
792
|
"User-Agent": userAgent
|
|
@@ -669,6 +822,157 @@ function parseJsonOrNull(body) {
|
|
|
669
822
|
}
|
|
670
823
|
}
|
|
671
824
|
|
|
825
|
+
// src/shared/telemetry.ts
|
|
826
|
+
import { writeSync } from "node:fs";
|
|
827
|
+
var ENABLED_VALUES = new Set(["1", "true", "yes", "on"]);
|
|
828
|
+
function isTelemetryEnabled(env = process.env) {
|
|
829
|
+
const raw = env.GITHITS_TELEMETRY?.trim().toLowerCase();
|
|
830
|
+
if (!raw)
|
|
831
|
+
return false;
|
|
832
|
+
return ENABLED_VALUES.has(raw);
|
|
833
|
+
}
|
|
834
|
+
|
|
835
|
+
class TelemetryCollector {
|
|
836
|
+
enabled;
|
|
837
|
+
now;
|
|
838
|
+
write;
|
|
839
|
+
sessionStartMs;
|
|
840
|
+
spans = [];
|
|
841
|
+
activeSpans = new Map;
|
|
842
|
+
nextId = 1;
|
|
843
|
+
flushed = false;
|
|
844
|
+
constructor(options = {}) {
|
|
845
|
+
this.enabled = isTelemetryEnabled(options.env);
|
|
846
|
+
this.now = options.now ?? (() => globalThis.performance.now());
|
|
847
|
+
this.write = options.write ?? ((text) => writeSync(process.stderr.fd, text));
|
|
848
|
+
this.sessionStartMs = this.now();
|
|
849
|
+
}
|
|
850
|
+
isEnabled() {
|
|
851
|
+
return this.enabled;
|
|
852
|
+
}
|
|
853
|
+
startSpan(name, attributes) {
|
|
854
|
+
if (!this.enabled)
|
|
855
|
+
return;
|
|
856
|
+
const span = {
|
|
857
|
+
id: this.nextId++,
|
|
858
|
+
name,
|
|
859
|
+
startMs: this.now(),
|
|
860
|
+
attributes: sanitiseAttributes(attributes)
|
|
861
|
+
};
|
|
862
|
+
this.spans.push(span);
|
|
863
|
+
this.activeSpans.set(span.id, span);
|
|
864
|
+
return { id: span.id };
|
|
865
|
+
}
|
|
866
|
+
endSpan(handle, attributes) {
|
|
867
|
+
if (!this.enabled || !handle)
|
|
868
|
+
return;
|
|
869
|
+
const span = this.activeSpans.get(handle.id);
|
|
870
|
+
if (!span || span.endMs !== undefined)
|
|
871
|
+
return;
|
|
872
|
+
span.endMs = this.now();
|
|
873
|
+
span.attributes = mergeAttributes(span.attributes, attributes);
|
|
874
|
+
this.activeSpans.delete(handle.id);
|
|
875
|
+
}
|
|
876
|
+
flush(exitCode = 0) {
|
|
877
|
+
if (!this.enabled || this.flushed)
|
|
878
|
+
return;
|
|
879
|
+
const nowMs = this.now();
|
|
880
|
+
for (const span of this.activeSpans.values()) {
|
|
881
|
+
if (span.endMs !== undefined)
|
|
882
|
+
continue;
|
|
883
|
+
span.endMs = nowMs;
|
|
884
|
+
span.endedAtExit = true;
|
|
885
|
+
}
|
|
886
|
+
this.activeSpans.clear();
|
|
887
|
+
this.write(formatTelemetryReport(this.spans, this.sessionStartMs, nowMs, exitCode));
|
|
888
|
+
this.flushed = true;
|
|
889
|
+
}
|
|
890
|
+
}
|
|
891
|
+
async function withTelemetrySpan(name, operation, attributes) {
|
|
892
|
+
const handle = telemetryCollector.startSpan(name, attributes);
|
|
893
|
+
try {
|
|
894
|
+
const result = await operation();
|
|
895
|
+
telemetryCollector.endSpan(handle);
|
|
896
|
+
return result;
|
|
897
|
+
} catch (error) {
|
|
898
|
+
telemetryCollector.endSpan(handle, { error: true });
|
|
899
|
+
throw error;
|
|
900
|
+
}
|
|
901
|
+
}
|
|
902
|
+
function withTelemetrySpanSync(name, operation, attributes) {
|
|
903
|
+
const handle = telemetryCollector.startSpan(name, attributes);
|
|
904
|
+
try {
|
|
905
|
+
const result = operation();
|
|
906
|
+
telemetryCollector.endSpan(handle);
|
|
907
|
+
return result;
|
|
908
|
+
} catch (error) {
|
|
909
|
+
telemetryCollector.endSpan(handle, { error: true });
|
|
910
|
+
throw error;
|
|
911
|
+
}
|
|
912
|
+
}
|
|
913
|
+
function startTelemetrySpan(name, attributes) {
|
|
914
|
+
return telemetryCollector.startSpan(name, attributes);
|
|
915
|
+
}
|
|
916
|
+
function endTelemetrySpan(handle, attributes) {
|
|
917
|
+
telemetryCollector.endSpan(handle, attributes);
|
|
918
|
+
}
|
|
919
|
+
function flushTelemetry(exitCode = 0) {
|
|
920
|
+
telemetryCollector.flush(exitCode);
|
|
921
|
+
}
|
|
922
|
+
var telemetryCollector = new TelemetryCollector;
|
|
923
|
+
function sanitiseAttributes(attributes) {
|
|
924
|
+
if (!attributes)
|
|
925
|
+
return;
|
|
926
|
+
const entries = Object.entries(attributes).filter(([, value]) => value !== undefined);
|
|
927
|
+
if (entries.length === 0)
|
|
928
|
+
return;
|
|
929
|
+
return Object.fromEntries(entries);
|
|
930
|
+
}
|
|
931
|
+
function mergeAttributes(initial, extra) {
|
|
932
|
+
if (!initial && !extra)
|
|
933
|
+
return;
|
|
934
|
+
return sanitiseAttributes({
|
|
935
|
+
...initial ?? {},
|
|
936
|
+
...extra ?? {}
|
|
937
|
+
});
|
|
938
|
+
}
|
|
939
|
+
function formatTelemetryReport(spans, sessionStartMs, sessionEndMs, exitCode) {
|
|
940
|
+
const lines = [
|
|
941
|
+
"[githits telemetry]",
|
|
942
|
+
`exit: ${exitCode}`,
|
|
943
|
+
`total: ${formatMs(sessionEndMs - sessionStartMs)}`
|
|
944
|
+
];
|
|
945
|
+
const orderedSpans = [...spans].sort((left, right) => {
|
|
946
|
+
if (left.startMs !== right.startMs) {
|
|
947
|
+
return left.startMs - right.startMs;
|
|
948
|
+
}
|
|
949
|
+
return left.id - right.id;
|
|
950
|
+
});
|
|
951
|
+
for (const span of orderedSpans) {
|
|
952
|
+
const endMs = span.endMs ?? sessionEndMs;
|
|
953
|
+
const details = [`start +${formatMs(span.startMs - sessionStartMs)}`];
|
|
954
|
+
if (span.endedAtExit) {
|
|
955
|
+
details.push("ended-at-exit");
|
|
956
|
+
}
|
|
957
|
+
const attrs = formatAttributes(span.attributes);
|
|
958
|
+
if (attrs) {
|
|
959
|
+
details.push(attrs);
|
|
960
|
+
}
|
|
961
|
+
lines.push(`- ${span.name}: ${formatMs(endMs - span.startMs)} (${details.join(", ")})`);
|
|
962
|
+
}
|
|
963
|
+
return `${lines.join(`
|
|
964
|
+
`)}
|
|
965
|
+
`;
|
|
966
|
+
}
|
|
967
|
+
function formatAttributes(attributes) {
|
|
968
|
+
if (!attributes)
|
|
969
|
+
return "";
|
|
970
|
+
return Object.entries(attributes).map(([key, value]) => `${key}=${String(value)}`).join(" ");
|
|
971
|
+
}
|
|
972
|
+
function formatMs(value) {
|
|
973
|
+
return `${value.toFixed(1)}ms`;
|
|
974
|
+
}
|
|
975
|
+
|
|
672
976
|
// src/services/githits-service.ts
|
|
673
977
|
class AuthenticationError extends Error {
|
|
674
978
|
constructor(message) {
|
|
@@ -697,47 +1001,54 @@ class GitHitsServiceImpl {
|
|
|
697
1001
|
this.token = token;
|
|
698
1002
|
}
|
|
699
1003
|
async search(params) {
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
1004
|
+
return withTelemetrySpan("githits.search.request", async () => {
|
|
1005
|
+
const response = await fetch(`${this.apiUrl}/search`, {
|
|
1006
|
+
method: "POST",
|
|
1007
|
+
headers: this.headers(),
|
|
1008
|
+
body: JSON.stringify({
|
|
1009
|
+
query: params.query,
|
|
1010
|
+
language: params.language,
|
|
1011
|
+
license_mode: params.licenseMode ?? "strict",
|
|
1012
|
+
include_explanation: params.includeExplanation ?? false
|
|
1013
|
+
})
|
|
1014
|
+
});
|
|
1015
|
+
if (!response.ok) {
|
|
1016
|
+
throw await this.createError(response);
|
|
1017
|
+
}
|
|
1018
|
+
return response.text();
|
|
709
1019
|
});
|
|
710
|
-
if (!response.ok) {
|
|
711
|
-
throw await this.createError(response);
|
|
712
|
-
}
|
|
713
|
-
return response.text();
|
|
714
1020
|
}
|
|
715
1021
|
async getLanguages() {
|
|
716
|
-
|
|
717
|
-
|
|
1022
|
+
return withTelemetrySpan("githits.languages.request", async () => {
|
|
1023
|
+
const response = await fetch(`${this.apiUrl}/languages`, {
|
|
1024
|
+
headers: this.headers()
|
|
1025
|
+
});
|
|
1026
|
+
if (!response.ok) {
|
|
1027
|
+
throw await this.createError(response);
|
|
1028
|
+
}
|
|
1029
|
+
return response.json();
|
|
718
1030
|
});
|
|
719
|
-
if (!response.ok) {
|
|
720
|
-
throw await this.createError(response);
|
|
721
|
-
}
|
|
722
|
-
return response.json();
|
|
723
1031
|
}
|
|
724
1032
|
async submitFeedback(params) {
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
1033
|
+
return withTelemetrySpan("githits.feedback.request", async () => {
|
|
1034
|
+
const response = await fetch(`${this.apiUrl}/feedbacks`, {
|
|
1035
|
+
method: "POST",
|
|
1036
|
+
headers: this.headers(),
|
|
1037
|
+
body: JSON.stringify({
|
|
1038
|
+
solution_id: params.solutionId,
|
|
1039
|
+
accepted: params.accepted,
|
|
1040
|
+
feedback_text: params.feedbackText ?? null
|
|
1041
|
+
})
|
|
1042
|
+
});
|
|
1043
|
+
if (!response.ok) {
|
|
1044
|
+
throw await this.createError(response);
|
|
1045
|
+
}
|
|
1046
|
+
return { success: true, message: "Feedback submitted successfully" };
|
|
733
1047
|
});
|
|
734
|
-
if (!response.ok) {
|
|
735
|
-
throw await this.createError(response);
|
|
736
|
-
}
|
|
737
|
-
return { success: true, message: "Feedback submitted successfully" };
|
|
738
1048
|
}
|
|
739
1049
|
headers() {
|
|
740
1050
|
return {
|
|
1051
|
+
...buildClientHeaders(),
|
|
741
1052
|
Authorization: `Bearer ${this.token}`,
|
|
742
1053
|
"Content-Type": "application/json",
|
|
743
1054
|
"User-Agent": `githits-cli/${version}`
|
|
@@ -962,7 +1273,7 @@ query SearchSymbols(
|
|
|
962
1273
|
hint
|
|
963
1274
|
}
|
|
964
1275
|
warning
|
|
965
|
-
|
|
1276
|
+
codeIndexState
|
|
966
1277
|
indexingRef
|
|
967
1278
|
availableVersions {
|
|
968
1279
|
version
|
|
@@ -1005,7 +1316,7 @@ var searchSymbolsResponseSchema = z.object({
|
|
|
1005
1316
|
hint: z.string().nullable().optional()
|
|
1006
1317
|
}).nullable().optional(),
|
|
1007
1318
|
warning: z.string().nullable().optional(),
|
|
1008
|
-
|
|
1319
|
+
codeIndexState: z.string(),
|
|
1009
1320
|
indexingRef: z.string().nullable().optional(),
|
|
1010
1321
|
availableVersions: z.array(availableVersionSchema).nullable().optional()
|
|
1011
1322
|
});
|
|
@@ -1036,7 +1347,7 @@ var listRepoFilesResponseSchema = z.object({
|
|
|
1036
1347
|
indexedVersion: z.string().nullable().optional(),
|
|
1037
1348
|
resolution: navigationResolutionSchema,
|
|
1038
1349
|
diagnostics: navigationDiagnosticsSchema,
|
|
1039
|
-
|
|
1350
|
+
codeIndexState: z.string(),
|
|
1040
1351
|
indexingRef: z.string().nullable().optional(),
|
|
1041
1352
|
availableVersions: z.array(availableVersionSchema).nullable().optional()
|
|
1042
1353
|
});
|
|
@@ -1086,7 +1397,7 @@ query ListRepoFiles(
|
|
|
1086
1397
|
diagnostics {
|
|
1087
1398
|
hint
|
|
1088
1399
|
}
|
|
1089
|
-
|
|
1400
|
+
codeIndexState
|
|
1090
1401
|
indexingRef
|
|
1091
1402
|
availableVersions {
|
|
1092
1403
|
version
|
|
@@ -1104,7 +1415,7 @@ var codeContextResponseSchema = z.object({
|
|
|
1104
1415
|
repoUrl: z.string().nullable().optional(),
|
|
1105
1416
|
gitRef: z.string().nullable().optional(),
|
|
1106
1417
|
isBinary: z.boolean().nullable().optional(),
|
|
1107
|
-
|
|
1418
|
+
codeIndexState: z.string(),
|
|
1108
1419
|
indexingRef: z.string().nullable().optional()
|
|
1109
1420
|
});
|
|
1110
1421
|
var fetchCodeContextGraphQLResponseSchema = z.object({
|
|
@@ -1145,7 +1456,7 @@ query FetchCodeContext(
|
|
|
1145
1456
|
repoUrl
|
|
1146
1457
|
gitRef
|
|
1147
1458
|
isBinary
|
|
1148
|
-
|
|
1459
|
+
codeIndexState
|
|
1149
1460
|
indexingRef
|
|
1150
1461
|
}
|
|
1151
1462
|
}`;
|
|
@@ -1165,7 +1476,7 @@ var grepRepoFileResponseSchema = z.object({
|
|
|
1165
1476
|
indexedVersion: z.string().nullable().optional(),
|
|
1166
1477
|
resolution: navigationResolutionSchema,
|
|
1167
1478
|
diagnostics: navigationDiagnosticsSchema,
|
|
1168
|
-
|
|
1479
|
+
codeIndexState: z.string(),
|
|
1169
1480
|
indexingRef: z.string().nullable().optional(),
|
|
1170
1481
|
availableVersions: z.array(availableVersionSchema).nullable().optional()
|
|
1171
1482
|
});
|
|
@@ -1221,7 +1532,7 @@ query GrepRepoFile(
|
|
|
1221
1532
|
diagnostics {
|
|
1222
1533
|
hint
|
|
1223
1534
|
}
|
|
1224
|
-
|
|
1535
|
+
codeIndexState
|
|
1225
1536
|
indexingRef
|
|
1226
1537
|
availableVersions {
|
|
1227
1538
|
version
|
|
@@ -1301,13 +1612,13 @@ class CodeNavigationServiceImpl {
|
|
|
1301
1612
|
if (!data) {
|
|
1302
1613
|
throw new MalformedCodeNavigationResponseError("Malformed response from code navigation service.");
|
|
1303
1614
|
}
|
|
1304
|
-
if (data.
|
|
1615
|
+
if (data.codeIndexState === "INDEXING") {
|
|
1305
1616
|
throw new CodeNavigationIndexingError(this.createIndexingMessage(data.indexingRef ?? undefined), data.indexingRef ?? undefined, data.availableVersions?.map((entry) => ({
|
|
1306
1617
|
version: entry.version ?? undefined,
|
|
1307
1618
|
ref: entry.ref
|
|
1308
1619
|
})));
|
|
1309
1620
|
}
|
|
1310
|
-
if (data.
|
|
1621
|
+
if (data.codeIndexState === "UNRESOLVABLE") {
|
|
1311
1622
|
throw new CodeNavigationUnresolvableError("The requested target or version could not be resolved.");
|
|
1312
1623
|
}
|
|
1313
1624
|
return {
|
|
@@ -1410,7 +1721,7 @@ class CodeNavigationServiceImpl {
|
|
|
1410
1721
|
return base;
|
|
1411
1722
|
}
|
|
1412
1723
|
throwIfIndexing(data) {
|
|
1413
|
-
if (data.
|
|
1724
|
+
if (data.codeIndexState === "INDEXING") {
|
|
1414
1725
|
throw new CodeNavigationIndexingError(this.createIndexingMessage(data.indexingRef ?? undefined), data.indexingRef ?? undefined, data.availableVersions?.map((entry) => ({
|
|
1415
1726
|
version: entry.version ?? undefined,
|
|
1416
1727
|
ref: entry.ref
|
|
@@ -1534,7 +1845,7 @@ class CodeNavigationServiceImpl {
|
|
|
1534
1845
|
throw new MalformedCodeNavigationResponseError("Malformed response from code navigation service.");
|
|
1535
1846
|
}
|
|
1536
1847
|
this.throwIfIndexing({
|
|
1537
|
-
|
|
1848
|
+
codeIndexState: data.codeIndexState,
|
|
1538
1849
|
indexingRef: data.indexingRef
|
|
1539
1850
|
});
|
|
1540
1851
|
return {
|
|
@@ -1936,33 +2247,64 @@ class KeyringServiceImpl {
|
|
|
1936
2247
|
class MigratingAuthStorage {
|
|
1937
2248
|
primary;
|
|
1938
2249
|
legacy;
|
|
1939
|
-
|
|
2250
|
+
onPrimaryUnavailable;
|
|
2251
|
+
primaryAvailable = true;
|
|
2252
|
+
warnedOnPrimaryFailure = false;
|
|
2253
|
+
constructor(primary, legacy, onPrimaryUnavailable = () => {}) {
|
|
1940
2254
|
this.primary = primary;
|
|
1941
2255
|
this.legacy = legacy;
|
|
2256
|
+
this.onPrimaryUnavailable = onPrimaryUnavailable;
|
|
1942
2257
|
}
|
|
1943
2258
|
async loadTokens(baseUrl2) {
|
|
1944
|
-
|
|
1945
|
-
|
|
1946
|
-
|
|
2259
|
+
if (this.primaryAvailable) {
|
|
2260
|
+
try {
|
|
2261
|
+
const tokens = await this.primary.loadTokens(baseUrl2);
|
|
2262
|
+
if (tokens)
|
|
2263
|
+
return tokens;
|
|
2264
|
+
} catch (error) {
|
|
2265
|
+
if (!this.handlePrimaryFailure(error))
|
|
2266
|
+
throw error;
|
|
2267
|
+
}
|
|
2268
|
+
}
|
|
1947
2269
|
const legacyTokens = await this.legacy.loadTokens(baseUrl2);
|
|
1948
|
-
if (legacyTokens)
|
|
2270
|
+
if (!legacyTokens)
|
|
2271
|
+
return null;
|
|
2272
|
+
if (!this.primaryAvailable)
|
|
2273
|
+
return legacyTokens;
|
|
2274
|
+
try {
|
|
1949
2275
|
await this.primary.saveTokens(baseUrl2, legacyTokens);
|
|
1950
|
-
|
|
1951
|
-
|
|
1952
|
-
|
|
2276
|
+
} catch (error) {
|
|
2277
|
+
if (!this.handlePrimaryFailure(error))
|
|
2278
|
+
throw error;
|
|
1953
2279
|
return legacyTokens;
|
|
1954
2280
|
}
|
|
1955
|
-
|
|
2281
|
+
try {
|
|
2282
|
+
await this.legacy.clearTokens(baseUrl2);
|
|
2283
|
+
} catch {}
|
|
2284
|
+
return legacyTokens;
|
|
1956
2285
|
}
|
|
1957
2286
|
async saveTokens(baseUrl2, data) {
|
|
1958
|
-
|
|
2287
|
+
if (this.primaryAvailable) {
|
|
2288
|
+
try {
|
|
2289
|
+
await this.primary.saveTokens(baseUrl2, data);
|
|
2290
|
+
return;
|
|
2291
|
+
} catch (error) {
|
|
2292
|
+
if (!this.handlePrimaryFailure(error))
|
|
2293
|
+
throw error;
|
|
2294
|
+
}
|
|
2295
|
+
}
|
|
2296
|
+
await this.legacy.saveTokens(baseUrl2, data);
|
|
1959
2297
|
}
|
|
1960
2298
|
async clearTokens(baseUrl2) {
|
|
1961
2299
|
let primaryError;
|
|
1962
|
-
|
|
1963
|
-
|
|
1964
|
-
|
|
1965
|
-
|
|
2300
|
+
if (this.primaryAvailable) {
|
|
2301
|
+
try {
|
|
2302
|
+
await this.primary.clearTokens(baseUrl2);
|
|
2303
|
+
} catch (error) {
|
|
2304
|
+
if (!this.handlePrimaryFailure(error)) {
|
|
2305
|
+
primaryError = error;
|
|
2306
|
+
}
|
|
2307
|
+
}
|
|
1966
2308
|
}
|
|
1967
2309
|
try {
|
|
1968
2310
|
await this.legacy.clearTokens(baseUrl2);
|
|
@@ -1971,28 +2313,55 @@ class MigratingAuthStorage {
|
|
|
1971
2313
|
throw primaryError;
|
|
1972
2314
|
}
|
|
1973
2315
|
async loadClient(baseUrl2) {
|
|
1974
|
-
|
|
1975
|
-
|
|
1976
|
-
|
|
2316
|
+
if (this.primaryAvailable) {
|
|
2317
|
+
try {
|
|
2318
|
+
const client = await this.primary.loadClient(baseUrl2);
|
|
2319
|
+
if (client)
|
|
2320
|
+
return client;
|
|
2321
|
+
} catch (error) {
|
|
2322
|
+
if (!this.handlePrimaryFailure(error))
|
|
2323
|
+
throw error;
|
|
2324
|
+
}
|
|
2325
|
+
}
|
|
1977
2326
|
const legacyClient = await this.legacy.loadClient(baseUrl2);
|
|
1978
|
-
if (legacyClient)
|
|
2327
|
+
if (!legacyClient)
|
|
2328
|
+
return null;
|
|
2329
|
+
if (!this.primaryAvailable)
|
|
2330
|
+
return legacyClient;
|
|
2331
|
+
try {
|
|
1979
2332
|
await this.primary.saveClient(baseUrl2, legacyClient);
|
|
1980
|
-
|
|
1981
|
-
|
|
1982
|
-
|
|
2333
|
+
} catch (error) {
|
|
2334
|
+
if (!this.handlePrimaryFailure(error))
|
|
2335
|
+
throw error;
|
|
1983
2336
|
return legacyClient;
|
|
1984
2337
|
}
|
|
1985
|
-
|
|
2338
|
+
try {
|
|
2339
|
+
await this.legacy.clearClient(baseUrl2);
|
|
2340
|
+
} catch {}
|
|
2341
|
+
return legacyClient;
|
|
1986
2342
|
}
|
|
1987
2343
|
async saveClient(baseUrl2, data) {
|
|
1988
|
-
|
|
2344
|
+
if (this.primaryAvailable) {
|
|
2345
|
+
try {
|
|
2346
|
+
await this.primary.saveClient(baseUrl2, data);
|
|
2347
|
+
return;
|
|
2348
|
+
} catch (error) {
|
|
2349
|
+
if (!this.handlePrimaryFailure(error))
|
|
2350
|
+
throw error;
|
|
2351
|
+
}
|
|
2352
|
+
}
|
|
2353
|
+
await this.legacy.saveClient(baseUrl2, data);
|
|
1989
2354
|
}
|
|
1990
2355
|
async clearClient(baseUrl2) {
|
|
1991
2356
|
let primaryError;
|
|
1992
|
-
|
|
1993
|
-
|
|
1994
|
-
|
|
1995
|
-
|
|
2357
|
+
if (this.primaryAvailable) {
|
|
2358
|
+
try {
|
|
2359
|
+
await this.primary.clearClient(baseUrl2);
|
|
2360
|
+
} catch (error) {
|
|
2361
|
+
if (!this.handlePrimaryFailure(error)) {
|
|
2362
|
+
primaryError = error;
|
|
2363
|
+
}
|
|
2364
|
+
}
|
|
1996
2365
|
}
|
|
1997
2366
|
try {
|
|
1998
2367
|
await this.legacy.clearClient(baseUrl2);
|
|
@@ -2001,7 +2370,18 @@ class MigratingAuthStorage {
|
|
|
2001
2370
|
throw primaryError;
|
|
2002
2371
|
}
|
|
2003
2372
|
getStorageLocation() {
|
|
2004
|
-
return this.primary.getStorageLocation();
|
|
2373
|
+
return this.primaryAvailable ? this.primary.getStorageLocation() : this.legacy.getStorageLocation();
|
|
2374
|
+
}
|
|
2375
|
+
handlePrimaryFailure(error) {
|
|
2376
|
+
if (!(error instanceof KeychainUnavailableError)) {
|
|
2377
|
+
return false;
|
|
2378
|
+
}
|
|
2379
|
+
this.primaryAvailable = false;
|
|
2380
|
+
if (!this.warnedOnPrimaryFailure) {
|
|
2381
|
+
this.warnedOnPrimaryFailure = true;
|
|
2382
|
+
this.onPrimaryUnavailable(error);
|
|
2383
|
+
}
|
|
2384
|
+
return true;
|
|
2005
2385
|
}
|
|
2006
2386
|
}
|
|
2007
2387
|
// src/services/package-intelligence-service.ts
|
|
@@ -2302,13 +2682,50 @@ var directDependencySchema = z2.object({
|
|
|
2302
2682
|
versionConstraint: z2.string().nullable().optional(),
|
|
2303
2683
|
type: z2.string().nullable().optional()
|
|
2304
2684
|
});
|
|
2685
|
+
var dependencyGraphNodeSchema = z2.object({
|
|
2686
|
+
registry: z2.string(),
|
|
2687
|
+
name: z2.string(),
|
|
2688
|
+
version: z2.string().nullable().optional()
|
|
2689
|
+
});
|
|
2690
|
+
var dependencyGraphEdgeSchema = z2.object({
|
|
2691
|
+
fromIndex: z2.number().int().nullable().optional(),
|
|
2692
|
+
toIndex: z2.number().int(),
|
|
2693
|
+
constraint: z2.string().nullable().optional(),
|
|
2694
|
+
dependencyType: z2.string().nullable().optional()
|
|
2695
|
+
});
|
|
2696
|
+
var dependencyGraphSchema = z2.object({
|
|
2697
|
+
formatVersion: z2.number().int(),
|
|
2698
|
+
nodes: z2.array(dependencyGraphNodeSchema),
|
|
2699
|
+
edges: z2.array(dependencyGraphEdgeSchema)
|
|
2700
|
+
});
|
|
2701
|
+
var dependencyConflictEdgeSchema = z2.object({
|
|
2702
|
+
fromIndex: z2.number().int().nullable().optional(),
|
|
2703
|
+
toIndex: z2.number().int(),
|
|
2704
|
+
versionConstraint: z2.string(),
|
|
2705
|
+
dependencyType: z2.string()
|
|
2706
|
+
});
|
|
2707
|
+
var dependencyConflictSchema = z2.object({
|
|
2708
|
+
packageName: z2.string(),
|
|
2709
|
+
requiredVersions: z2.array(z2.string()),
|
|
2710
|
+
conflictingEdges: z2.array(dependencyConflictEdgeSchema)
|
|
2711
|
+
});
|
|
2712
|
+
var circularDependencyCycleSchema = z2.object({
|
|
2713
|
+
cycleStart: z2.string(),
|
|
2714
|
+
circularPath: z2.array(z2.string()),
|
|
2715
|
+
displayChain: z2.string()
|
|
2716
|
+
});
|
|
2717
|
+
var environmentMarkerSchema = z2.object({
|
|
2718
|
+
type: z2.string().nullable().optional(),
|
|
2719
|
+
value: z2.string().nullable().optional(),
|
|
2720
|
+
raw: z2.string().nullable().optional()
|
|
2721
|
+
});
|
|
2305
2722
|
var transitiveDependencySchema = z2.object({
|
|
2306
2723
|
totalEdges: z2.number().int().nullable().optional(),
|
|
2307
2724
|
uniquePackagesCount: z2.number().int().nullable().optional(),
|
|
2308
2725
|
uniqueDependencies: z2.array(z2.string()).nullable().optional(),
|
|
2309
|
-
|
|
2310
|
-
|
|
2311
|
-
|
|
2726
|
+
dependencyConflicts: z2.array(dependencyConflictSchema).nullable().optional(),
|
|
2727
|
+
circularDependencyCycles: z2.array(circularDependencyCycleSchema).nullable().optional(),
|
|
2728
|
+
dependencyGraph: dependencyGraphSchema.nullable().optional()
|
|
2312
2729
|
}).nullable().optional();
|
|
2313
2730
|
var dependencyBundleSchema = z2.object({
|
|
2314
2731
|
direct: z2.array(directDependencySchema).nullable().optional(),
|
|
@@ -2332,7 +2749,7 @@ var dependencyGroupSchema = z2.object({
|
|
|
2332
2749
|
});
|
|
2333
2750
|
var dependencyGroupsInfoSchema = z2.object({
|
|
2334
2751
|
primaryGroup: z2.string().nullable().optional(),
|
|
2335
|
-
|
|
2752
|
+
environmentMarkers: z2.array(environmentMarkerSchema).nullable().optional(),
|
|
2336
2753
|
groups: z2.array(dependencyGroupSchema)
|
|
2337
2754
|
}).nullable().optional();
|
|
2338
2755
|
var dependencyReportResponseSchema = z2.object({
|
|
@@ -2382,14 +2799,44 @@ query PackageDependencies(
|
|
|
2382
2799
|
totalEdges
|
|
2383
2800
|
uniquePackagesCount
|
|
2384
2801
|
uniqueDependencies
|
|
2385
|
-
|
|
2386
|
-
|
|
2387
|
-
|
|
2802
|
+
dependencyConflicts {
|
|
2803
|
+
packageName
|
|
2804
|
+
requiredVersions
|
|
2805
|
+
conflictingEdges {
|
|
2806
|
+
fromIndex
|
|
2807
|
+
toIndex
|
|
2808
|
+
versionConstraint
|
|
2809
|
+
dependencyType
|
|
2810
|
+
}
|
|
2811
|
+
}
|
|
2812
|
+
circularDependencyCycles {
|
|
2813
|
+
cycleStart
|
|
2814
|
+
circularPath
|
|
2815
|
+
displayChain
|
|
2816
|
+
}
|
|
2817
|
+
dependencyGraph {
|
|
2818
|
+
formatVersion
|
|
2819
|
+
nodes {
|
|
2820
|
+
registry
|
|
2821
|
+
name
|
|
2822
|
+
version
|
|
2823
|
+
}
|
|
2824
|
+
edges {
|
|
2825
|
+
fromIndex
|
|
2826
|
+
toIndex
|
|
2827
|
+
constraint
|
|
2828
|
+
dependencyType
|
|
2829
|
+
}
|
|
2830
|
+
}
|
|
2388
2831
|
}
|
|
2389
2832
|
}
|
|
2390
2833
|
dependencyGroups {
|
|
2391
2834
|
primaryGroup
|
|
2392
|
-
|
|
2835
|
+
environmentMarkers {
|
|
2836
|
+
type
|
|
2837
|
+
value
|
|
2838
|
+
raw
|
|
2839
|
+
}
|
|
2393
2840
|
groups {
|
|
2394
2841
|
name
|
|
2395
2842
|
lifecycle
|
|
@@ -2484,12 +2931,12 @@ class PackageIntelligenceServiceImpl {
|
|
|
2484
2931
|
this.fetchFn = fetchFn;
|
|
2485
2932
|
}
|
|
2486
2933
|
async packageSummary(params) {
|
|
2487
|
-
return executeWithTokenRefresh({
|
|
2934
|
+
return withTelemetrySpan("pkg-intel.summary.request", () => executeWithTokenRefresh({
|
|
2488
2935
|
getToken: () => this.tokenProvider.getToken(),
|
|
2489
2936
|
forceRefresh: () => this.tokenProvider.forceRefresh(),
|
|
2490
2937
|
shouldRefresh: (error) => error instanceof AuthenticationError,
|
|
2491
2938
|
executeWithToken: (token) => this.executePackageSummary(token, params)
|
|
2492
|
-
});
|
|
2939
|
+
}));
|
|
2493
2940
|
}
|
|
2494
2941
|
async executePackageSummary(token, params) {
|
|
2495
2942
|
let response;
|
|
@@ -2627,12 +3074,12 @@ class PackageIntelligenceServiceImpl {
|
|
|
2627
3074
|
};
|
|
2628
3075
|
}
|
|
2629
3076
|
async packageVulnerabilities(params) {
|
|
2630
|
-
return executeWithTokenRefresh({
|
|
3077
|
+
return withTelemetrySpan("pkg-intel.vulnerabilities.request", () => executeWithTokenRefresh({
|
|
2631
3078
|
getToken: () => this.tokenProvider.getToken(),
|
|
2632
3079
|
forceRefresh: () => this.tokenProvider.forceRefresh(),
|
|
2633
3080
|
shouldRefresh: (error) => error instanceof AuthenticationError,
|
|
2634
3081
|
executeWithToken: (token) => this.executePackageVulnerabilities(token, params)
|
|
2635
|
-
});
|
|
3082
|
+
}));
|
|
2636
3083
|
}
|
|
2637
3084
|
async executePackageVulnerabilities(token, params) {
|
|
2638
3085
|
let response;
|
|
@@ -2707,12 +3154,12 @@ class PackageIntelligenceServiceImpl {
|
|
|
2707
3154
|
};
|
|
2708
3155
|
}
|
|
2709
3156
|
async packageDependencies(params) {
|
|
2710
|
-
return executeWithTokenRefresh({
|
|
3157
|
+
return withTelemetrySpan("pkg-intel.dependencies.request", () => executeWithTokenRefresh({
|
|
2711
3158
|
getToken: () => this.tokenProvider.getToken(),
|
|
2712
3159
|
forceRefresh: () => this.tokenProvider.forceRefresh(),
|
|
2713
3160
|
shouldRefresh: (error) => error instanceof AuthenticationError,
|
|
2714
3161
|
executeWithToken: (token) => this.executePackageDependencies(token, params)
|
|
2715
|
-
});
|
|
3162
|
+
}));
|
|
2716
3163
|
}
|
|
2717
3164
|
async executePackageDependencies(token, params) {
|
|
2718
3165
|
let response;
|
|
@@ -2780,14 +3227,44 @@ class PackageIntelligenceServiceImpl {
|
|
|
2780
3227
|
totalEdges: bundle.transitive.totalEdges ?? undefined,
|
|
2781
3228
|
uniquePackagesCount: bundle.transitive.uniquePackagesCount ?? undefined,
|
|
2782
3229
|
uniqueDependencies: bundle.transitive.uniqueDependencies ?? undefined,
|
|
2783
|
-
|
|
2784
|
-
|
|
2785
|
-
|
|
3230
|
+
dependencyConflicts: bundle.transitive.dependencyConflicts?.map((c) => ({
|
|
3231
|
+
packageName: c.packageName,
|
|
3232
|
+
requiredVersions: c.requiredVersions,
|
|
3233
|
+
conflictingEdges: c.conflictingEdges.map((edge) => ({
|
|
3234
|
+
fromIndex: edge.fromIndex ?? undefined,
|
|
3235
|
+
toIndex: edge.toIndex,
|
|
3236
|
+
versionConstraint: edge.versionConstraint,
|
|
3237
|
+
dependencyType: edge.dependencyType
|
|
3238
|
+
}))
|
|
3239
|
+
})) ?? undefined,
|
|
3240
|
+
circularDependencyCycles: bundle.transitive.circularDependencyCycles?.map((cycle) => ({
|
|
3241
|
+
cycleStart: cycle.cycleStart,
|
|
3242
|
+
circularPath: cycle.circularPath,
|
|
3243
|
+
displayChain: cycle.displayChain
|
|
3244
|
+
})) ?? undefined,
|
|
3245
|
+
dependencyGraph: bundle.transitive.dependencyGraph ? {
|
|
3246
|
+
formatVersion: bundle.transitive.dependencyGraph.formatVersion,
|
|
3247
|
+
nodes: bundle.transitive.dependencyGraph.nodes.map((n) => ({
|
|
3248
|
+
registry: n.registry,
|
|
3249
|
+
name: n.name,
|
|
3250
|
+
version: n.version ?? undefined
|
|
3251
|
+
})),
|
|
3252
|
+
edges: bundle.transitive.dependencyGraph.edges.map((e) => ({
|
|
3253
|
+
fromIndex: e.fromIndex ?? undefined,
|
|
3254
|
+
toIndex: e.toIndex,
|
|
3255
|
+
constraint: e.constraint ?? undefined,
|
|
3256
|
+
dependencyType: e.dependencyType ?? undefined
|
|
3257
|
+
}))
|
|
3258
|
+
} : undefined
|
|
2786
3259
|
} : undefined
|
|
2787
3260
|
} : undefined;
|
|
2788
3261
|
const dependencyGroups = data.dependencyGroups ? {
|
|
2789
3262
|
primaryGroup: data.dependencyGroups.primaryGroup ?? undefined,
|
|
2790
|
-
|
|
3263
|
+
environmentMarkers: data.dependencyGroups.environmentMarkers?.map((m) => ({
|
|
3264
|
+
type: m.type ?? undefined,
|
|
3265
|
+
value: m.value ?? undefined,
|
|
3266
|
+
raw: m.raw ?? undefined
|
|
3267
|
+
})) ?? undefined,
|
|
2791
3268
|
groups: data.dependencyGroups.groups.map((group) => ({
|
|
2792
3269
|
name: group.name,
|
|
2793
3270
|
lifecycle: group.lifecycle,
|
|
@@ -2811,12 +3288,12 @@ class PackageIntelligenceServiceImpl {
|
|
|
2811
3288
|
};
|
|
2812
3289
|
}
|
|
2813
3290
|
async packageChangelog(params) {
|
|
2814
|
-
return executeWithTokenRefresh({
|
|
3291
|
+
return withTelemetrySpan("pkg-intel.changelog.request", () => executeWithTokenRefresh({
|
|
2815
3292
|
getToken: () => this.tokenProvider.getToken(),
|
|
2816
3293
|
forceRefresh: () => this.tokenProvider.forceRefresh(),
|
|
2817
3294
|
shouldRefresh: (error) => error instanceof AuthenticationError,
|
|
2818
3295
|
executeWithToken: (token) => this.executePackageChangelog(token, params)
|
|
2819
|
-
});
|
|
3296
|
+
}));
|
|
2820
3297
|
}
|
|
2821
3298
|
async executePackageChangelog(token, params) {
|
|
2822
3299
|
let response;
|
|
@@ -3010,27 +3487,29 @@ class TokenManager {
|
|
|
3010
3487
|
this.mcpUrl = deps.mcpUrl;
|
|
3011
3488
|
}
|
|
3012
3489
|
async getToken() {
|
|
3013
|
-
|
|
3014
|
-
|
|
3015
|
-
|
|
3016
|
-
|
|
3017
|
-
|
|
3018
|
-
|
|
3019
|
-
|
|
3020
|
-
|
|
3021
|
-
|
|
3022
|
-
|
|
3023
|
-
|
|
3024
|
-
|
|
3025
|
-
|
|
3026
|
-
|
|
3027
|
-
|
|
3028
|
-
|
|
3029
|
-
|
|
3030
|
-
|
|
3490
|
+
return withTelemetrySpan("token-manager.get-token", async () => {
|
|
3491
|
+
if (!this.cachedToken) {
|
|
3492
|
+
this.cachedToken = await withTelemetrySpan("token-manager.load-tokens", () => this.authStorage.loadTokens(this.mcpUrl));
|
|
3493
|
+
if (!this.cachedToken)
|
|
3494
|
+
return;
|
|
3495
|
+
}
|
|
3496
|
+
const currentToken = this.cachedToken.accessToken;
|
|
3497
|
+
const { expired, shouldRefresh } = shouldRefreshToken(this.cachedToken, PROACTIVE_REFRESH_RATIO, new Date);
|
|
3498
|
+
if (!shouldRefresh) {
|
|
3499
|
+
return currentToken;
|
|
3500
|
+
}
|
|
3501
|
+
const refreshedToken = await this.doRefresh();
|
|
3502
|
+
if (refreshedToken) {
|
|
3503
|
+
return refreshedToken;
|
|
3504
|
+
}
|
|
3505
|
+
if (!expired) {
|
|
3506
|
+
return currentToken;
|
|
3507
|
+
}
|
|
3508
|
+
return;
|
|
3509
|
+
});
|
|
3031
3510
|
}
|
|
3032
3511
|
async forceRefresh() {
|
|
3033
|
-
return this.doRefresh();
|
|
3512
|
+
return withTelemetrySpan("token-manager.force-refresh", () => this.doRefresh());
|
|
3034
3513
|
}
|
|
3035
3514
|
async doRefresh() {
|
|
3036
3515
|
if (this.refreshPromise) {
|
|
@@ -3044,59 +3523,55 @@ class TokenManager {
|
|
|
3044
3523
|
}
|
|
3045
3524
|
}
|
|
3046
3525
|
async executeRefresh() {
|
|
3047
|
-
|
|
3048
|
-
|
|
3049
|
-
|
|
3050
|
-
|
|
3051
|
-
|
|
3052
|
-
|
|
3053
|
-
|
|
3054
|
-
|
|
3055
|
-
|
|
3056
|
-
|
|
3057
|
-
|
|
3058
|
-
|
|
3059
|
-
|
|
3060
|
-
|
|
3061
|
-
|
|
3062
|
-
|
|
3063
|
-
|
|
3064
|
-
|
|
3065
|
-
|
|
3066
|
-
|
|
3526
|
+
return withTelemetrySpan("token-manager.refresh", async () => {
|
|
3527
|
+
const tokens = this.cachedToken ?? await withTelemetrySpan("token-manager.load-tokens", () => this.authStorage.loadTokens(this.mcpUrl));
|
|
3528
|
+
if (!tokens)
|
|
3529
|
+
return;
|
|
3530
|
+
const client = await withTelemetrySpan("token-manager.load-client", () => this.authStorage.loadClient(this.mcpUrl));
|
|
3531
|
+
if (!client)
|
|
3532
|
+
return;
|
|
3533
|
+
let response;
|
|
3534
|
+
try {
|
|
3535
|
+
const metadata = await withTelemetrySpan("token-manager.discover-endpoints", () => this.authService.discoverEndpoints(this.mcpUrl));
|
|
3536
|
+
response = await withTelemetrySpan("token-manager.refresh-access-token", () => this.authService.refreshAccessToken({
|
|
3537
|
+
tokenEndpoint: metadata.tokenEndpoint,
|
|
3538
|
+
clientId: client.clientId,
|
|
3539
|
+
clientSecret: client.clientSecret,
|
|
3540
|
+
refreshToken: tokens.refreshToken
|
|
3541
|
+
}));
|
|
3542
|
+
} catch {
|
|
3543
|
+
const isExpired = tokens.expiresAt ? new Date >= new Date(tokens.expiresAt) : false;
|
|
3544
|
+
if (isExpired) {
|
|
3545
|
+
this.cachedToken = null;
|
|
3546
|
+
await withTelemetrySpan("token-manager.clear-tokens", () => this.authStorage.clearTokens(this.mcpUrl));
|
|
3547
|
+
}
|
|
3548
|
+
return;
|
|
3067
3549
|
}
|
|
3068
|
-
|
|
3069
|
-
|
|
3070
|
-
|
|
3071
|
-
|
|
3072
|
-
|
|
3073
|
-
|
|
3074
|
-
|
|
3075
|
-
|
|
3076
|
-
|
|
3077
|
-
|
|
3078
|
-
return response.accessToken;
|
|
3550
|
+
const newTokenData = {
|
|
3551
|
+
accessToken: response.accessToken,
|
|
3552
|
+
refreshToken: response.refreshToken,
|
|
3553
|
+
expiresAt: new Date(Date.now() + response.expiresIn * 1000).toISOString(),
|
|
3554
|
+
createdAt: new Date().toISOString()
|
|
3555
|
+
};
|
|
3556
|
+
await withTelemetrySpan("token-manager.save-tokens", () => this.authStorage.saveTokens(this.mcpUrl, newTokenData));
|
|
3557
|
+
this.cachedToken = newTokenData;
|
|
3558
|
+
return response.accessToken;
|
|
3559
|
+
});
|
|
3079
3560
|
}
|
|
3080
3561
|
}
|
|
3081
3562
|
// src/container.ts
|
|
3082
3563
|
function createAuthStorage(fileSystemService) {
|
|
3083
|
-
|
|
3084
|
-
|
|
3564
|
+
return withTelemetrySpanSync("container.create-auth-storage", () => {
|
|
3565
|
+
const fileStorage = new AuthStorageImpl(fileSystemService);
|
|
3085
3566
|
const rawKeyring = new KeyringServiceImpl;
|
|
3086
3567
|
const keyring = process.platform === "win32" ? new ChunkingKeyringService(rawKeyring, WINDOWS_MAX_ENTRY_SIZE) : rawKeyring;
|
|
3087
|
-
const probeKey = `__probe_${Date.now()}_${Math.random().toString(36).slice(2, 8)}`;
|
|
3088
|
-
keyring.setPassword("githits", probeKey, "probe");
|
|
3089
|
-
try {
|
|
3090
|
-
keyring.deletePassword("githits", probeKey);
|
|
3091
|
-
} catch {}
|
|
3092
3568
|
const keychainStorage = new KeychainAuthStorage(keyring);
|
|
3093
|
-
return new MigratingAuthStorage(keychainStorage, fileStorage)
|
|
3094
|
-
|
|
3095
|
-
|
|
3096
|
-
|
|
3097
|
-
|
|
3098
|
-
|
|
3099
|
-
}
|
|
3569
|
+
return new MigratingAuthStorage(keychainStorage, fileStorage, (error) => {
|
|
3570
|
+
if (!(error instanceof KeychainUnavailableError))
|
|
3571
|
+
return;
|
|
3572
|
+
console.error("Warning: System keychain unavailable. Falling back to file-based credential storage.");
|
|
3573
|
+
});
|
|
3574
|
+
});
|
|
3100
3575
|
}
|
|
3101
3576
|
function createStaticTokenProvider(token) {
|
|
3102
3577
|
return {
|
|
@@ -3107,19 +3582,42 @@ function createStaticTokenProvider(token) {
|
|
|
3107
3582
|
};
|
|
3108
3583
|
}
|
|
3109
3584
|
async function createContainer() {
|
|
3110
|
-
|
|
3111
|
-
|
|
3112
|
-
|
|
3113
|
-
|
|
3114
|
-
|
|
3115
|
-
|
|
3116
|
-
|
|
3117
|
-
|
|
3118
|
-
|
|
3119
|
-
|
|
3120
|
-
|
|
3121
|
-
|
|
3122
|
-
|
|
3585
|
+
return withTelemetrySpan("container.create", async () => {
|
|
3586
|
+
const mcpUrl = getMcpUrl();
|
|
3587
|
+
const apiUrl = getApiUrl();
|
|
3588
|
+
const codeNavigationUrl = getCodeNavigationUrl();
|
|
3589
|
+
const codeNavigationCliOverrideEnabled = isCodeNavigationCliOverrideEnabled();
|
|
3590
|
+
const fileSystemService = new FileSystemServiceImpl;
|
|
3591
|
+
const authStorage = createAuthStorage(fileSystemService);
|
|
3592
|
+
const authService = new AuthServiceImpl;
|
|
3593
|
+
const browserService = new BrowserServiceImpl;
|
|
3594
|
+
const envToken = getEnvApiToken();
|
|
3595
|
+
if (envToken) {
|
|
3596
|
+
const tokenProvider = createStaticTokenProvider(envToken);
|
|
3597
|
+
const codeNavigationService2 = codeNavigationUrl ? new CodeNavigationServiceImpl(codeNavigationUrl, tokenProvider) : undefined;
|
|
3598
|
+
const packageIntelligenceService2 = codeNavigationUrl ? new PackageIntelligenceServiceImpl(codeNavigationUrl, tokenProvider) : undefined;
|
|
3599
|
+
return {
|
|
3600
|
+
authStorage,
|
|
3601
|
+
authService,
|
|
3602
|
+
browserService,
|
|
3603
|
+
fileSystemService,
|
|
3604
|
+
mcpUrl,
|
|
3605
|
+
apiUrl,
|
|
3606
|
+
apiToken: envToken,
|
|
3607
|
+
hasValidToken: true,
|
|
3608
|
+
envApiToken: envToken,
|
|
3609
|
+
codeNavigationCapability: getCodeNavigationCapability(envToken),
|
|
3610
|
+
codeNavigationCliOverrideEnabled,
|
|
3611
|
+
codeNavigationUrl,
|
|
3612
|
+
codeNavigationService: codeNavigationService2,
|
|
3613
|
+
packageIntelligenceService: packageIntelligenceService2,
|
|
3614
|
+
githitsService: new GitHitsServiceImpl(apiUrl, envToken)
|
|
3615
|
+
};
|
|
3616
|
+
}
|
|
3617
|
+
const tokenManager = new TokenManager({ authService, authStorage, mcpUrl });
|
|
3618
|
+
const apiToken = await withTelemetrySpan("container.token.get", () => tokenManager.getToken());
|
|
3619
|
+
const codeNavigationService = codeNavigationUrl ? new CodeNavigationServiceImpl(codeNavigationUrl, tokenManager) : undefined;
|
|
3620
|
+
const packageIntelligenceService = codeNavigationUrl ? new PackageIntelligenceServiceImpl(codeNavigationUrl, tokenManager) : undefined;
|
|
3123
3621
|
return {
|
|
3124
3622
|
authStorage,
|
|
3125
3623
|
authService,
|
|
@@ -3127,73 +3625,56 @@ async function createContainer() {
|
|
|
3127
3625
|
fileSystemService,
|
|
3128
3626
|
mcpUrl,
|
|
3129
3627
|
apiUrl,
|
|
3130
|
-
apiToken
|
|
3131
|
-
hasValidToken:
|
|
3132
|
-
envApiToken:
|
|
3133
|
-
codeNavigationCapability: getCodeNavigationCapability(
|
|
3628
|
+
apiToken,
|
|
3629
|
+
hasValidToken: apiToken !== undefined,
|
|
3630
|
+
envApiToken: undefined,
|
|
3631
|
+
codeNavigationCapability: getCodeNavigationCapability(apiToken),
|
|
3134
3632
|
codeNavigationCliOverrideEnabled,
|
|
3135
3633
|
codeNavigationUrl,
|
|
3136
|
-
codeNavigationService
|
|
3137
|
-
packageIntelligenceService
|
|
3138
|
-
githitsService: new
|
|
3634
|
+
codeNavigationService,
|
|
3635
|
+
packageIntelligenceService,
|
|
3636
|
+
githitsService: new RefreshingGitHitsService(apiUrl, tokenManager)
|
|
3139
3637
|
};
|
|
3140
|
-
}
|
|
3141
|
-
const tokenManager = new TokenManager({ authService, authStorage, mcpUrl });
|
|
3142
|
-
const apiToken = await tokenManager.getToken();
|
|
3143
|
-
const codeNavigationService = codeNavigationUrl ? new CodeNavigationServiceImpl(codeNavigationUrl, tokenManager) : undefined;
|
|
3144
|
-
const packageIntelligenceService = codeNavigationUrl ? new PackageIntelligenceServiceImpl(codeNavigationUrl, tokenManager) : undefined;
|
|
3145
|
-
return {
|
|
3146
|
-
authStorage,
|
|
3147
|
-
authService,
|
|
3148
|
-
browserService,
|
|
3149
|
-
fileSystemService,
|
|
3150
|
-
mcpUrl,
|
|
3151
|
-
apiUrl,
|
|
3152
|
-
apiToken,
|
|
3153
|
-
hasValidToken: apiToken !== undefined,
|
|
3154
|
-
envApiToken: undefined,
|
|
3155
|
-
codeNavigationCapability: getCodeNavigationCapability(apiToken),
|
|
3156
|
-
codeNavigationCliOverrideEnabled,
|
|
3157
|
-
codeNavigationUrl,
|
|
3158
|
-
codeNavigationService,
|
|
3159
|
-
packageIntelligenceService,
|
|
3160
|
-
githitsService: new RefreshingGitHitsService(apiUrl, tokenManager)
|
|
3161
|
-
};
|
|
3638
|
+
});
|
|
3162
3639
|
}
|
|
3163
3640
|
async function resolveStartupCodeNavigationRegistrationState() {
|
|
3164
|
-
|
|
3165
|
-
|
|
3641
|
+
return withTelemetrySpan("startup.resolve-code-nav-registration-state", async () => {
|
|
3642
|
+
const envToken = getEnvApiToken();
|
|
3643
|
+
if (envToken) {
|
|
3644
|
+
return {
|
|
3645
|
+
capability: getCodeNavigationCapability(envToken),
|
|
3646
|
+
expiredStoredAuth: false
|
|
3647
|
+
};
|
|
3648
|
+
}
|
|
3649
|
+
const tokens = await loadStartupTokens(getMcpUrl());
|
|
3650
|
+
if (tokens?.expiresAt && new Date(tokens.expiresAt) < new Date) {
|
|
3651
|
+
return { capability: "unknown", expiredStoredAuth: true };
|
|
3652
|
+
}
|
|
3166
3653
|
return {
|
|
3167
|
-
capability: getCodeNavigationCapability(
|
|
3654
|
+
capability: getCodeNavigationCapability(tokens?.accessToken),
|
|
3168
3655
|
expiredStoredAuth: false
|
|
3169
3656
|
};
|
|
3170
|
-
}
|
|
3171
|
-
const tokens = await loadStartupTokens(getMcpUrl());
|
|
3172
|
-
if (tokens?.expiresAt && new Date(tokens.expiresAt) < new Date) {
|
|
3173
|
-
return { capability: "unknown", expiredStoredAuth: true };
|
|
3174
|
-
}
|
|
3175
|
-
return {
|
|
3176
|
-
capability: getCodeNavigationCapability(tokens?.accessToken),
|
|
3177
|
-
expiredStoredAuth: false
|
|
3178
|
-
};
|
|
3657
|
+
});
|
|
3179
3658
|
}
|
|
3180
3659
|
async function loadStartupTokens(mcpUrl) {
|
|
3181
|
-
|
|
3182
|
-
|
|
3183
|
-
|
|
3184
|
-
|
|
3185
|
-
|
|
3186
|
-
|
|
3187
|
-
|
|
3188
|
-
|
|
3189
|
-
|
|
3190
|
-
|
|
3191
|
-
|
|
3192
|
-
|
|
3193
|
-
|
|
3660
|
+
return withTelemetrySpan("startup.load-tokens", async () => {
|
|
3661
|
+
const fileSystemService = new FileSystemServiceImpl;
|
|
3662
|
+
const fileStorage = new AuthStorageImpl(fileSystemService);
|
|
3663
|
+
try {
|
|
3664
|
+
const rawKeyring = new KeyringServiceImpl;
|
|
3665
|
+
const keyring = process.platform === "win32" ? new ChunkingKeyringService(rawKeyring, WINDOWS_MAX_ENTRY_SIZE) : rawKeyring;
|
|
3666
|
+
const keychainStorage = new KeychainAuthStorage(keyring);
|
|
3667
|
+
const keychainTokens = await keychainStorage.loadTokens(mcpUrl);
|
|
3668
|
+
if (keychainTokens) {
|
|
3669
|
+
return keychainTokens;
|
|
3670
|
+
}
|
|
3671
|
+
} catch (error) {
|
|
3672
|
+
if (!(error instanceof KeychainUnavailableError)) {
|
|
3673
|
+
throw error;
|
|
3674
|
+
}
|
|
3194
3675
|
}
|
|
3195
|
-
|
|
3196
|
-
|
|
3676
|
+
return fileStorage.loadTokens(mcpUrl);
|
|
3677
|
+
});
|
|
3197
3678
|
}
|
|
3198
3679
|
|
|
3199
3680
|
// src/commands/auth-status.ts
|
|
@@ -3813,8 +4294,8 @@ function buildPackageDependenciesSuccessPayload(report, options = {}) {
|
|
|
3813
4294
|
payload.requestedVersion = requestedEcho;
|
|
3814
4295
|
}
|
|
3815
4296
|
const bundle = report.dependencies;
|
|
3816
|
-
const
|
|
3817
|
-
const directVersionByName =
|
|
4297
|
+
const graph = bundle?.transitive?.dependencyGraph ?? null;
|
|
4298
|
+
const directVersionByName = graph ? buildDirectVersionLookup(graph) : null;
|
|
3818
4299
|
const directArray = bundle?.direct;
|
|
3819
4300
|
if (directArray !== undefined) {
|
|
3820
4301
|
const items = directArray.map((entry) => buildDirect(entry, directVersionByName));
|
|
@@ -3827,8 +4308,8 @@ function buildPackageDependenciesSuccessPayload(report, options = {}) {
|
|
|
3827
4308
|
if (groupsInfo.primaryGroup) {
|
|
3828
4309
|
groupsBlock.primaryGroup = groupsInfo.primaryGroup;
|
|
3829
4310
|
}
|
|
3830
|
-
if (groupsInfo.
|
|
3831
|
-
groupsBlock.
|
|
4311
|
+
if (groupsInfo.environmentMarkers && groupsInfo.environmentMarkers.length > 0) {
|
|
4312
|
+
groupsBlock.environmentMarkers = groupsInfo.environmentMarkers.map((m) => projectEnvironmentMarker(m));
|
|
3832
4313
|
}
|
|
3833
4314
|
payload.groups = groupsBlock;
|
|
3834
4315
|
}
|
|
@@ -3845,15 +4326,18 @@ function buildPackageDependenciesSuccessPayload(report, options = {}) {
|
|
|
3845
4326
|
if (options.maxDepth !== undefined) {
|
|
3846
4327
|
block.depth = options.maxDepth;
|
|
3847
4328
|
}
|
|
3848
|
-
const packages = buildTransitivePackages(transitive.uniqueDependencies,
|
|
4329
|
+
const packages = buildTransitivePackages(transitive.uniqueDependencies, graph, options.includeImporters ?? false);
|
|
3849
4330
|
if (packages && packages.length > 0) {
|
|
3850
4331
|
block.packages = packages;
|
|
3851
4332
|
}
|
|
3852
|
-
if (transitive.
|
|
3853
|
-
block.conflicts =
|
|
4333
|
+
if (transitive.dependencyConflicts && transitive.dependencyConflicts.length > 0) {
|
|
4334
|
+
block.conflicts = transitive.dependencyConflicts.map((c) => ({
|
|
4335
|
+
name: c.packageName,
|
|
4336
|
+
requiredVersions: c.requiredVersions.slice().sort()
|
|
4337
|
+
}));
|
|
3854
4338
|
}
|
|
3855
|
-
if (transitive.
|
|
3856
|
-
block.circularDependencies =
|
|
4339
|
+
if (transitive.circularDependencyCycles && transitive.circularDependencyCycles.length > 0) {
|
|
4340
|
+
block.circularDependencies = transitive.circularDependencyCycles.map((c) => ({ cycle: c.circularPath.slice() }));
|
|
3857
4341
|
}
|
|
3858
4342
|
payload.transitive = block;
|
|
3859
4343
|
}
|
|
@@ -3863,6 +4347,16 @@ function buildPackageDependenciesSuccessPayload(report, options = {}) {
|
|
|
3863
4347
|
}
|
|
3864
4348
|
return payload;
|
|
3865
4349
|
}
|
|
4350
|
+
function projectEnvironmentMarker(marker) {
|
|
4351
|
+
const out = {};
|
|
4352
|
+
if (marker.type !== undefined)
|
|
4353
|
+
out.type = marker.type;
|
|
4354
|
+
if (marker.value !== undefined)
|
|
4355
|
+
out.value = marker.value;
|
|
4356
|
+
if (marker.raw !== undefined)
|
|
4357
|
+
out.raw = marker.raw;
|
|
4358
|
+
return out;
|
|
4359
|
+
}
|
|
3866
4360
|
function buildDirect(entry, directVersionByName) {
|
|
3867
4361
|
const lean = { name: entry.name };
|
|
3868
4362
|
if (entry.versionConstraint)
|
|
@@ -3872,15 +4366,14 @@ function buildDirect(entry, directVersionByName) {
|
|
|
3872
4366
|
lean.version = resolved;
|
|
3873
4367
|
return lean;
|
|
3874
4368
|
}
|
|
3875
|
-
function buildDirectVersionLookup(
|
|
3876
|
-
const rootIdx = findRootNodeIdx(
|
|
3877
|
-
if (rootIdx === null)
|
|
3878
|
-
return null;
|
|
4369
|
+
function buildDirectVersionLookup(graph) {
|
|
4370
|
+
const rootIdx = findRootNodeIdx(graph);
|
|
3879
4371
|
const out = new Map;
|
|
3880
|
-
for (const edge of
|
|
3881
|
-
|
|
4372
|
+
for (const edge of graph.edges) {
|
|
4373
|
+
const fromRoot = edge.fromIndex === undefined || edge.fromIndex === null || edge.fromIndex === rootIdx;
|
|
4374
|
+
if (!fromRoot)
|
|
3882
4375
|
continue;
|
|
3883
|
-
const node =
|
|
4376
|
+
const node = graph.nodes[edge.toIndex];
|
|
3884
4377
|
if (!node || !node.version)
|
|
3885
4378
|
continue;
|
|
3886
4379
|
if (!out.has(node.name)) {
|
|
@@ -3889,12 +4382,12 @@ function buildDirectVersionLookup(dag) {
|
|
|
3889
4382
|
}
|
|
3890
4383
|
return out.size > 0 ? out : null;
|
|
3891
4384
|
}
|
|
3892
|
-
function findRootNodeIdx(
|
|
4385
|
+
function findRootNodeIdx(graph) {
|
|
3893
4386
|
const incoming = new Set;
|
|
3894
|
-
for (const e of
|
|
3895
|
-
incoming.add(e.
|
|
4387
|
+
for (const e of graph.edges)
|
|
4388
|
+
incoming.add(e.toIndex);
|
|
3896
4389
|
let root = null;
|
|
3897
|
-
for (let i = 0;i <
|
|
4390
|
+
for (let i = 0;i < graph.nodes.length; i++) {
|
|
3898
4391
|
if (!incoming.has(i)) {
|
|
3899
4392
|
if (root !== null)
|
|
3900
4393
|
return null;
|
|
@@ -3903,10 +4396,10 @@ function findRootNodeIdx(dag) {
|
|
|
3903
4396
|
}
|
|
3904
4397
|
return root;
|
|
3905
4398
|
}
|
|
3906
|
-
function buildTransitivePackages(uniqueDependencies,
|
|
4399
|
+
function buildTransitivePackages(uniqueDependencies, graph, includeImporters) {
|
|
3907
4400
|
if (!uniqueDependencies || uniqueDependencies.length === 0)
|
|
3908
4401
|
return null;
|
|
3909
|
-
const incoming = includeImporters &&
|
|
4402
|
+
const incoming = includeImporters && graph ? buildIncomingEdgeMap(graph) : null;
|
|
3910
4403
|
const out = [];
|
|
3911
4404
|
for (const entry of uniqueDependencies) {
|
|
3912
4405
|
const [name, version2] = parseNameAtVersion(entry);
|
|
@@ -3915,11 +4408,11 @@ function buildTransitivePackages(uniqueDependencies, dag, includeImporters) {
|
|
|
3915
4408
|
const record = { name };
|
|
3916
4409
|
if (version2)
|
|
3917
4410
|
record.version = version2;
|
|
3918
|
-
if (includeImporters &&
|
|
3919
|
-
const nodeIdx = findNodeIdx(
|
|
4411
|
+
if (includeImporters && graph && incoming) {
|
|
4412
|
+
const nodeIdx = findNodeIdx(graph, name, version2);
|
|
3920
4413
|
if (nodeIdx !== null) {
|
|
3921
4414
|
const edges = incoming.get(nodeIdx) ?? [];
|
|
3922
|
-
const importers = buildImportersFromEdges(
|
|
4415
|
+
const importers = buildImportersFromEdges(graph, edges);
|
|
3923
4416
|
if (importers.length > 0)
|
|
3924
4417
|
record.importers = importers;
|
|
3925
4418
|
}
|
|
@@ -3937,21 +4430,21 @@ function parseNameAtVersion(raw) {
|
|
|
3937
4430
|
return [trimmed, undefined];
|
|
3938
4431
|
return [trimmed.slice(0, atIdx), trimmed.slice(atIdx + 1)];
|
|
3939
4432
|
}
|
|
3940
|
-
function buildIncomingEdgeMap(
|
|
4433
|
+
function buildIncomingEdgeMap(graph) {
|
|
3941
4434
|
const map = new Map;
|
|
3942
|
-
for (const edge of
|
|
3943
|
-
const list = map.get(edge.
|
|
4435
|
+
for (const edge of graph.edges) {
|
|
4436
|
+
const list = map.get(edge.toIndex);
|
|
3944
4437
|
if (list)
|
|
3945
4438
|
list.push(edge);
|
|
3946
4439
|
else
|
|
3947
|
-
map.set(edge.
|
|
4440
|
+
map.set(edge.toIndex, [edge]);
|
|
3948
4441
|
}
|
|
3949
4442
|
return map;
|
|
3950
4443
|
}
|
|
3951
|
-
function findNodeIdx(
|
|
4444
|
+
function findNodeIdx(graph, name, version2) {
|
|
3952
4445
|
let fallback = null;
|
|
3953
|
-
for (let i = 0;i <
|
|
3954
|
-
const n =
|
|
4446
|
+
for (let i = 0;i < graph.nodes.length; i++) {
|
|
4447
|
+
const n = graph.nodes[i];
|
|
3955
4448
|
if (!n)
|
|
3956
4449
|
continue;
|
|
3957
4450
|
if (n.name !== name)
|
|
@@ -3965,11 +4458,13 @@ function findNodeIdx(dag, name, version2) {
|
|
|
3965
4458
|
}
|
|
3966
4459
|
return fallback;
|
|
3967
4460
|
}
|
|
3968
|
-
function buildImportersFromEdges(
|
|
4461
|
+
function buildImportersFromEdges(graph, edges) {
|
|
3969
4462
|
const seen = new Set;
|
|
3970
4463
|
const out = [];
|
|
3971
4464
|
for (const edge of edges) {
|
|
3972
|
-
|
|
4465
|
+
if (edge.fromIndex === undefined || edge.fromIndex === null)
|
|
4466
|
+
continue;
|
|
4467
|
+
const from = graph.nodes[edge.fromIndex];
|
|
3973
4468
|
if (!from)
|
|
3974
4469
|
continue;
|
|
3975
4470
|
const key = `${from.name}\x00${from.version ?? ""}\x00${edge.constraint ?? ""}`;
|
|
@@ -3996,60 +4491,6 @@ function buildImportersFromEdges(dag, edges) {
|
|
|
3996
4491
|
});
|
|
3997
4492
|
return out;
|
|
3998
4493
|
}
|
|
3999
|
-
function buildTypedConflicts(raw) {
|
|
4000
|
-
const typed = [];
|
|
4001
|
-
for (const entry of raw) {
|
|
4002
|
-
const decoded = decodeConflictEntryForEnvelope(entry);
|
|
4003
|
-
if (!decoded)
|
|
4004
|
-
return raw.slice();
|
|
4005
|
-
typed.push(decoded);
|
|
4006
|
-
}
|
|
4007
|
-
return typed;
|
|
4008
|
-
}
|
|
4009
|
-
function decodeConflictEntryForEnvelope(raw) {
|
|
4010
|
-
if (!raw || typeof raw !== "object")
|
|
4011
|
-
return null;
|
|
4012
|
-
const obj = raw;
|
|
4013
|
-
const name = typeof obj.package_name === "string" ? obj.package_name : typeof obj.packageName === "string" ? obj.packageName : null;
|
|
4014
|
-
if (!name)
|
|
4015
|
-
return null;
|
|
4016
|
-
const rangesRaw = obj.required_versions ?? obj.requiredVersions;
|
|
4017
|
-
if (!Array.isArray(rangesRaw))
|
|
4018
|
-
return null;
|
|
4019
|
-
const ranges = [];
|
|
4020
|
-
for (const r of rangesRaw) {
|
|
4021
|
-
if (typeof r === "string" && r.length > 0 && !ranges.includes(r)) {
|
|
4022
|
-
ranges.push(r);
|
|
4023
|
-
}
|
|
4024
|
-
}
|
|
4025
|
-
if (ranges.length === 0)
|
|
4026
|
-
return null;
|
|
4027
|
-
ranges.sort();
|
|
4028
|
-
return { name, requiredVersions: ranges };
|
|
4029
|
-
}
|
|
4030
|
-
function buildTypedCycles(raw) {
|
|
4031
|
-
const typed = [];
|
|
4032
|
-
for (const entry of raw) {
|
|
4033
|
-
const decoded = decodeCycleEntryForEnvelope(entry);
|
|
4034
|
-
if (!decoded)
|
|
4035
|
-
return raw.slice();
|
|
4036
|
-
typed.push({ cycle: decoded });
|
|
4037
|
-
}
|
|
4038
|
-
return typed;
|
|
4039
|
-
}
|
|
4040
|
-
function decodeCycleEntryForEnvelope(raw) {
|
|
4041
|
-
if (Array.isArray(raw) && raw.every((x) => typeof x === "string")) {
|
|
4042
|
-
return raw;
|
|
4043
|
-
}
|
|
4044
|
-
if (!raw || typeof raw !== "object")
|
|
4045
|
-
return null;
|
|
4046
|
-
const obj = raw;
|
|
4047
|
-
const source = obj.cycle ?? obj.packages ?? obj.path;
|
|
4048
|
-
if (!Array.isArray(source))
|
|
4049
|
-
return null;
|
|
4050
|
-
const names = source.filter((x) => typeof x === "string");
|
|
4051
|
-
return names.length > 0 ? names : null;
|
|
4052
|
-
}
|
|
4053
4494
|
function buildGroup(group) {
|
|
4054
4495
|
const lean = {
|
|
4055
4496
|
name: group.name,
|
|
@@ -4295,49 +4736,23 @@ function formatConflictsAndCycles(payload, verbose, useColors) {
|
|
|
4295
4736
|
return "";
|
|
4296
4737
|
if (conflicts.length > 0) {
|
|
4297
4738
|
lines.push(colorize(`Conflicts (${conflicts.length}):`, "yellow", useColors));
|
|
4298
|
-
const
|
|
4299
|
-
|
|
4300
|
-
|
|
4301
|
-
const
|
|
4302
|
-
|
|
4303
|
-
const padded = `${c.name}:`.padEnd(nameWidth + 2);
|
|
4304
|
-
lines.push(` ${padded} ${c.requiredVersions.join(", ")}`);
|
|
4305
|
-
}
|
|
4306
|
-
} else {
|
|
4307
|
-
for (const c of conflicts)
|
|
4308
|
-
lines.push(` ${JSON.stringify(c)}`);
|
|
4739
|
+
const nameWidth = Math.max(...conflicts.map((c) => c.name.length));
|
|
4740
|
+
const sorted = [...conflicts].sort((a, b) => a.name < b.name ? -1 : a.name > b.name ? 1 : 0);
|
|
4741
|
+
for (const c of sorted) {
|
|
4742
|
+
const padded = `${c.name}:`.padEnd(nameWidth + 2);
|
|
4743
|
+
lines.push(` ${padded} ${c.requiredVersions.join(", ")}`);
|
|
4309
4744
|
}
|
|
4310
4745
|
}
|
|
4311
4746
|
if (cycles.length > 0) {
|
|
4312
4747
|
if (conflicts.length > 0)
|
|
4313
4748
|
lines.push("");
|
|
4314
4749
|
lines.push(colorize(`Circular dependencies (${cycles.length}):`, "red", useColors));
|
|
4315
|
-
const
|
|
4316
|
-
|
|
4317
|
-
for (const c of typed)
|
|
4318
|
-
lines.push(` ${c.cycle.join(" → ")}`);
|
|
4319
|
-
} else {
|
|
4320
|
-
for (const c of cycles)
|
|
4321
|
-
lines.push(` ${JSON.stringify(c)}`);
|
|
4322
|
-
}
|
|
4750
|
+
for (const c of cycles)
|
|
4751
|
+
lines.push(` ${c.cycle.join(" → ")}`);
|
|
4323
4752
|
}
|
|
4324
4753
|
return lines.join(`
|
|
4325
4754
|
`);
|
|
4326
4755
|
}
|
|
4327
|
-
function isTypedConflictArray(arr) {
|
|
4328
|
-
const first = arr[0];
|
|
4329
|
-
if (!first || typeof first !== "object")
|
|
4330
|
-
return false;
|
|
4331
|
-
const obj = first;
|
|
4332
|
-
return typeof obj.name === "string" && Array.isArray(obj.requiredVersions);
|
|
4333
|
-
}
|
|
4334
|
-
function isTypedCycleArray(arr) {
|
|
4335
|
-
const first = arr[0];
|
|
4336
|
-
if (!first || typeof first !== "object")
|
|
4337
|
-
return false;
|
|
4338
|
-
const obj = first;
|
|
4339
|
-
return Array.isArray(obj.cycle);
|
|
4340
|
-
}
|
|
4341
4756
|
function formatGroupsBlock(payload, verbose, useColors) {
|
|
4342
4757
|
const groups = payload.groups;
|
|
4343
4758
|
const lines = [];
|
|
@@ -4350,10 +4765,10 @@ function formatGroupsBlock(payload, verbose, useColors) {
|
|
|
4350
4765
|
const groupNoun = groups.items.length === 1 ? "group" : "groups";
|
|
4351
4766
|
lines.push(colorize(`${groups.items.length} ${groupNoun} (${summary}):`, "bold", useColors));
|
|
4352
4767
|
lines.push("");
|
|
4353
|
-
if (verbose && groups.
|
|
4354
|
-
lines.push(dim(`
|
|
4355
|
-
for (const
|
|
4356
|
-
lines.push(dim(` ${
|
|
4768
|
+
if (verbose && groups.environmentMarkers && groups.environmentMarkers.length > 0) {
|
|
4769
|
+
lines.push(dim(`environmentMarkers (${groups.environmentMarkers.length}):`, useColors));
|
|
4770
|
+
for (const marker of groups.environmentMarkers) {
|
|
4771
|
+
lines.push(dim(` ${formatEnvironmentMarker(marker)}`, useColors));
|
|
4357
4772
|
}
|
|
4358
4773
|
lines.push("");
|
|
4359
4774
|
}
|
|
@@ -4382,6 +4797,15 @@ function formatGroupsBlock(payload, verbose, useColors) {
|
|
|
4382
4797
|
return lines.join(`
|
|
4383
4798
|
`).trimEnd();
|
|
4384
4799
|
}
|
|
4800
|
+
function formatEnvironmentMarker(marker) {
|
|
4801
|
+
if (marker.type && marker.value)
|
|
4802
|
+
return `${marker.type}: ${marker.value}`;
|
|
4803
|
+
if (marker.value)
|
|
4804
|
+
return marker.value;
|
|
4805
|
+
if (marker.type)
|
|
4806
|
+
return marker.type;
|
|
4807
|
+
return marker.raw ?? "(empty marker)";
|
|
4808
|
+
}
|
|
4385
4809
|
function formatGroupHeading(group, registry) {
|
|
4386
4810
|
if (group.conditionType === "always") {
|
|
4387
4811
|
return group.name;
|
|
@@ -4447,101 +4871,6 @@ function sortAlphabetically(items, key) {
|
|
|
4447
4871
|
return ka < kb ? -1 : ka > kb ? 1 : 0;
|
|
4448
4872
|
});
|
|
4449
4873
|
}
|
|
4450
|
-
function decodeDag(raw) {
|
|
4451
|
-
if (!raw || typeof raw !== "object")
|
|
4452
|
-
return null;
|
|
4453
|
-
const obj = raw;
|
|
4454
|
-
const rawNodes = obj.n ?? obj.nodes;
|
|
4455
|
-
const rawEdges = obj.e ?? obj.edges;
|
|
4456
|
-
const nodes = decodeNodes(rawNodes);
|
|
4457
|
-
if (!nodes)
|
|
4458
|
-
return null;
|
|
4459
|
-
const edges = decodeEdges(rawEdges);
|
|
4460
|
-
if (!edges)
|
|
4461
|
-
return null;
|
|
4462
|
-
return { nodes, edges };
|
|
4463
|
-
}
|
|
4464
|
-
function decodeNodes(raw) {
|
|
4465
|
-
if (Array.isArray(raw)) {
|
|
4466
|
-
const result = [];
|
|
4467
|
-
for (const entry of raw) {
|
|
4468
|
-
if (!Array.isArray(entry)) {
|
|
4469
|
-
if (typeof entry === "object" && entry !== null) {
|
|
4470
|
-
const n = decodeObjectNode(entry);
|
|
4471
|
-
if (!n)
|
|
4472
|
-
return null;
|
|
4473
|
-
result.push(n);
|
|
4474
|
-
continue;
|
|
4475
|
-
}
|
|
4476
|
-
return null;
|
|
4477
|
-
}
|
|
4478
|
-
const [registry, name, version2] = entry;
|
|
4479
|
-
if (typeof name !== "string")
|
|
4480
|
-
return null;
|
|
4481
|
-
result.push({
|
|
4482
|
-
name,
|
|
4483
|
-
version: typeof version2 === "string" ? version2 : undefined,
|
|
4484
|
-
registry: typeof registry === "string" ? registry : undefined
|
|
4485
|
-
});
|
|
4486
|
-
}
|
|
4487
|
-
return result;
|
|
4488
|
-
}
|
|
4489
|
-
if (raw && typeof raw === "object") {
|
|
4490
|
-
const result = [];
|
|
4491
|
-
for (const entry of Object.values(raw)) {
|
|
4492
|
-
if (!entry || typeof entry !== "object")
|
|
4493
|
-
return null;
|
|
4494
|
-
const n = decodeObjectNode(entry);
|
|
4495
|
-
if (!n)
|
|
4496
|
-
return null;
|
|
4497
|
-
result.push(n);
|
|
4498
|
-
}
|
|
4499
|
-
return result;
|
|
4500
|
-
}
|
|
4501
|
-
return null;
|
|
4502
|
-
}
|
|
4503
|
-
function decodeObjectNode(entry) {
|
|
4504
|
-
const name = typeof entry.n === "string" ? entry.n : typeof entry.name === "string" ? entry.name : null;
|
|
4505
|
-
if (!name)
|
|
4506
|
-
return null;
|
|
4507
|
-
const version2 = typeof entry.v === "string" ? entry.v : typeof entry.version === "string" ? entry.version : undefined;
|
|
4508
|
-
return { name, version: version2 };
|
|
4509
|
-
}
|
|
4510
|
-
function decodeEdges(raw) {
|
|
4511
|
-
if (!Array.isArray(raw))
|
|
4512
|
-
return null;
|
|
4513
|
-
const out = [];
|
|
4514
|
-
for (const entry of raw) {
|
|
4515
|
-
if (Array.isArray(entry)) {
|
|
4516
|
-
const [from, to, constraint, lifecycle] = entry;
|
|
4517
|
-
if (typeof from !== "number" || typeof to !== "number")
|
|
4518
|
-
return null;
|
|
4519
|
-
out.push({
|
|
4520
|
-
fromIdx: from,
|
|
4521
|
-
toIdx: to,
|
|
4522
|
-
constraint: typeof constraint === "string" ? constraint : undefined,
|
|
4523
|
-
lifecycle: typeof lifecycle === "string" ? lifecycle : undefined
|
|
4524
|
-
});
|
|
4525
|
-
continue;
|
|
4526
|
-
}
|
|
4527
|
-
if (entry && typeof entry === "object") {
|
|
4528
|
-
const obj = entry;
|
|
4529
|
-
const from = obj.f ?? obj.from;
|
|
4530
|
-
const to = obj.t ?? obj.to;
|
|
4531
|
-
if (typeof from !== "number" || typeof to !== "number")
|
|
4532
|
-
return null;
|
|
4533
|
-
out.push({
|
|
4534
|
-
fromIdx: from,
|
|
4535
|
-
toIdx: to,
|
|
4536
|
-
constraint: typeof obj.c === "string" ? obj.c : undefined,
|
|
4537
|
-
lifecycle: typeof obj.l === "string" ? obj.l : undefined
|
|
4538
|
-
});
|
|
4539
|
-
continue;
|
|
4540
|
-
}
|
|
4541
|
-
return null;
|
|
4542
|
-
}
|
|
4543
|
-
return out;
|
|
4544
|
-
}
|
|
4545
4874
|
// src/shared/package-intelligence-error-map.ts
|
|
4546
4875
|
function mapPackageIntelligenceError(error2) {
|
|
4547
4876
|
const mapped = classify2(error2);
|
|
@@ -9142,8 +9471,23 @@ function createMcpServer(deps) {
|
|
|
9142
9471
|
return server;
|
|
9143
9472
|
}
|
|
9144
9473
|
async function startMcpServer(deps) {
|
|
9474
|
+
setClientMode("mcp");
|
|
9145
9475
|
const server = createMcpServer(deps);
|
|
9146
9476
|
const transport = new StdioServerTransport;
|
|
9477
|
+
setMcpClientVersionProvider(() => {
|
|
9478
|
+
try {
|
|
9479
|
+
const clientVersion = server.server.getClientVersion();
|
|
9480
|
+
if (!clientVersion?.name || typeof clientVersion.name !== "string" || clientVersion.name.trim().length === 0) {
|
|
9481
|
+
return;
|
|
9482
|
+
}
|
|
9483
|
+
const name = clientVersion.name.trim();
|
|
9484
|
+
const rawVersion = clientVersion.version;
|
|
9485
|
+
const versionOut = typeof rawVersion === "string" && rawVersion.trim().length > 0 ? rawVersion.trim() : undefined;
|
|
9486
|
+
return { name, version: versionOut };
|
|
9487
|
+
} catch {
|
|
9488
|
+
return;
|
|
9489
|
+
}
|
|
9490
|
+
});
|
|
9147
9491
|
await server.connect(transport);
|
|
9148
9492
|
}
|
|
9149
9493
|
function showMcpSetupInstructions() {
|
|
@@ -9652,10 +9996,20 @@ function registerSearchCommand(program) {
|
|
|
9652
9996
|
}
|
|
9653
9997
|
// src/cli.ts
|
|
9654
9998
|
var program = new Command;
|
|
9655
|
-
|
|
9999
|
+
var commandSpans = new WeakMap;
|
|
10000
|
+
if (isTelemetryEnabled()) {
|
|
10001
|
+
process.once("exit", (exitCode) => {
|
|
10002
|
+
flushTelemetry(exitCode);
|
|
10003
|
+
});
|
|
10004
|
+
}
|
|
10005
|
+
program.name("githits").description("Code examples from global open source for your AI assistant").version(version).option("--no-color", "Disable colored output").hook("preAction", (thisCommand, actionCommand) => {
|
|
9656
10006
|
if (thisCommand.opts().color === false) {
|
|
9657
10007
|
process.env.NO_COLOR = "1";
|
|
9658
10008
|
}
|
|
10009
|
+
const command = actionCommand ?? thisCommand;
|
|
10010
|
+
commandSpans.set(command, startTelemetrySpan(getTelemetryCommandName(command)));
|
|
10011
|
+
}).hook("postAction", (_thisCommand, actionCommand) => {
|
|
10012
|
+
endTelemetrySpan(commandSpans.get(actionCommand));
|
|
9659
10013
|
}).addHelpText("after", `
|
|
9660
10014
|
Getting started:
|
|
9661
10015
|
githits init Set up MCP for your coding agents
|
|
@@ -9675,15 +10029,27 @@ registerLanguagesCommand(program);
|
|
|
9675
10029
|
registerFeedbackCommand(program);
|
|
9676
10030
|
var argv = process.argv.slice(2);
|
|
9677
10031
|
if (shouldEagerLoadGatedCommandGroup(argv, "code")) {
|
|
9678
|
-
await registerCodeCommandGroup(program);
|
|
10032
|
+
await withTelemetrySpan("cli.register.code-group", () => registerCodeCommandGroup(program));
|
|
9679
10033
|
}
|
|
9680
10034
|
if (shouldEagerLoadGatedCommandGroup(argv, "pkg")) {
|
|
9681
|
-
await registerPkgCommandGroup(program);
|
|
10035
|
+
await withTelemetrySpan("cli.register.pkg-group", () => registerPkgCommandGroup(program));
|
|
9682
10036
|
}
|
|
9683
10037
|
var authCommand = program.command("auth").summary("Manage authentication").description("Manage authentication with GitHits.");
|
|
9684
10038
|
registerAuthStatusCommand(authCommand);
|
|
9685
|
-
await program.parseAsync();
|
|
10039
|
+
await withTelemetrySpan("cli.parse", () => program.parseAsync());
|
|
9686
10040
|
function shouldEagerLoadGatedCommandGroup(args, groupName) {
|
|
9687
10041
|
const [firstArg] = args;
|
|
9688
10042
|
return firstArg === groupName || firstArg === "help" || firstArg === "--help" || firstArg === "-h";
|
|
9689
10043
|
}
|
|
10044
|
+
function getTelemetryCommandName(command) {
|
|
10045
|
+
const names = [];
|
|
10046
|
+
let current = command;
|
|
10047
|
+
while (current) {
|
|
10048
|
+
const name = current.name();
|
|
10049
|
+
if (name && name !== "githits") {
|
|
10050
|
+
names.unshift(name);
|
|
10051
|
+
}
|
|
10052
|
+
current = current.parent ?? null;
|
|
10053
|
+
}
|
|
10054
|
+
return `command.${names.join(".")}`;
|
|
10055
|
+
}
|