diff --git a/core/core.ts b/core/core.ts index f011ccd952..5fa42c5b67 100644 --- a/core/core.ts +++ b/core/core.ts @@ -22,7 +22,6 @@ import { DataLogger } from "./data/log"; import { streamDiffLines } from "./edit/streamDiffLines"; import { CodebaseIndexer, PauseToken } from "./indexing/CodebaseIndexer"; import DocsService from "./indexing/docs/DocsService"; -import { getAllSuggestedDocs } from "./indexing/docs/suggestions"; import Ollama from "./llm/llms/Ollama"; import { createNewPromptFileV2 } from "./promptFiles/v2/createNewPromptFile"; import { callTool } from "./tools/callTool"; @@ -807,14 +806,6 @@ export class Core { // this.docsService.setPaused(msg.data.id, msg.data.paused); // not supported yet } }); - on("docs/getSuggestedDocs", async (msg) => { - if (hasRequestedDocs) { - return; - } // TODO, remove, hack because of rerendering - hasRequestedDocs = true; - const suggestedDocs = await getAllSuggestedDocs(this.ide); - this.messenger.send("docs/suggestions", suggestedDocs); - }); on("docs/initStatuses", async (msg) => { void this.docsService.initStatuses(); }); @@ -989,4 +980,3 @@ export class Core { // private } -let hasRequestedDocs = false; diff --git a/core/indexing/docs/suggestions/index.ts b/core/indexing/docs/suggestions/index.ts deleted file mode 100644 index fac5091fd8..0000000000 --- a/core/indexing/docs/suggestions/index.ts +++ /dev/null @@ -1,129 +0,0 @@ -import { - PackageDocsResult, - FilePathAndName, - PackageFilePathAndName, - IDE, - PackageDetails, - ParsedPackageInfo, -} from "../../.."; -import { getUriPathBasename } from "../../../util/uri"; -import { walkDir, walkDirs } from "../../walkDir"; - -import { PythonPackageCrawler } from "./packageCrawlers/Python"; -import { NodePackageCrawler } from "./packageCrawlers/TsJs"; - -const PACKAGE_CRAWLERS = [NodePackageCrawler, PythonPackageCrawler]; - -export interface PackageCrawler { - packageRegistry: string; - getPackageFiles(files: FilePathAndName[]): PackageFilePathAndName[]; - parsePackageFile( - file: PackageFilePathAndName, - contents: string, - ): ParsedPackageInfo[]; - getPackageDetails(packageInfo: ParsedPackageInfo): Promise; -} - -export async function getAllSuggestedDocs(ide: IDE) { - const allFileUris = await walkDirs(ide); - const allFiles = allFileUris.map((uri) => ({ - path: uri, - name: getUriPathBasename(uri), - })); - - // Build map of language -> package files - const packageFilesByRegistry: Record = {}; - for (const Crawler of PACKAGE_CRAWLERS) { - const crawler = new Crawler(); - const packageFilePaths = crawler.getPackageFiles(allFiles); - packageFilesByRegistry[crawler.packageRegistry] = packageFilePaths; - } - - // Get file contents for all unique package files - const uniqueFilePaths = Array.from( - new Set( - Object.values(packageFilesByRegistry).flatMap((files) => - files.map((file) => file.path), - ), - ), - ); - const fileContentsArray = await Promise.all( - uniqueFilePaths.map(async (path) => { - const contents = await ide.readFile(path); - return { path, contents }; - }), - ); - const fileContents = new Map( - fileContentsArray.map(({ path, contents }) => [path, contents]), - ); - - // Parse package files and build map of language -> packages - const packagesByCrawler: Record = {}; - PACKAGE_CRAWLERS.forEach((Crawler) => { - const crawler = new Crawler(); - packagesByCrawler[crawler.packageRegistry] = []; - const packageFiles = packageFilesByRegistry[crawler.packageRegistry]; - packageFiles.forEach((file) => { - const contents = fileContents.get(file.path); - if (!contents) { - return; - } - const packages = crawler.parsePackageFile(file, contents); - packagesByCrawler[crawler.packageRegistry].push(...packages); - }); - }); - - // Deduplicate packages per language - // TODO - this is where you would allow docs for different versions - // by e.g. using "name-version" as the map key instead of just name - // For now have not allowed - const registries = Object.keys(packagesByCrawler); - registries.forEach((registry) => { - const packages = packagesByCrawler[registry]; - const uniquePackages = Array.from( - new Map(packages.map((pkg) => [pkg.name, pkg])).values(), - ); - packagesByCrawler[registry] = uniquePackages; - }); - - // Get documentation links for all packages - const allDocsResults: PackageDocsResult[] = []; - await Promise.all( - PACKAGE_CRAWLERS.map(async (Crawler) => { - const crawler = new Crawler(); - const packages = packagesByCrawler[crawler.packageRegistry]; - const docsByRegistry = await Promise.all( - packages.map(async (packageInfo) => { - try { - const details = await crawler.getPackageDetails(packageInfo); - if (!details.docsLink) { - return { - packageInfo, - error: `No documentation link found for ${packageInfo.name}`, - }; - } - return { - packageInfo, - details: { - ...details, - docsLink: details.docsLink, - docsLinkWarning: details.docsLink.includes("github.com") - ? "Github docs not supported, find the docs site" - : details.docsLink.includes("docs") - ? undefined - : "May not be a docs site, check the URL", - }, - }; - } catch (error) { - return { - packageInfo, - error: `Error getting package details for ${packageInfo.name}`, - }; - } - }), - ); - allDocsResults.push(...docsByRegistry); - }), - ); - return allDocsResults; -} diff --git a/core/indexing/docs/suggestions/packageCrawlers/Python.ts b/core/indexing/docs/suggestions/packageCrawlers/Python.ts deleted file mode 100644 index 3a617568f4..0000000000 --- a/core/indexing/docs/suggestions/packageCrawlers/Python.ts +++ /dev/null @@ -1,63 +0,0 @@ -import { PackageCrawler } from ".."; -import { - FilePathAndName, - PackageDetails, - PackageFilePathAndName, - ParsedPackageInfo, -} from "../../../.."; - -export class PythonPackageCrawler implements PackageCrawler { - packageRegistry = "pypi"; - - getPackageFiles(files: FilePathAndName[]): PackageFilePathAndName[] { - // For Python, we typically look for files like requirements.txt or Pipfile - return files - .filter( - (file) => file.name === "requirements.txt" || file.name === "Pipfile", - ) - .map((file) => ({ - ...file, - packageRegistry: "pypi", - })); - } - - parsePackageFile( - file: PackageFilePathAndName, - contents: string, - ): ParsedPackageInfo[] { - // Assume the fileContent is a string from a requirements.txt formatted file - return contents - .split("\n") - .map((line) => { - const [name, version] = line.split("=="); - return { name, version, packageFile: file, language: "py" }; - }) - .filter((pkg) => pkg.name && pkg.version); - } - - async getPackageDetails( - packageInfo: ParsedPackageInfo, - ): Promise { - // Fetch metadata from PyPI to find the documentation link - const response = await fetch( - `https://pypi.org/pypi/${packageInfo.name}/json`, - ); - if (!response.ok) { - throw new Error(`Could not fetch data for package ${packageInfo.name}`); - } - const data = await response.json(); - const homePage = data?.info?.home_page as string | undefined; - - return { - docsLink: - (data?.info?.project_urls?.Documentation as string | undefined) ?? - homePage, - title: data?.info?.name as string | undefined, - description: data?.info?.summary as string | undefined, - repo: - (data?.info?.project_urls?.Repository as string | undefined) ?? - homePage, - license: data?.info?.license as string | undefined, - }; - } -} diff --git a/core/indexing/docs/suggestions/packageCrawlers/TsJs.ts b/core/indexing/docs/suggestions/packageCrawlers/TsJs.ts deleted file mode 100644 index 3a9ef96c2b..0000000000 --- a/core/indexing/docs/suggestions/packageCrawlers/TsJs.ts +++ /dev/null @@ -1,77 +0,0 @@ -import { PackageCrawler } from ".."; -import { - FilePathAndName, - PackageDetails, - PackageFilePathAndName, - ParsedPackageInfo, -} from "../../../.."; - -export class NodePackageCrawler implements PackageCrawler { - packageRegistry = "npm"; - - getPackageFiles(files: FilePathAndName[]): PackageFilePathAndName[] { - // For Javascript/TypeScript, we look for package.json file - return files - .filter((file) => file.name === "package.json") - .map((file) => ({ - ...file, - packageRegistry: this.packageRegistry, - })); - } - - parsePackageFile( - file: PackageFilePathAndName, - contents: string, - ): ParsedPackageInfo[] { - // Parse the package.json content - const jsonData = JSON.parse(contents) as Record; - const dependencies = Object.entries(jsonData.dependencies || {}).concat( - Object.entries(jsonData.devDependencies || {}), - ); - - // Filter out types packages and check if typescript is present - let foundTypes = false; - const filtered = dependencies.filter(([name, _]) => { - if (name.startsWith("@types/")) { - foundTypes = true; - return false; - } - if (name.includes("typescript")) { - foundTypes = true; - } - return true; - }); - return filtered.map(([name, version]) => ({ - name, - version, - packageFile: file, - language: foundTypes ? "ts" : "js", - })); - } - - async getPackageDetails( - packageInfo: ParsedPackageInfo, - ): Promise { - const { name } = packageInfo; - // Fetch metadata from the NPM registry to find the documentation link - const response = await fetch(`https://registry.npmjs.org/${name}`); - if (!response.ok) { - throw new Error(`Could not fetch data for package ${name}`); - } - const data = await response.json(); - - // const dependencies = Object.keys(packageContentData.dependencies || {}) - // .concat(Object.keys(packageContentData.devDependencies || {})); - // const usesTypescript = dependencies.includes("typescript"); - - return { - docsLink: data.homepage as string | undefined, - title: name, // package.json doesn't have specific title field - description: data.description as string | undefined, - repo: Array.isArray(data.repository) - ? (data.respository[0]?.url as string | undefined) - : undefined, - license: data.license as string | undefined, - }; - } -} diff --git a/core/indexing/docs/suggestions/suggestions.test.ts b/core/indexing/docs/suggestions/suggestions.test.ts deleted file mode 100644 index 60b58caa6a..0000000000 --- a/core/indexing/docs/suggestions/suggestions.test.ts +++ /dev/null @@ -1,283 +0,0 @@ -// Generated by continue - -import { getAllSuggestedDocs } from "./index"; -import { testIde } from "../../../test/fixtures"; -import { - setUpTestDir, - tearDownTestDir, - addToTestDir, -} from "../../../test/testDir"; -import fetch, { RequestInfo } from "node-fetch"; - -jest.mock("node-fetch", undefined, { - virtual: false, -}); - -describe.skip("getAllSuggestedDocs", () => { - beforeEach(() => { - setUpTestDir(); - jest.clearAllMocks(); - }); - - afterEach(() => { - tearDownTestDir(); - jest.restoreAllMocks(); - }); - - it("should return package docs for JavaScript and Python projects", async () => { - // Set up test files - addToTestDir([ - [ - "package.json", - JSON.stringify({ - dependencies: { - express: "^4.17.1", - lodash: "^4.17.21", - }, - devDependencies: { - typescript: "^4.0.0", - }, - }), - ], - ["requirements.txt", "requests==2.25.1\nflask==1.1.2"], - ]); - - const mockedFetch = fetch as jest.MockedFunction; - mockedFetch.mockImplementation((url: URL | RequestInfo) => { - if (url.toString().includes("registry.npmjs.org/express")) { - return Promise.resolve({ - ok: true, - json: jest.fn().mockResolvedValue({ - homepage: "https://expressjs.com/", - name: "express", - description: "Fast, unopinionated, minimalist web framework", - license: "MIT", - }), - }) as any; - } else if (url.toString().includes("registry.npmjs.org/lodash")) { - return Promise.resolve({ - ok: true, - json: jest.fn().mockResolvedValue({ - homepage: "https://lodash.com/", - name: "lodash", - description: "Lodash modular utilities.", - license: "MIT", - }), - }) as any; - } else if (url.toString().includes("pypi.org/pypi/requests/json")) { - return Promise.resolve({ - ok: true, - json: jest.fn().mockResolvedValue({ - info: { - home_page: "https://docs.python-requests.org/", - name: "requests", - summary: "Python HTTP for Humans.", - license: "Apache 2.0", - }, - }), - }) as any; - } else if (url.toString().includes("pypi.org/pypi/flask/json")) { - return Promise.resolve({ - ok: true, - json: jest.fn().mockResolvedValue({ - info: { - home_page: "https://palletsprojects.com/p/flask/", - name: "flask", - summary: - "A simple framework for building complex web applications.", - license: "BSD-3-Clause", - }, - }), - }) as any; - } else { - return Promise.reject(new Error(`Unhandled URL: ${url}`)); - } - }); - - const results = await getAllSuggestedDocs(testIde); - - expect(results).toHaveLength(4); - expect(results).toEqual( - expect.arrayContaining([ - expect.objectContaining({ - packageInfo: expect.objectContaining({ name: "express" }), - details: expect.objectContaining({ - docsLink: "https://expressjs.com/", - }), - }), - expect.objectContaining({ - packageInfo: expect.objectContaining({ name: "lodash" }), - details: expect.objectContaining({ - docsLink: "https://lodash.com/", - }), - }), - expect.objectContaining({ - packageInfo: expect.objectContaining({ name: "requests" }), - details: expect.objectContaining({ - docsLink: "https://docs.python-requests.org/", - }), - }), - expect.objectContaining({ - packageInfo: expect.objectContaining({ name: "flask" }), - details: expect.objectContaining({ - docsLink: "https://palletsprojects.com/p/flask/", - }), - }), - ]), - ); - - // Verify no errors are present - results.forEach((result) => { - expect(result.error).toBeUndefined(); - }); - }); - - it("should handle packages without documentation links", async () => { - addToTestDir([ - [ - "package.json", - JSON.stringify({ - dependencies: { - "no-docs-package": "^1.0.0", - }, - }), - ], - ]); - - // Mock fetch - const mockedFetch = fetch as jest.MockedFunction; - mockedFetch.mockImplementation((url: RequestInfo | URL) => { - if (url.toString().includes("registry.npmjs.org/no-docs-package")) { - return Promise.resolve({ - ok: true, - json: jest.fn().mockResolvedValue({ - name: "no-docs-package", - description: "A package without docs", - license: "MIT", - // No homepage provided - }), - }) as any; - } else { - return Promise.reject(new Error(`Unhandled URL: ${url}`)); - } - }); - - const results = await getAllSuggestedDocs(testIde); - - expect(results).toHaveLength(1); - expect(results[0].error).toContain( - "No documentation link found for no-docs-package", - ); - expect(results[0].details).toBeUndefined(); - }); - - it("should handle errors when fetching package details", async () => { - addToTestDir([ - [ - "package.json", - JSON.stringify({ - dependencies: { - "error-package": "^1.0.0", - }, - }), - ], - ]); - - // Mock fetch - const mockedFetch = fetch as jest.MockedFunction; - mockedFetch.mockImplementation((url: URL | RequestInfo) => { - if (url.toString().includes("registry.npmjs.org/error-package")) { - return Promise.resolve({ - ok: false, - }) as any; - } else { - return Promise.reject(new Error(`Unhandled URL: ${url}`)); - } - }); - - const results = await getAllSuggestedDocs(testIde); - - expect(results).toHaveLength(1); - expect(results[0].error).toContain( - "Error getting package details for error-package", - ); - expect(results[0].details).toBeUndefined(); - }); - - it("should handle workspaces with no package files", async () => { - const results = await getAllSuggestedDocs(testIde); - - expect(results).toEqual([]); - }); - - it("should handle packages with GitHub documentation links", async () => { - addToTestDir([ - [ - "package.json", - JSON.stringify({ - dependencies: { - "github-docs-package": "^1.0.0", - }, - }), - ], - ]); - - // Mock fetch - const mockedFetch = fetch as jest.MockedFunction; - mockedFetch.mockImplementation((url: URL | RequestInfo) => { - if (url.toString().includes("registry.npmjs.org/github-docs-package")) { - return Promise.resolve({ - ok: true, - json: jest.fn().mockResolvedValue({ - homepage: "https://github.com/user/repo", - name: "github-docs-package", - description: "A package with GitHub docs", - license: "MIT", - }), - }) as any; - } else { - return Promise.reject(new Error(`Unhandled URL: ${url}`)); - } - }); - - const results = await getAllSuggestedDocs(testIde); - - expect(results).toHaveLength(1); - expect(results[0].details?.docsLink).toBe("https://github.com/user/repo"); - expect(results[0].details?.docsLinkWarning).toBe( - "Github docs not supported, find the docs site", - ); - }); - - it("should handle packages with non-docs links", async () => { - addToTestDir([["requirements.txt", "non-docs-package==1.0.0"]]); - - // Mock fetch - const mockedFetch = fetch as jest.MockedFunction; - mockedFetch.mockImplementation((url: URL | RequestInfo) => { - if (url.toString().includes("pypi.org/pypi/non-docs-package/json")) { - return Promise.resolve({ - ok: true, - json: jest.fn().mockResolvedValue({ - info: { - home_page: "https://somewebsite.com", - name: "non-docs-package", - summary: "A package with non-docs homepage", - license: "MIT", - }, - }), - }) as any; - } else { - return Promise.reject(new Error(`Unhandled URL: ${url}`)); - } - }); - - const results = await getAllSuggestedDocs(testIde); - - expect(results).toHaveLength(1); - expect(results[0].details?.docsLink).toBe("https://somewebsite.com"); - expect(results[0].details?.docsLinkWarning).toBe( - "May not be a docs site, check the URL", - ); - }); -}); diff --git a/core/protocol/passThrough.ts b/core/protocol/passThrough.ts index b4cf5185b7..9fcbeda83f 100644 --- a/core/protocol/passThrough.ts +++ b/core/protocol/passThrough.ts @@ -52,7 +52,6 @@ export const WEBVIEW_TO_CORE_PASS_THROUGH: (keyof ToCoreFromWebviewProtocol)[] = "indexing/reindex", "indexing/abort", "indexing/setPaused", - "docs/getSuggestedDocs", "docs/initStatuses", "docs/getDetails", // @@ -81,7 +80,6 @@ export const CORE_TO_WEBVIEW_PASS_THROUGH: (keyof ToWebviewFromCoreProtocol)[] = "setTTSActive", "getWebviewHistoryLength", "getCurrentSessionId", - "docs/suggestions", "didCloseFiles", "didSelectOrganization", ]; diff --git a/core/protocol/webview.ts b/core/protocol/webview.ts index 45c3fb424b..329f71bdca 100644 --- a/core/protocol/webview.ts +++ b/core/protocol/webview.ts @@ -37,6 +37,5 @@ export type ToWebviewFromIdeOrCoreProtocol = { setTTSActive: [boolean, void]; getWebviewHistoryLength: [undefined, number]; getCurrentSessionId: [undefined, string]; - "docs/suggestions": [PackageDocsResult[], void]; "jetbrains/setColors": [Record, void]; }; diff --git a/extensions/intellij/src/main/kotlin/com/github/continuedev/continueintellijextension/constants/MessageTypes.kt b/extensions/intellij/src/main/kotlin/com/github/continuedev/continueintellijextension/constants/MessageTypes.kt index 7bce39c819..665b393c04 100644 --- a/extensions/intellij/src/main/kotlin/com/github/continuedev/continueintellijextension/constants/MessageTypes.kt +++ b/extensions/intellij/src/main/kotlin/com/github/continuedev/continueintellijextension/constants/MessageTypes.kt @@ -69,7 +69,6 @@ class MessageTypes { "setTTSActive", "getWebviewHistoryLength", "getCurrentSessionId", - "docs/suggestions", "didCloseFiles", "didSelectOrganization" ) @@ -121,7 +120,6 @@ class MessageTypes { "indexing/reindex", "indexing/abort", "indexing/setPaused", - "docs/getSuggestedDocs", "docs/initStatuses", "docs/getDetails", // diff --git a/extensions/vscode/scripts/esbuild.js b/extensions/vscode/scripts/esbuild.js index e44fc60aff..d8a9d4e681 100644 --- a/extensions/vscode/scripts/esbuild.js +++ b/extensions/vscode/scripts/esbuild.js @@ -1,6 +1,7 @@ -const esbuild = require("esbuild"); const fs = require("fs"); +const esbuild = require("esbuild"); + const flags = process.argv.slice(2); const esbuildConfig = { @@ -59,9 +60,9 @@ const esbuildConfig = { // The watcher automatically notices changes to source files // so the only thing it needs to be notified about is if the // output file gets removed. - if (fs.existsSync (outFile)) { - console.log("VS Code Extension esbuild up to date"); - return; + if (fs.existsSync(outFile)) { + console.log("VS Code Extension esbuild up to date"); + return; } fs.watchFile(outFile, (current, previous) => { diff --git a/gui/src/components/dialogs/AddDocsDialog.tsx b/gui/src/components/dialogs/AddDocsDialog.tsx index eb3d3bcbb0..d421d94c48 100644 --- a/gui/src/components/dialogs/AddDocsDialog.tsx +++ b/gui/src/components/dialogs/AddDocsDialog.tsx @@ -1,26 +1,17 @@ -import { - CheckIcon, - InformationCircleIcon, - PencilIcon, - PlusIcon, -} from "@heroicons/react/24/outline"; -import { IndexingStatus, PackageDocsResult, SiteIndexingConfig } from "core"; -import preIndexedDocs from "core/indexing/docs/preIndexedDocs"; +import { InformationCircleIcon } from "@heroicons/react/24/outline"; +import { IndexingStatus, SiteIndexingConfig } from "core"; import { usePostHog } from "posthog-js/react"; import { useContext, useLayoutEffect, useMemo, useRef, useState } from "react"; import { useDispatch } from "react-redux"; import { Input, SecondaryButton } from ".."; import { IdeMessengerContext } from "../../context/IdeMessenger"; import { useAppSelector } from "../../redux/hooks"; -import { updateConfig } from "../../redux/slices/configSlice"; import { updateIndexingStatus } from "../../redux/slices/indexingSlice"; import { setDialogMessage, setShowDialog } from "../../redux/slices/uiSlice"; -import FileIcon from "../FileIcon"; import { ToolTip } from "../gui/Tooltip"; import DocsIndexingPeeks from "../indexing/DocsIndexingPeeks"; function AddDocsDialog() { - const config = useAppSelector((store) => store.config.config); const posthog = usePostHog(); const dispatch = useDispatch(); @@ -42,36 +33,6 @@ function AddDocsDialog() { ); }, [indexingStatuses]); - const docsSuggestions = useAppSelector((store) => store.misc.docsSuggestions); - const configDocs = useAppSelector((store) => store.config.config.docs); - - const sortedDocsSuggestions = useMemo(() => { - const docsFromConfig = configDocs ?? []; - // Don't show suggestions that are already in the config, indexing, and/or pre-indexed - const filtered = docsSuggestions.filter((sug) => { - const startUrl = sug.details?.docsLink; - return ( - !docsFromConfig.find((d) => d.startUrl === startUrl) && - !docsIndexingStatuses.find((s) => s.id === startUrl) && - (startUrl ? !preIndexedDocs[startUrl] : true) - ); - }); - - filtered.sort((a, b) => { - const rank = (result: PackageDocsResult) => { - if (result.error) { - return 2; - } else if (result.details?.docsLinkWarning) { - return 1; - } else { - return 0; - } - }; - return rank(a) - rank(b); - }); - return filtered; - }, [docsSuggestions, configDocs, docsIndexingStatuses]); - const isFormValid = startUrl && title; useLayoutEffect(() => { @@ -118,59 +79,6 @@ function AddDocsDialog() { ); } - const handleSelectSuggestion = (docsResult: PackageDocsResult) => { - if (docsResult.error || !docsResult.details) { - setTitle(docsResult.packageInfo.name); - setStartUrl(""); - urlRef.current?.focus(); - return; - } - const suggestedTitle = - docsResult.details.title ?? docsResult.packageInfo.name; - - if (docsResult.details?.docsLinkWarning) { - setTitle(suggestedTitle); - setStartUrl(docsResult.details.docsLink); - urlRef.current?.focus(); - return; - } - const siteIndexingConfig: SiteIndexingConfig = { - startUrl: docsResult.details.docsLink, - title: suggestedTitle, - faviconUrl: undefined, - }; - - ideMessenger.post("context/addDocs", siteIndexingConfig); - - posthog.capture("add_docs_gui", { url: startUrl }); - - // Optimistic status update - dispatch( - updateConfig({ - ...config, - docs: [ - ...(config.docs?.filter( - (doc) => doc.startUrl !== docsResult.details.docsLink, - ) ?? []), - { - startUrl: docsResult.details.docsLink, - title: suggestedTitle, - faviconUrl: undefined, - }, - ], - }), - updateIndexingStatus({ - type: "docs", - description: "Initializing", - id: docsResult.details.docsLink, - progress: 0, - status: "indexing", - title: docsResult.details.title ?? docsResult.packageInfo.name, - url: docsResult.details.docsLink, - }), - ); - }; - return (
@@ -179,91 +87,10 @@ function AddDocsDialog() {

For the @docs context provider

- {!!sortedDocsSuggestions.length && ( -

Suggestions

- )} -
- {sortedDocsSuggestions.map((docsResult) => { - const { error, details } = docsResult; - const { language, name, version } = docsResult.packageInfo; - const id = `${language}-${name}-${version}`; - return ( -
{ - handleSelectSuggestion(docsResult); - }} - > -
- {error || details?.docsLinkWarning ? ( -
- - - This may not be a docs page - -
- ) : ( - - )} -
-
-
- -
- {name} -
-
- {error || !details?.docsLink ? ( - - No docs link found - - ) : ( -
- {/*
- -
*/} -

{ - e.stopPropagation(); - ideMessenger.post("openUrl", details.docsLink); - }} - > - {details.docsLink} -

-
- )} -
-
{ - e.stopPropagation(); - }} - > - - -

{`Version: ${version}`}

-

{`Found in ${docsResult.packageInfo.packageFile.path}`}

-
-
-
- ); - })} -
-
-