UNPKG

@langchain/community

Version:
1 lines • 32 kB
{"version":3,"file":"github.cjs","names":["binaryExtensions","name: string","extname","BaseDocumentLoader","githubUrl: string","UnknownHandling","AsyncCaller","url: string","documents: Document[]","Document","gitmodulesContent: string","submoduleInfo: SubmoduleInfo","path: string","fileType: string","file: GithubFile","files: GithubFile[]","currentDirectoryFilePromises: Promise<GetContentResponse>[]","currentDirectoryDirectoryPromises: Promise<\n Promise<GetContentResponse>[]\n >[]","curDirDirectories: Promise<GetContentResponse>[][]","message: string"],"sources":["../../../src/document_loaders/web/github.ts"],"sourcesContent":["import ignore, { Ignore } from \"ignore\";\nimport binaryExtensions from \"binary-extensions\";\n\nimport { Document } from \"@langchain/core/documents\";\nimport { getEnvironmentVariable } from \"@langchain/core/utils/env\";\nimport {\n AsyncCaller,\n AsyncCallerParams,\n} from \"@langchain/core/utils/async_caller\";\nimport { BaseDocumentLoader } from \"@langchain/core/document_loaders/base\";\nimport { UnknownHandling } from \"@langchain/classic/document_loaders/fs/directory\";\nimport { extname } from \"../../utils/extname.js\";\n\nconst extensions = /* #__PURE__ */ new Set(binaryExtensions);\n\n/**\n * A function that checks if a file path is a binary file based on its\n * extension.\n * @param name The file path to check.\n * @returns A boolean indicating whether the file path is a binary file.\n */\nfunction isBinaryPath(name: string) {\n return extensions.has(extname(name).slice(1).toLowerCase());\n}\n\n/**\n * An interface that represents a file in a GitHub repository. It has\n * properties for the file name, path, SHA, size, URLs, type, and links.\n */\nexport interface GithubFile {\n name: string;\n path: string;\n sha: string;\n size: number;\n url: string;\n html_url: string;\n git_url: string;\n download_url: string;\n type: string;\n _links: {\n self: string;\n git: string;\n html: string;\n };\n}\n\n/**\n * An interface that represents the response from fetching the content of\n * a file. It has properties for the file contents and metadata.\n */\ninterface GetContentResponse {\n contents: string;\n metadata: { source: string; repository: string; branch: string };\n}\n\n/**\n * An interface describing the submodules of a Git repository.\n */\ninterface SubmoduleInfo {\n name: string;\n path: string;\n url: string;\n ref: string;\n}\n\n/**\n * An interface that represents the parameters for the GithubRepoLoader\n * class. It extends the AsyncCallerParams interface and adds additional\n * properties specific to the GitHub repository loader.\n */\nexport interface GithubRepoLoaderParams extends AsyncCallerParams {\n /**\n * The base URL of the GitHub instance.\n * To be used when you are not targeting github.com, e.g. a GitHub Enterprise instance.\n */\n baseUrl?: string;\n /**\n * The API endpoint URL of the GitHub instance.\n * To be used when you are not targeting github.com, e.g. a GitHub Enterprise instance.\n */\n apiUrl?: string;\n branch?: string;\n recursive?: boolean;\n /**\n * Set to true to recursively process submodules. Is only effective, when recursive=true.\n */\n processSubmodules?: boolean;\n unknown?: UnknownHandling;\n accessToken?: string;\n ignoreFiles?: (string | RegExp)[];\n ignorePaths?: string[];\n verbose?: boolean;\n /**\n * The maximum number of concurrent calls that can be made. Defaults to 2.\n */\n maxConcurrency?: number;\n /**\n * The maximum number of retries that can be made for a single call,\n * with an exponential backoff between each attempt. Defaults to 2.\n */\n maxRetries?: number;\n}\n\n/**\n * A class that extends the BaseDocumentLoader and implements the\n * GithubRepoLoaderParams interface. It represents a document loader for\n * loading files from a GitHub repository.\n */\nexport class GithubRepoLoader\n extends BaseDocumentLoader\n implements GithubRepoLoaderParams\n{\n public baseUrl: string;\n\n public apiUrl: string;\n\n private readonly owner: string;\n\n private readonly repo: string;\n\n private readonly initialPath: string;\n\n private headers: Record<string, string> = {};\n\n public branch: string;\n\n public recursive: boolean;\n\n public processSubmodules: boolean;\n\n public unknown: UnknownHandling;\n\n public accessToken?: string;\n\n public ignoreFiles: (string | RegExp)[];\n\n public ignore?: Ignore;\n\n public verbose?: boolean;\n\n public maxConcurrency?: number;\n\n public maxRetries?: number;\n\n protected caller: AsyncCaller;\n\n public ignorePaths?: string[];\n\n private submoduleInfos: SubmoduleInfo[];\n\n constructor(\n githubUrl: string,\n {\n accessToken = getEnvironmentVariable(\"GITHUB_ACCESS_TOKEN\"),\n baseUrl = \"https://github.com\",\n apiUrl = \"https://api.github.com\",\n branch = \"main\",\n recursive = true,\n processSubmodules = false,\n unknown = UnknownHandling.Warn,\n ignoreFiles = [],\n ignorePaths,\n verbose = false,\n maxConcurrency = 2,\n maxRetries = 2,\n ...rest\n }: GithubRepoLoaderParams = {}\n ) {\n super();\n this.baseUrl = baseUrl;\n this.apiUrl = apiUrl;\n const { owner, repo, path } = this.extractOwnerAndRepoAndPath(githubUrl);\n this.owner = owner;\n this.repo = repo;\n this.initialPath = path;\n this.branch = branch;\n this.recursive = recursive;\n // processing submodules without processing contents of other directories makes no sense\n if (processSubmodules && !recursive) {\n throw new Error(\n `Input property \"recursive\" must be true if \"processSubmodules\" is true.`\n );\n }\n this.processSubmodules = processSubmodules;\n this.unknown = unknown;\n this.accessToken = accessToken;\n this.ignoreFiles = ignoreFiles;\n this.verbose = verbose;\n this.maxConcurrency = maxConcurrency;\n this.maxRetries = maxRetries;\n this.headers = {\n \"User-Agent\": \"langchain\",\n };\n this.caller = new AsyncCaller({\n maxConcurrency,\n maxRetries,\n ...rest,\n });\n this.ignorePaths = ignorePaths;\n if (ignorePaths) {\n this.ignore = ignore().add(ignorePaths);\n }\n if (this.accessToken) {\n this.headers = {\n ...this.headers,\n Authorization: `Bearer ${this.accessToken}`,\n };\n }\n }\n\n /**\n * Extracts the owner, repository, and path from a GitHub URL.\n * @param url The GitHub URL to extract information from.\n * @returns An object containing the owner, repository, and path extracted from the GitHub URL.\n */\n private extractOwnerAndRepoAndPath(url: string): {\n owner: string;\n repo: string;\n path: string;\n } {\n const match = url.match(\n new RegExp(`${this.baseUrl}/([^/]+)/([^/]+)(/tree/[^/]+/(.+))?`, \"i\")\n );\n\n if (!match) {\n throw new Error(\"Invalid GitHub URL format.\");\n }\n\n return { owner: match[1], repo: match[2], path: match[4] || \"\" };\n }\n\n /**\n * Fetches the files from the GitHub repository and creates Document\n * instances for each file. It also handles error handling based on the\n * unknown handling option.\n * @returns A promise that resolves to an array of Document instances.\n */\n public async load(): Promise<Document[]> {\n this.log(\n `Loading documents from ${this.baseUrl}/${this.owner}/${this.repo}/${this.initialPath}...`\n );\n // process repository without submodules\n const documents: Document[] = (await this.processRepo()).map(\n (fileResponse) =>\n new Document({\n pageContent: fileResponse.contents,\n metadata: fileResponse.metadata,\n })\n );\n if (this.processSubmodules) {\n // process submodules\n await this.getSubmoduleInfo();\n for (const submoduleInfo of this.submoduleInfos) {\n documents.push(...(await this.loadSubmodule(submoduleInfo)));\n }\n }\n return documents;\n }\n\n /**\n * Asynchronously streams documents from the entire GitHub repository.\n * It is suitable for situations where processing large repositories in a memory-efficient manner is required.\n * @yields Yields a Promise that resolves to a Document object for each file or submodule content found in the repository.\n */\n public async *loadAsStream(): AsyncGenerator<Document, void, undefined> {\n this.log(\n `Loading documents from ${this.baseUrl}/${this.owner}/${this.repo}/${this.initialPath}...`\n );\n yield* await this.processRepoAsStream(this.initialPath);\n\n if (!this.processSubmodules) {\n return;\n }\n\n await this.getSubmoduleInfo();\n for (const submoduleInfo of this.submoduleInfos) {\n yield* await this.loadSubmoduleAsStream(submoduleInfo);\n }\n }\n\n /**\n * Loads the information about Git submodules from the repository, if available.\n */\n private async getSubmoduleInfo(): Promise<void> {\n this.log(\"Loading info about submodules...\");\n // we have to fetch the files of the root directory to get the download url of the .gitmodules file\n // however, we cannot reuse the files retrieved in processRepo() as initialPath may be != \"\"\n // so it may be that we end up fetching this file list twice\n const repoFiles = await this.fetchRepoFiles(\"\");\n const gitmodulesFile = repoFiles.filter(\n ({ name }) => name === \".gitmodules\"\n )?.[0];\n if (gitmodulesFile) {\n const gitmodulesContent = await this.fetchFileContent({\n download_url: gitmodulesFile.download_url,\n } as GithubFile);\n this.submoduleInfos = await this.parseGitmodules(gitmodulesContent);\n } else {\n this.submoduleInfos = [];\n }\n this.log(`Found ${this.submoduleInfos.length} submodules:`);\n for (const submoduleInfo of this.submoduleInfos) {\n this.log(JSON.stringify(submoduleInfo));\n }\n }\n\n /**\n * Parses the given content of a .gitmodules file. Furthermore, queries the current SHA ref of all submodules.\n * Returns the submodule information as array.\n * @param gitmodulesContent the content of a .gitmodules file\n */\n private async parseGitmodules(\n gitmodulesContent: string\n ): Promise<SubmoduleInfo[]> {\n let validGitmodulesContent = gitmodulesContent;\n // in case the .gitmodules file does not end with a newline, we add one to make the regex work\n if (!validGitmodulesContent.endsWith(\"\\n\")) {\n validGitmodulesContent += \"\\n\";\n }\n // catches the initial line of submodule entries\n const submodulePattern = /\\[submodule \"(.*?)\"]\\n((\\s+.*?\\s*=\\s*.*?\\n)*)/g;\n // catches the properties of a submodule\n const keyValuePattern = /\\s+(.*?)\\s*=\\s*(.*?)\\s/g;\n\n const submoduleInfos = [];\n for (const [, name, propertyLines] of validGitmodulesContent.matchAll(\n submodulePattern\n )) {\n if (!name || !propertyLines) {\n throw new Error(\"Could not parse submodule entry\");\n }\n const submodulePropertyLines = propertyLines.matchAll(keyValuePattern);\n let path;\n let url;\n for (const [, key, value] of submodulePropertyLines) {\n if (!key || !value) {\n throw new Error(\n `Could not parse key/value pairs for submodule ${name}`\n );\n }\n switch (key) {\n case \"path\":\n path = value;\n break;\n case \"url\":\n url = value;\n if (url.endsWith(\".git\")) {\n url = url.substring(0, url.length - 4);\n }\n break;\n default:\n // ignoring unused keys\n }\n }\n if (!path || !url) {\n throw new Error(`Missing properties for submodule ${name}`);\n }\n // fetch the current ref of the submodule\n const files = await this.fetchRepoFiles(path);\n const submoduleInfo: SubmoduleInfo = {\n name,\n path,\n url,\n ref: files[0].sha,\n };\n submoduleInfos.push(submoduleInfo);\n }\n return submoduleInfos;\n }\n\n /**\n * Loads the documents of the given submodule. Uses the same parameters as for the current repository.\n * External submodules, i.e. submodules pointing to another GitHub instance, are ignored.\n * @param submoduleInfo the info about the submodule to be loaded\n */\n private async loadSubmodule(\n submoduleInfo: SubmoduleInfo\n ): Promise<Document[]> {\n if (!submoduleInfo.url.startsWith(this.baseUrl)) {\n this.log(`Ignoring external submodule ${submoduleInfo.url}.`);\n return [];\n } else if (!submoduleInfo.path.startsWith(this.initialPath)) {\n this.log(\n `Ignoring submodule ${submoduleInfo.url}, as it is not on initial path.`\n );\n return [];\n } else {\n this.log(\n `Accessing submodule ${submoduleInfo.name} (${submoduleInfo.url})...`\n );\n return new GithubRepoLoader(submoduleInfo.url, {\n accessToken: this.accessToken,\n apiUrl: this.apiUrl,\n baseUrl: this.baseUrl,\n branch: submoduleInfo.ref,\n recursive: this.recursive,\n processSubmodules: this.processSubmodules,\n unknown: this.unknown,\n ignoreFiles: this.ignoreFiles,\n ignorePaths: this.ignorePaths,\n verbose: this.verbose,\n maxConcurrency: this.maxConcurrency,\n maxRetries: this.maxRetries,\n }).load();\n }\n }\n\n /**\n * Asynchronously processes and streams the contents of a specified submodule in the GitHub repository.\n * @param submoduleInfo the info about the submodule to be loaded\n * @yields Yields a Promise that resolves to a Document object for each file found in the submodule.\n */\n private async *loadSubmoduleAsStream(\n submoduleInfo: SubmoduleInfo\n ): AsyncGenerator<Document, void, undefined> {\n if (!submoduleInfo.url.startsWith(this.baseUrl)) {\n this.log(`Ignoring external submodule ${submoduleInfo.url}.`);\n yield* [];\n }\n\n if (!submoduleInfo.path.startsWith(this.initialPath)) {\n this.log(\n `Ignoring submodule ${submoduleInfo.url}, as it is not on initial path.`\n );\n yield* [];\n }\n\n this.log(\n `Accessing submodule ${submoduleInfo.name} (${submoduleInfo.url})...`\n );\n const submoduleLoader = new GithubRepoLoader(submoduleInfo.url, {\n accessToken: this.accessToken,\n baseUrl: this.baseUrl,\n apiUrl: this.apiUrl,\n branch: submoduleInfo.ref,\n recursive: this.recursive,\n processSubmodules: this.processSubmodules,\n unknown: this.unknown,\n ignoreFiles: this.ignoreFiles,\n ignorePaths: this.ignorePaths,\n verbose: this.verbose,\n maxConcurrency: this.maxConcurrency,\n maxRetries: this.maxRetries,\n });\n\n yield* await submoduleLoader.processRepoAsStream(submoduleInfo.path);\n }\n\n /**\n * Determines whether a file or directory should be ignored based on its\n * path and type.\n * @param path The path of the file or directory.\n * @param fileType The type of the file or directory.\n * @returns A boolean indicating whether the file or directory should be ignored.\n */\n protected shouldIgnore(path: string, fileType: string): boolean {\n if (fileType !== \"dir\" && isBinaryPath(path)) {\n return true;\n }\n if (this.ignore !== undefined) {\n return this.ignore.ignores(path);\n }\n return (\n fileType !== \"dir\" &&\n this.ignoreFiles.some((pattern) => {\n if (typeof pattern === \"string\") {\n return path === pattern;\n }\n\n try {\n return pattern.test(path);\n } catch {\n throw new Error(`Unknown ignore file pattern: ${pattern}`);\n }\n })\n );\n }\n\n /**\n * Takes the file info and wrap it in a promise that will resolve to the file content and metadata\n * @param file\n * @returns\n */\n private async fetchFileContentWrapper(\n file: GithubFile\n ): Promise<GetContentResponse> {\n const fileContent = await this.fetchFileContent(file).catch((error) => {\n this.handleError(`Failed wrap file content: ${file}, ${error}`);\n });\n return {\n contents: fileContent || \"\",\n metadata: {\n source: file.path,\n repository: `${this.baseUrl}/${this.owner}/${this.repo}`,\n branch: this.branch,\n },\n };\n }\n\n /**\n * Maps a list of files / directories to a list of promises that will fetch the file / directory contents\n */\n private async getCurrentDirectoryFilePromises(\n files: GithubFile[]\n ): Promise<Promise<GetContentResponse>[]> {\n const currentDirectoryFilePromises: Promise<GetContentResponse>[] = [];\n // Directories have nested files / directories, which is why this is a list of promises of promises\n const currentDirectoryDirectoryPromises: Promise<\n Promise<GetContentResponse>[]\n >[] = [];\n\n for (const file of files) {\n if (file.type !== \"dir\" && this.shouldIgnore(file.path, file.type)) {\n continue;\n }\n if (file.type === \"file\" && file.size === 0) {\n // this is a submodule. ignoring for the moment. submodule processing is done separately\n continue;\n }\n if (file.type !== \"dir\") {\n try {\n currentDirectoryFilePromises.push(this.fetchFileContentWrapper(file));\n } catch (e) {\n this.handleError(`Failed to fetch file content: ${file.path}, ${e}`);\n }\n } else if (this.recursive) {\n currentDirectoryDirectoryPromises.push(\n this.processDirectory(file.path)\n );\n }\n }\n\n const curDirDirectories: Promise<GetContentResponse>[][] =\n await Promise.all(currentDirectoryDirectoryPromises);\n\n return [...currentDirectoryFilePromises, ...curDirDirectories.flat()];\n }\n\n /**\n * Begins the process of fetching the contents of the repository\n */\n private async processRepo(): Promise<GetContentResponse[]> {\n try {\n // Get the list of file / directory names in the root directory\n const files = await this.fetchRepoFiles(this.initialPath);\n // Map the file / directory paths to promises that will fetch the file / directory contents\n const currentDirectoryFilePromises =\n await this.getCurrentDirectoryFilePromises(files);\n return Promise.all(currentDirectoryFilePromises);\n } catch (error) {\n this.handleError(\n `Failed to process directory: ${this.initialPath}, ${error}`\n );\n return Promise.reject(error);\n }\n }\n\n /**\n * Asynchronously processes the contents of the entire GitHub repository,\n * streaming each file as a Document object.\n * @param path The path of the directory to process.\n * @yields Yields a Promise that resolves to a Document object for each file found in the repository.\n */\n private async *processRepoAsStream(\n path: string\n ): AsyncGenerator<Document, void, undefined> {\n const files = await this.fetchRepoFiles(path);\n for (const file of files) {\n if (file.type !== \"dir\" && this.shouldIgnore(file.path, file.type)) {\n continue;\n }\n\n if (file.type === \"file\") {\n try {\n const fileResponse = await this.fetchFileContentWrapper(file);\n\n yield new Document({\n pageContent: fileResponse.contents,\n metadata: fileResponse.metadata,\n });\n } catch (error) {\n this.handleError(\n `Failed to fetch file content: ${file.path}, ${error}`\n );\n }\n } else if (this.recursive) {\n yield* await this.processDirectoryAsStream(file.path);\n }\n }\n }\n\n /**\n * Fetches the contents of a directory and maps the file / directory paths\n * to promises that will fetch the file / directory contents.\n * @param path The path of the directory to process.\n * @returns A promise that resolves to an array of promises that will fetch the file / directory contents.\n */\n private async processDirectory(\n path: string\n ): Promise<Promise<GetContentResponse>[]> {\n try {\n const files = await this.fetchRepoFiles(path);\n return this.getCurrentDirectoryFilePromises(files);\n } catch (error) {\n this.handleError(`Failed to process directory: ${path}, ${error}`);\n return Promise.reject(error);\n }\n }\n\n /**\n * Asynchronously processes the contents of a given directory in the GitHub repository,\n * streaming each file as a Document object.\n * @param path The path of the directory to process.\n * @yields Yields a Promise that resolves to a Document object for each file in the directory.\n */\n private async *processDirectoryAsStream(\n path: string\n ): AsyncGenerator<Document, void, undefined> {\n const files = await this.fetchRepoFiles(path);\n\n for (const file of files) {\n if (file.type !== \"dir\" && this.shouldIgnore(file.path, file.type)) {\n continue;\n }\n\n if (file.type === \"file\") {\n try {\n const fileResponse = await this.fetchFileContentWrapper(file);\n\n yield new Document({\n pageContent: fileResponse.contents,\n metadata: fileResponse.metadata,\n });\n } catch {\n this.handleError(`Failed to fetch file content: ${file.path}`);\n }\n } else if (this.recursive) {\n yield* await this.processDirectoryAsStream(file.path);\n }\n }\n }\n\n /**\n * Fetches the files from a GitHub repository.\n * If the path denotes a single file, the resulting array contains only one element.\n * @param path The path of the repository to fetch the files from.\n * @returns A promise that resolves to an array of GithubFile instances.\n */\n private async fetchRepoFiles(path: string): Promise<GithubFile[]> {\n const url = `${this.apiUrl}/repos/${this.owner}/${\n this.repo\n }/contents/${encodeURIComponent(path)}?ref=${this.branch}`;\n return this.caller.call(async () => {\n this.log(`Fetching ${url}`);\n const response = await fetch(url, { headers: this.headers });\n const data = await response.json();\n if (!response.ok) {\n throw new Error(\n `Unable to fetch repository files: ${\n response.status\n } ${JSON.stringify(data)}`\n );\n }\n\n if (Array.isArray(data)) {\n return data as GithubFile[];\n } else {\n return [data as GithubFile];\n }\n });\n }\n\n /**\n * Fetches the content of a file from a GitHub repository.\n * @param file The file to fetch the content from.\n * @returns A promise that resolves to the content of the file.\n */\n private async fetchFileContent(file: GithubFile): Promise<string> {\n return this.caller.call(async () => {\n this.log(`Fetching ${file.download_url}`);\n const response = await fetch(file.download_url, {\n headers: this.headers,\n });\n return response.text();\n });\n }\n\n /**\n * Handles errors based on the unknown handling option.\n * @param message The error message.\n * @returns void\n */\n private handleError(message: string): void {\n switch (this.unknown) {\n case UnknownHandling.Ignore:\n break;\n case UnknownHandling.Warn:\n console.warn(message);\n break;\n case UnknownHandling.Error:\n throw new Error(message);\n default:\n throw new Error(`Unknown unknown handling: ${this.unknown}`);\n }\n }\n\n /**\n * Logs the given message to the console, if parameter 'verbose' is set to true.\n * @param message the message to be logged.\n */\n private log(message: string): void {\n if (this.verbose) {\n console.log(message);\n }\n }\n}\n"],"mappings":"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"}