MCPcopy
hub / github.com/upstash/context7 / suggestCommand

Function suggestCommand

packages/cli/src/commands/skill.ts:827–1026  ·  view source on GitHub ↗
(options: SuggestOptions)

Source from the content-addressed store, hash-verified

825}
826
827async function suggestCommand(options: SuggestOptions): Promise<void> {
828 trackEvent("command", { name: "suggest" });
829 log.blank();
830
831 // Step 1: Detect dependencies
832 const scanSpinner = ora("Scanning project dependencies...").start();
833 const deps = await detectProjectDependencies(process.cwd());
834
835 if (deps.length === 0) {
836 scanSpinner.warn(pc.yellow("No dependencies detected"));
837 log.info(`Try ${pc.cyan("ctx7 skills search <keyword>")} to search manually`);
838 return;
839 }
840
841 scanSpinner.succeed(`Found ${deps.length} dependencies`);
842
843 // Step 2: Single API call to backend
844 const searchSpinner = ora("Finding matching skills...").start();
845
846 const tokens = loadTokens();
847 const accessToken = tokens && !isTokenExpired(tokens) ? tokens.access_token : undefined;
848
849 let data;
850 try {
851 data = await suggestSkills(deps, accessToken);
852 } catch {
853 searchSpinner.fail(pc.red("Failed to connect to Context7"));
854 return;
855 }
856
857 if (data.error) {
858 searchSpinner.fail(pc.red(`Error: ${data.message || data.error}`));
859 return;
860 }
861
862 const skills = data.skills;
863
864 if (skills.length === 0) {
865 searchSpinner.warn(pc.yellow("No matching skills found for your dependencies"));
866 return;
867 }
868
869 searchSpinner.succeed(`Found ${skills.length} relevant skill(s)`);
870 trackEvent("suggest_results", { depCount: deps.length, skillCount: skills.length });
871 log.blank();
872
873 const nameWithRepo = (s: SkillSearchResult) => `${s.name} ${pc.dim(`(${s.project})`)}`;
874 const nameWithRepoLen = (s: SkillSearchResult) => `${s.name} (${s.project})`.length;
875 const maxNameLen = Math.max(...skills.map(nameWithRepoLen));
876 const popularityColWidth = 13;
877 const trustColWidth = 8;
878 const maxMatchedLen = Math.max(...skills.map((s) => s.matchedDep.length));
879 const indexWidth = skills.length.toString().length;
880
881 const choices = skills.map((s, index) => {
882 const indexStr = pc.dim(`${(index + 1).toString().padStart(indexWidth)}.`);
883 const rawLen = nameWithRepoLen(s);
884 const displayName = nameWithRepo(s) + " ".repeat(maxNameLen - rawLen);

Callers 2

registerSkillCommandsFunction · 0.85
registerSkillAliasesFunction · 0.85

Calls 15

trackEventFunction · 0.85
loadTokensFunction · 0.85
isTokenExpiredFunction · 0.85
suggestSkillsFunction · 0.85
nameWithRepoLenFunction · 0.85
nameWithRepoFunction · 0.85
formatPopularityFunction · 0.85
getTrustLabelFunction · 0.85
formatTrustFunction · 0.85
terminalLinkFunction · 0.85
formatInstallRangeFunction · 0.85

Tested by

no test coverage detected