diff --git a/.github/workflows/ai-pr-reviewer.yml b/.github/workflows/ai-pr-reviewer.yml new file mode 100644 index 00000000..27a1139f --- /dev/null +++ b/.github/workflows/ai-pr-reviewer.yml @@ -0,0 +1,75 @@ +name: Code Review + +permissions: + contents: read + pull-requests: write + +on: + pull_request: + types: [opened] + branches-ignore: + - main + pull_request_review_comment: + types: [created] + +concurrency: + group: ${{ github.repository }}-${{ github.event.number || github.head_ref || github.sha }}-${{ github.workflow }}-${{ github.event_name == 'pull_request_review_comment' && 'pr_comment' || 'pr' }} + cancel-in-progress: ${{ github.event_name != 'pull_request_review_comment' }} + +jobs: + review: + runs-on: ubuntu-latest + steps: + - uses: nishihara-shinya/ai-pr-reviewer@v1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + AZURE_OPENAI_API_VERSION: '2023-09-01-preview' + BASE_URL: 'https://azurite-openai-01.openai.azure.com/' + with: + debug: true + review_comment_lgtm: false + openai_light_model: gpt-3.5-turbo + openai_heavy_model: gpt-3.5-turbo + language: ja-JP + system_message: | + あなたは `@openai` (a.k.a. `github-actions[bot]`) です。 + あなたの目的は、経験豊富なソフトウェアエンジニアとして、PullRequestの徹底的なレビューを日本語で提供することです。 + 以下のような重要な部分を改善するためのコードスニペットを提案すること: + - ロジック + - セキュリティ + - パフォーマンス + - レースコンディション + - 一貫性 + - エラー処理 + - 保守性 + - モジュール性 + - 複雑性 + - 最適化 + + 明示的に要求された場合を除き、些細なコードスタイルの問題、コメントの不足、ドキュメントの欠落についてコメントしたり、称賛したりすることは控えること。 + コード全体の品質を向上させるために、重大な懸念事項を特定して解決することに集中し、些細な問題は無視すること。 + + 注意: あなたの知識は古いかもしれないので、APIやメソッドが使用されていないように見えても、コミットされたユーザーコードを信頼してください。 + summarize: | + 最終的な回答を `markdown` フォーマットで以下の内容で書いてください: + + - 高レベルの要約(特定のファイルではなく、全体的な変更点についてのコメント日本語200文字以内) + - ファイルとその要約のtableを書くこと + - 同じような変更点のあるファイルをスペースを節約するために、同じような変更を持つファイルを1つの行にまとめてよい + + この要約は、GitHub の PullRequest にコメントとして追加されるので、追加コメントは避けること + summarize_release_notes: | + この PullRequest のために `markdown` フォーマットで簡潔なリリースノートを作成すること。 + コードの目的とユーザーストーリーに焦点を当てること。 + 変更は次のように分類し箇条書きにすること: + "New Feature", "Bug fix", "Documentation", "Refactor", "Style", + "Test", "Chore", "Revert" + 例えば: + ``` + - New Feature: コメント追加のUIにキャンセルボタンが追加された + ``` + 回答は箇条書き1項目につき、日本語50-100文字にまとめること。 + この回答はリリースノートでそのまま使用されます。 + + リリースノートの下に、この PullRequest の変更点についての短いお祝いのポエムを追加してください。 + このポエムを引用( `>` )として追加してください。ポエムには絵文字を使用できる \ No newline at end of file diff --git a/.github/workflows/openai-review.yml b/.github/workflows/openai-review.yml index c35e3659..7ca669ad 100644 --- a/.github/workflows/openai-review.yml +++ b/.github/workflows/openai-review.yml @@ -5,7 +5,7 @@ permissions: pull-requests: write on: - pull_request_target: + pull_request: types: [opened, synchronize, reopened] pull_request_review_comment: types: [created] @@ -19,6 +19,7 @@ concurrency: jobs: review: + if: github.actor != 'dependabot[bot]' runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 @@ -29,9 +30,13 @@ jobs: - uses: ./ env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }} + AZURE_OPENAI_API_KEY: ${{ secrets.AZURE_OPENAI_API_KEY }} + AZURE_OPENAI_API_INSTANCE_NAME: ${{ secrets.AZURE_OPENAI_API_INSTANCE_NAME }} + AZURE_OPENAI_API_DEPLOYMENT_NAME: ${{ secrets.AZURE_OPENAI_API_DEPLOYMENT_NAME }} + AZURE_OPENAI_API_VERSION: '2023-12-01-preview' with: debug: true + review_simple_changes: false review_comment_lgtm: false openai_heavy_model: gpt-4 path_filters: | diff --git a/.github/workflows/pr-ai-review.yml b/.github/workflows/pr-ai-review.yml new file mode 100644 index 00000000..98667e63 --- /dev/null +++ b/.github/workflows/pr-ai-review.yml @@ -0,0 +1,76 @@ +name: "[PR] Code Review" + +permissions: + contents: read + pull-requests: write + +on: + pull_request: + types: [opened, synchronize, reopened] + branches-ignore: + - main + pull_request_review_comment: + types: [created] + +concurrency: + group: ${{ github.repository }}-${{ github.event.number || github.head_ref || github.sha }}-${{ github.workflow }}-${{ github.event_name == 'pull_request_review_comment' && 'pr_comment' || 'pr' }} + cancel-in-progress: ${{ github.event_name != 'pull_request_review_comment' }} + +jobs: + review: + runs-on: ubuntu-latest + steps: + - uses: coderabbitai/ai-pr-reviewer@latest + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + OPENAI_API_KEY: ${{ secrets.AZURE_OPENAI_API_KEY }} + BASE_URL: ${{ secrets.OPENAI_BASE_URL }} + with: + debug: true + review_comment_lgtm: false + openai_light_model: gpt-3.5-turbo + openai_heavy_model: gpt-3.5-turbo + openai_base_url: ${{ env.BASE_URL }} + language: ja-JP + system_message: | + あなたは `@openai` (a.k.a. `github-actions[bot]`) です。 + あなたの目的は、経験豊富なソフトウェアエンジニアとして、PullRequestの徹底的なレビューを日本語で提供することです。 + 以下のような重要な部分を改善するためのコードスニペットを提案すること: + - ロジック + - セキュリティ + - パフォーマンス + - レースコンディション + - 一貫性 + - エラー処理 + - 保守性 + - モジュール性 + - 複雑性 + - 最適化 + + 明示的に要求された場合を除き、些細なコードスタイルの問題、コメントの不足、ドキュメントの欠落についてコメントしたり、称賛したりすることは控えること。 + コード全体の品質を向上させるために、重大な懸念事項を特定して解決することに集中し、些細な問題は無視すること。 + + 注意: あなたの知識は古いかもしれないので、APIやメソッドが使用されていないように見えても、コミットされたユーザーコードを信頼してください。 + summarize: | + 最終的な回答を `markdown` フォーマットで以下の内容で書いてください: + + - 高レベルの要約(特定のファイルではなく、全体的な変更点についてのコメント日本語200文字以内) + - ファイルとその要約のtableを書くこと + - 同じような変更点のあるファイルをスペースを節約するために、同じような変更を持つファイルを1つの行にまとめてよい + + この要約は、GitHub の PullRequest にコメントとして追加されるので、追加コメントは避けること + summarize_release_notes: | + この PullRequest のために `markdown` フォーマットで簡潔なリリースノートを作成すること。 + コードの目的とユーザーストーリーに焦点を当てること。 + 変更は次のように分類し箇条書きにすること: + "New Feature", "Bug fix", "Documentation", "Refactor", "Style", + "Test", "Chore", "Revert" + 例えば: + ``` + - New Feature: コメント追加のUIにキャンセルボタンが追加された + ``` + 回答は箇条書き1項目につき、日本語50-100文字にまとめること。 + この回答はリリースノートでそのまま使用されます。 + + リリースノートの下に、この PullRequest の変更点についての短いお祝いのポエムを追加してください。 + このポエムを引用( `>` )として追加してください。ポエムには絵文字を使用できる \ No newline at end of file diff --git a/README.md b/README.md index 4092086b..610fc885 100644 --- a/README.md +++ b/README.md @@ -90,11 +90,14 @@ jobs: - uses: coderabbitai/ai-pr-reviewer@latest env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }} + AZURE_OPENAI_API_KEY: ${{ Secrets.AZURE_OPENAI_API_KEY }} + AZURE_OPENAI_API_INSTANCE_NAME: ${{ Secrets.AZURE_OPENAI_API_INSTANCE_NAME }} + AZURE_OPENAI_API_DEPLOYMENT_NAME: ${{ Secrets.AZURE_OPENAI_API_DEPLOYMENT_NAME }} with: debug: false review_simple_changes: false review_comment_lgtm: false + language: ja-JP ``` #### Environment variables diff --git a/dist/37.index.js b/dist/37.index.js index c349ca0a..4e0fd904 100644 --- a/dist/37.index.js +++ b/dist/37.index.js @@ -3,14 +3,14 @@ exports.id = 37; exports.ids = [37]; exports.modules = { -/***/ 4037: +/***/ 6152: /***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ "toFormData": () => (/* binding */ toFormData) /* harmony export */ }); -/* harmony import */ var fetch_blob_from_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(2777); +/* harmony import */ var fetch_blob_from_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(7972); /* harmony import */ var formdata_polyfill_esm_min_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(8010); diff --git a/dist/73.index.js b/dist/73.index.js new file mode 100644 index 00000000..dd9de4c0 --- /dev/null +++ b/dist/73.index.js @@ -0,0 +1,129 @@ +"use strict"; +exports.id = 73; +exports.ids = [73]; +exports.modules = { + +/***/ 4073: +/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => { + +// ESM COMPAT FLAG +__webpack_require__.r(__webpack_exports__); + +// EXPORTS +__webpack_require__.d(__webpack_exports__, { + "fileFromPath": () => (/* binding */ fileFromPath), + "fileFromPathSync": () => (/* binding */ fileFromPathSync), + "isFile": () => (/* reexport */ isFile/* isFile */.z) +}); + +// EXTERNAL MODULE: external "fs" +var external_fs_ = __webpack_require__(7147); +// EXTERNAL MODULE: external "path" +var external_path_ = __webpack_require__(1017); +// EXTERNAL MODULE: ./node_modules/node-domexception/index.js +var node_domexception = __webpack_require__(7760); +// EXTERNAL MODULE: ./node_modules/formdata-node/lib/esm/File.js +var File = __webpack_require__(2084); +;// CONCATENATED MODULE: ./node_modules/formdata-node/lib/esm/isPlainObject.js +const getType = (value) => (Object.prototype.toString.call(value).slice(8, -1).toLowerCase()); +function isPlainObject(value) { + if (getType(value) !== "object") { + return false; + } + const pp = Object.getPrototypeOf(value); + if (pp === null || pp === undefined) { + return true; + } + const Ctor = pp.constructor && pp.constructor.toString(); + return Ctor === Object.toString(); +} +/* harmony default export */ const esm_isPlainObject = (isPlainObject); + +// EXTERNAL MODULE: ./node_modules/formdata-node/lib/esm/isFile.js +var isFile = __webpack_require__(1574); +;// CONCATENATED MODULE: ./node_modules/formdata-node/lib/esm/fileFromPath.js +var __classPrivateFieldSet = (undefined && undefined.__classPrivateFieldSet) || function (receiver, state, value, kind, f) { + if (kind === "m") throw new TypeError("Private method is not writable"); + if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter"); + if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it"); + return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value; +}; +var __classPrivateFieldGet = (undefined && undefined.__classPrivateFieldGet) || function (receiver, state, kind, f) { + if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter"); + if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it"); + return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver); +}; +var _FileFromPath_path, _FileFromPath_start; + + + + + + +const MESSAGE = "The requested file could not be read, " + + "typically due to permission problems that have occurred after a reference " + + "to a file was acquired."; +class FileFromPath { + constructor(input) { + _FileFromPath_path.set(this, void 0); + _FileFromPath_start.set(this, void 0); + __classPrivateFieldSet(this, _FileFromPath_path, input.path, "f"); + __classPrivateFieldSet(this, _FileFromPath_start, input.start || 0, "f"); + this.name = (0,external_path_.basename)(__classPrivateFieldGet(this, _FileFromPath_path, "f")); + this.size = input.size; + this.lastModified = input.lastModified; + } + slice(start, end) { + return new FileFromPath({ + path: __classPrivateFieldGet(this, _FileFromPath_path, "f"), + lastModified: this.lastModified, + size: end - start, + start + }); + } + async *stream() { + const { mtimeMs } = await external_fs_.promises.stat(__classPrivateFieldGet(this, _FileFromPath_path, "f")); + if (mtimeMs > this.lastModified) { + throw new node_domexception(MESSAGE, "NotReadableError"); + } + if (this.size) { + yield* (0,external_fs_.createReadStream)(__classPrivateFieldGet(this, _FileFromPath_path, "f"), { + start: __classPrivateFieldGet(this, _FileFromPath_start, "f"), + end: __classPrivateFieldGet(this, _FileFromPath_start, "f") + this.size - 1 + }); + } + } + get [(_FileFromPath_path = new WeakMap(), _FileFromPath_start = new WeakMap(), Symbol.toStringTag)]() { + return "File"; + } +} +function createFileFromPath(path, { mtimeMs, size }, filenameOrOptions, options = {}) { + let filename; + if (esm_isPlainObject(filenameOrOptions)) { + [options, filename] = [filenameOrOptions, undefined]; + } + else { + filename = filenameOrOptions; + } + const file = new FileFromPath({ path, size, lastModified: mtimeMs }); + if (!filename) { + filename = file.name; + } + return new File/* File */.$([file], filename, { + ...options, lastModified: file.lastModified + }); +} +function fileFromPathSync(path, filenameOrOptions, options = {}) { + const stats = (0,external_fs_.statSync)(path); + return createFileFromPath(path, stats, filenameOrOptions, options); +} +async function fileFromPath(path, filenameOrOptions, options) { + const stats = await external_fs_.promises.stat(path); + return createFileFromPath(path, stats, filenameOrOptions, options); +} + + +/***/ }) + +}; +; \ No newline at end of file diff --git a/dist/index.js b/dist/index.js index a6f49664..93213e9b 100644 --- a/dist/index.js +++ b/dist/index.js @@ -1,7 +1,7 @@ /******/ (() => { // webpackBootstrap /******/ var __webpack_modules__ = ({ -/***/ 6959: +/***/ 562: /***/ ((__unused_webpack_module, __webpack_exports__, __nccwpck_require__) => { "use strict"; @@ -17,8 +17,8 @@ const external_node_http_namespaceObject = require("node:http"); const external_node_https_namespaceObject = require("node:https"); ;// CONCATENATED MODULE: external "node:zlib" const external_node_zlib_namespaceObject = require("node:zlib"); -;// CONCATENATED MODULE: external "node:stream" -const external_node_stream_namespaceObject = require("node:stream"); +// EXTERNAL MODULE: external "node:stream" +var external_node_stream_ = __nccwpck_require__(4492); ;// CONCATENATED MODULE: external "node:buffer" const external_node_buffer_namespaceObject = require("node:buffer"); ;// CONCATENATED MODULE: ./node_modules/data-uri-to-buffer/dist/index.js @@ -236,7 +236,7 @@ const isSameProtocol = (destination, original) => { -const pipeline = (0,external_node_util_namespaceObject.promisify)(external_node_stream_namespaceObject.pipeline); +const pipeline = (0,external_node_util_namespaceObject.promisify)(external_node_stream_.pipeline); const INTERNALS = Symbol('Body internals'); /** @@ -270,7 +270,7 @@ class Body { } else if (ArrayBuffer.isView(body)) { // Body is ArrayBufferView body = external_node_buffer_namespaceObject.Buffer.from(body.buffer, body.byteOffset, body.byteLength); - } else if (body instanceof external_node_stream_namespaceObject) { + } else if (body instanceof external_node_stream_) { // Body is stream } else if (body instanceof esm_min/* FormData */.Ct) { // Body is FormData @@ -285,9 +285,9 @@ class Body { let stream = body; if (external_node_buffer_namespaceObject.Buffer.isBuffer(body)) { - stream = external_node_stream_namespaceObject.Readable.from(body); + stream = external_node_stream_.Readable.from(body); } else if (isBlob(body)) { - stream = external_node_stream_namespaceObject.Readable.from(body.stream()); + stream = external_node_stream_.Readable.from(body.stream()); } this[INTERNALS] = { @@ -299,7 +299,7 @@ class Body { }; this.size = size; - if (body instanceof external_node_stream_namespaceObject) { + if (body instanceof external_node_stream_) { body.on('error', error_ => { const error = error_ instanceof FetchBaseError ? error_ : @@ -341,7 +341,7 @@ class Body { return formData; } - const {toFormData} = await __nccwpck_require__.e(/* import() */ 37).then(__nccwpck_require__.bind(__nccwpck_require__, 4037)); + const {toFormData} = await __nccwpck_require__.e(/* import() */ 37).then(__nccwpck_require__.bind(__nccwpck_require__, 6152)); return toFormData(this.body, ct); } @@ -430,7 +430,7 @@ async function consumeBody(data) { } /* c8 ignore next 3 */ - if (!(body instanceof external_node_stream_namespaceObject)) { + if (!(body instanceof external_node_stream_)) { return external_node_buffer_namespaceObject.Buffer.alloc(0); } @@ -489,10 +489,10 @@ const clone = (instance, highWaterMark) => { // Check that body is a stream and not form-data object // note: we can't clone the form-data object without having it as a dependency - if ((body instanceof external_node_stream_namespaceObject) && (typeof body.getBoundary !== 'function')) { + if ((body instanceof external_node_stream_) && (typeof body.getBoundary !== 'function')) { // Tee instance body - p1 = new external_node_stream_namespaceObject.PassThrough({highWaterMark}); - p2 = new external_node_stream_namespaceObject.PassThrough({highWaterMark}); + p1 = new external_node_stream_.PassThrough({highWaterMark}); + p2 = new external_node_stream_.PassThrough({highWaterMark}); body.pipe(p1); body.pipe(p2); // Set instance body to teed body and return the other teed body @@ -555,7 +555,7 @@ const extractContentType = (body, request) => { } // Body is stream - can't really do much about this - if (body instanceof external_node_stream_namespaceObject) { + if (body instanceof external_node_stream_) { return null; } @@ -1746,8 +1746,8 @@ class AbortError extends FetchBaseError { } } -// EXTERNAL MODULE: ./node_modules/fetch-blob/from.js + 2 modules -var from = __nccwpck_require__(2777); +// EXTERNAL MODULE: ./node_modules/fetch-blob/from.js + 1 modules +var from = __nccwpck_require__(7972); ;// CONCATENATED MODULE: ./node_modules/node-fetch/src/index.js /** * Index.js @@ -1789,7 +1789,7 @@ const supportedSchemas = new Set(['data:', 'http:', 'https:']); * @param {*} [options_] - Fetch options * @return {Promise} */ -async function fetch(url, options_) { +async function src_fetch(url, options_) { return new Promise((resolve, reject) => { // Build request object const request = new Request(url, options_); @@ -1813,7 +1813,7 @@ async function fetch(url, options_) { const abort = () => { const error = new AbortError('The operation was aborted.'); reject(error); - if (request.body && request.body instanceof external_node_stream_namespaceObject.Readable) { + if (request.body && request.body instanceof external_node_stream_.Readable) { request.body.destroy(error); } @@ -1957,7 +1957,7 @@ async function fetch(url, options_) { } // HTTP-redirect fetch step 9 - if (response_.statusCode !== 303 && request.body && options_.body instanceof external_node_stream_namespaceObject.Readable) { + if (response_.statusCode !== 303 && request.body && options_.body instanceof external_node_stream_.Readable) { reject(new FetchError('Cannot follow redirect with body being a readable stream', 'unsupported-redirect')); finalize(); return; @@ -1977,7 +1977,7 @@ async function fetch(url, options_) { } // HTTP-redirect fetch step 15 - resolve(fetch(new Request(locationURL, requestOptions))); + resolve(src_fetch(new Request(locationURL, requestOptions))); finalize(); return; } @@ -1994,7 +1994,7 @@ async function fetch(url, options_) { }); } - let body = (0,external_node_stream_namespaceObject.pipeline)(response_, new external_node_stream_namespaceObject.PassThrough(), error => { + let body = (0,external_node_stream_.pipeline)(response_, new external_node_stream_.PassThrough(), error => { if (error) { reject(error); } @@ -2044,7 +2044,7 @@ async function fetch(url, options_) { // For gzip if (codings === 'gzip' || codings === 'x-gzip') { - body = (0,external_node_stream_namespaceObject.pipeline)(body, external_node_zlib_namespaceObject.createGunzip(zlibOptions), error => { + body = (0,external_node_stream_.pipeline)(body, external_node_zlib_namespaceObject.createGunzip(zlibOptions), error => { if (error) { reject(error); } @@ -2058,7 +2058,7 @@ async function fetch(url, options_) { if (codings === 'deflate' || codings === 'x-deflate') { // Handle the infamous raw deflate response from old servers // a hack for old IIS and Apache servers - const raw = (0,external_node_stream_namespaceObject.pipeline)(response_, new external_node_stream_namespaceObject.PassThrough(), error => { + const raw = (0,external_node_stream_.pipeline)(response_, new external_node_stream_.PassThrough(), error => { if (error) { reject(error); } @@ -2066,13 +2066,13 @@ async function fetch(url, options_) { raw.once('data', chunk => { // See http://stackoverflow.com/questions/37519828 if ((chunk[0] & 0x0F) === 0x08) { - body = (0,external_node_stream_namespaceObject.pipeline)(body, external_node_zlib_namespaceObject.createInflate(), error => { + body = (0,external_node_stream_.pipeline)(body, external_node_zlib_namespaceObject.createInflate(), error => { if (error) { reject(error); } }); } else { - body = (0,external_node_stream_namespaceObject.pipeline)(body, external_node_zlib_namespaceObject.createInflateRaw(), error => { + body = (0,external_node_stream_.pipeline)(body, external_node_zlib_namespaceObject.createInflateRaw(), error => { if (error) { reject(error); } @@ -2095,7 +2095,7 @@ async function fetch(url, options_) { // For br if (codings === 'br') { - body = (0,external_node_stream_namespaceObject.pipeline)(body, external_node_zlib_namespaceObject.createBrotliDecompress(), error => { + body = (0,external_node_stream_.pipeline)(body, external_node_zlib_namespaceObject.createBrotliDecompress(), error => { if (error) { reject(error); } @@ -2164,7 +2164,7 @@ function fixResponseChunkedTransferBadEnding(request, errorCallback) { // fetch-polyfill.js if (!globalThis.fetch) { - globalThis.fetch = fetch; + globalThis.fetch = src_fetch; globalThis.Headers = Headers; globalThis.Request = Request; globalThis.Response = Response; @@ -2172,679 +2172,2871 @@ if (!globalThis.fetch) { // EXTERNAL MODULE: ./node_modules/@actions/core/lib/core.js var core = __nccwpck_require__(2186); -// EXTERNAL MODULE: ./node_modules/keyv/src/index.js -var src = __nccwpck_require__(1531); -;// CONCATENATED MODULE: ./node_modules/p-timeout/index.js -class TimeoutError extends Error { - constructor(message) { - super(message); - this.name = 'TimeoutError'; - } -} +// EXTERNAL MODULE: ./node_modules/langchain/dist/chains/base.js +var base = __nccwpck_require__(3197); +// EXTERNAL MODULE: ./node_modules/langchain/dist/chains/llm_chain.js + 1 modules +var llm_chain = __nccwpck_require__(7287); +// EXTERNAL MODULE: ./node_modules/langchain/dist/chains/api/api_chain.js + 1 modules +var api_chain = __nccwpck_require__(6159); +// EXTERNAL MODULE: ./node_modules/langchain/dist/prompts/prompt.js +var prompts_prompt = __nccwpck_require__(3379); +// EXTERNAL MODULE: ./node_modules/langchain/dist/memory/base.js +var memory_base = __nccwpck_require__(790); +// EXTERNAL MODULE: ./node_modules/langchain/dist/schema/index.js +var schema = __nccwpck_require__(8102); +;// CONCATENATED MODULE: ./node_modules/langchain/dist/stores/message/in_memory.js /** -An error to be thrown when the request is aborted by AbortController. -DOMException is thrown instead of this Error when DOMException is available. -*/ -class p_timeout_AbortError extends Error { - constructor(message) { - super(); - this.name = 'AbortError'; - this.message = message; - } + * Class for storing chat message history in-memory. It extends the + * BaseListChatMessageHistory class and provides methods to get, add, and + * clear messages. + */ +class ChatMessageHistory extends schema/* BaseListChatMessageHistory */.oV { + constructor(messages) { + super(...arguments); + Object.defineProperty(this, "lc_namespace", { + enumerable: true, + configurable: true, + writable: true, + value: ["langchain", "stores", "message", "in_memory"] + }); + Object.defineProperty(this, "messages", { + enumerable: true, + configurable: true, + writable: true, + value: [] + }); + this.messages = messages ?? []; + } + /** + * Method to get all the messages stored in the ChatMessageHistory + * instance. + * @returns Array of stored BaseMessage instances. + */ + async getMessages() { + return this.messages; + } + /** + * Method to add a new message to the ChatMessageHistory instance. + * @param message The BaseMessage instance to add. + * @returns A promise that resolves when the message has been added. + */ + async addMessage(message) { + this.messages.push(message); + } + /** + * Method to clear all the messages from the ChatMessageHistory instance. + * @returns A promise that resolves when all messages have been cleared. + */ + async clear() { + this.messages = []; + } } -/** -TODO: Remove AbortError and just throw DOMException when targeting Node 18. -*/ -const getDOMException = errorMessage => globalThis.DOMException === undefined - ? new p_timeout_AbortError(errorMessage) - : new DOMException(errorMessage); +;// CONCATENATED MODULE: ./node_modules/langchain/dist/memory/chat_memory.js + /** -TODO: Remove below function and just 'reject(signal.reason)' when targeting Node 18. -*/ -const getAbortedReason = signal => { - const reason = signal.reason === undefined - ? getDOMException('This operation was aborted.') - : signal.reason; + * Abstract class that provides a base for implementing different types of + * memory systems. It is designed to maintain the state of an application, + * specifically the history of a conversation. This class is typically + * extended by other classes to create specific types of memory systems. + */ +class chat_memory_BaseChatMemory extends memory_base/* BaseMemory */.fF { + constructor(fields) { + super(); + Object.defineProperty(this, "chatHistory", { + enumerable: true, + configurable: true, + writable: true, + value: void 0 + }); + Object.defineProperty(this, "returnMessages", { + enumerable: true, + configurable: true, + writable: true, + value: false + }); + Object.defineProperty(this, "inputKey", { + enumerable: true, + configurable: true, + writable: true, + value: void 0 + }); + Object.defineProperty(this, "outputKey", { + enumerable: true, + configurable: true, + writable: true, + value: void 0 + }); + this.chatHistory = fields?.chatHistory ?? new ChatMessageHistory(); + this.returnMessages = fields?.returnMessages ?? this.returnMessages; + this.inputKey = fields?.inputKey ?? this.inputKey; + this.outputKey = fields?.outputKey ?? this.outputKey; + } + /** + * Method to add user and AI messages to the chat history in sequence. + * @param inputValues The input values from the user. + * @param outputValues The output values from the AI. + * @returns Promise that resolves when the context has been saved. + */ + async saveContext(inputValues, outputValues) { + // this is purposefully done in sequence so they're saved in order + await this.chatHistory.addUserMessage((0,memory_base/* getInputValue */.d9)(inputValues, this.inputKey)); + await this.chatHistory.addAIChatMessage((0,memory_base/* getOutputValue */.jG)(outputValues, this.outputKey)); + } + /** + * Method to clear the chat history. + * @returns Promise that resolves when the chat history has been cleared. + */ + async clear() { + await this.chatHistory.clear(); + } +} + +;// CONCATENATED MODULE: ./node_modules/langchain/dist/memory/buffer_memory.js - return reason instanceof Error ? reason : getDOMException(reason); -}; -function pTimeout(promise, options) { - const { - milliseconds, - fallback, - message, - customTimers = {setTimeout, clearTimeout}, - } = options; +/** + * The `BufferMemory` class is a type of memory component used for storing + * and managing previous chat messages. It is a wrapper around + * `ChatMessageHistory` that extracts the messages into an input variable. + * This class is particularly useful in applications like chatbots where + * it is essential to remember previous interactions. Note: The memory + * instance represents the history of a single conversation. Therefore, it + * is not recommended to share the same history or memory instance between + * two different chains. If you deploy your LangChain app on a serverless + * environment, do not store memory instances in a variable, as your + * hosting provider may reset it by the next time the function is called. + * @example + * ```typescript + * // Initialize the memory to store chat history and set up the language model with a specific temperature. + * const memory = new BufferMemory({ memoryKey: "chat_history" }); + * const model = new ChatOpenAI({ temperature: 0.9 }); + * + * // Create a prompt template for a friendly conversation between a human and an AI. + * const prompt = + * PromptTemplate.fromTemplate(`The following is a friendly conversation between a human and an AI. The AI is talkative and provides lots of specific details from its context. If the AI does not know the answer to a question, it truthfully says it does not know. + * + * Current conversation: + * {chat_history} + * Human: {input} + * AI:`); + * + * // Set up the chain with the language model, prompt, and memory. + * const chain = new LLMChain({ llm: model, prompt, memory }); + * + * // Example usage of the chain to continue the conversation. + * // The `call` method sends the input to the model and returns the AI's response. + * const res = await chain.call({ input: "Hi! I'm Jim." }); + * console.log({ res }); + * + * ``` + */ +class BufferMemory extends chat_memory_BaseChatMemory { + constructor(fields) { + super({ + chatHistory: fields?.chatHistory, + returnMessages: fields?.returnMessages ?? false, + inputKey: fields?.inputKey, + outputKey: fields?.outputKey, + }); + Object.defineProperty(this, "humanPrefix", { + enumerable: true, + configurable: true, + writable: true, + value: "Human" + }); + Object.defineProperty(this, "aiPrefix", { + enumerable: true, + configurable: true, + writable: true, + value: "AI" + }); + Object.defineProperty(this, "memoryKey", { + enumerable: true, + configurable: true, + writable: true, + value: "history" + }); + this.humanPrefix = fields?.humanPrefix ?? this.humanPrefix; + this.aiPrefix = fields?.aiPrefix ?? this.aiPrefix; + this.memoryKey = fields?.memoryKey ?? this.memoryKey; + } + get memoryKeys() { + return [this.memoryKey]; + } + /** + * Loads the memory variables. It takes an `InputValues` object as a + * parameter and returns a `Promise` that resolves with a + * `MemoryVariables` object. + * @param _values `InputValues` object. + * @returns A `Promise` that resolves with a `MemoryVariables` object. + */ + async loadMemoryVariables(_values) { + const messages = await this.chatHistory.getMessages(); + if (this.returnMessages) { + const result = { + [this.memoryKey]: messages, + }; + return result; + } + const result = { + [this.memoryKey]: (0,memory_base/* getBufferString */.zs)(messages, this.humanPrefix, this.aiPrefix), + }; + return result; + } +} - let timer; +;// CONCATENATED MODULE: ./node_modules/langchain/dist/chains/conversation.js - const cancelablePromise = new Promise((resolve, reject) => { - if (typeof milliseconds !== 'number' || Math.sign(milliseconds) !== 1) { - throw new TypeError(`Expected \`milliseconds\` to be a positive number, got \`${milliseconds}\``); - } - if (milliseconds === Number.POSITIVE_INFINITY) { - resolve(promise); - return; - } - if (options.signal) { - const {signal} = options; - if (signal.aborted) { - reject(getAbortedReason(signal)); - } +const conversation_DEFAULT_TEMPLATE = `The following is a friendly conversation between a human and an AI. The AI is talkative and provides lots of specific details from its context. If the AI does not know the answer to a question, it truthfully says it does not know. - signal.addEventListener('abort', () => { - reject(getAbortedReason(signal)); - }); - } +Current conversation: +{history} +Human: {input} +AI:`; +/** + * A class for conducting conversations between a human and an AI. It + * extends the {@link LLMChain} class. + * @example + * ```typescript + * const model = new ChatOpenAI({}); + * const chain = new ConversationChain({ llm: model }); + * + * // Sending a greeting to the conversation chain + * const res1 = await chain.call({ input: "Hi! I'm Jim." }); + * console.log({ res1 }); + * + * // Following up with a question in the conversation + * const res2 = await chain.call({ input: "What's my name?" }); + * console.log({ res2 }); + * ``` + */ +class conversation_ConversationChain extends llm_chain.LLMChain { + static lc_name() { + return "ConversationChain"; + } + constructor({ prompt, outputKey, memory, ...rest }) { + super({ + prompt: prompt ?? + new prompts_prompt.PromptTemplate({ + template: conversation_DEFAULT_TEMPLATE, + inputVariables: ["history", "input"], + }), + outputKey: outputKey ?? "response", + memory: memory ?? new BufferMemory(), + ...rest, + }); + } +} - // We create the error outside of `setTimeout` to preserve the stack trace. - const timeoutError = new TimeoutError(); +// EXTERNAL MODULE: ./node_modules/langchain/dist/chains/sequential_chain.js + 1 modules +var sequential_chain = __nccwpck_require__(7210); +// EXTERNAL MODULE: ./node_modules/langchain/dist/chains/combine_docs_chain.js +var combine_docs_chain = __nccwpck_require__(3608); +// EXTERNAL MODULE: ./node_modules/langchain/dist/chains/question_answering/load.js + 4 modules +var load = __nccwpck_require__(3504); +;// CONCATENATED MODULE: ./node_modules/langchain/dist/chains/chat_vector_db_chain.js - timer = customTimers.setTimeout.call(undefined, () => { - if (fallback) { - try { - resolve(fallback()); - } catch (error) { - reject(error); - } - return; - } - if (typeof promise.cancel === 'function') { - promise.cancel(); - } - if (message === false) { - resolve(); - } else if (message instanceof Error) { - reject(message); - } else { - timeoutError.message = message ?? `Promise timed out after ${milliseconds} milliseconds`; - reject(timeoutError); - } - }, milliseconds); +const question_generator_template = (/* unused pure expression or super */ null && (`Given the following conversation and a follow up question, rephrase the follow up question to be a standalone question. - (async () => { - try { - resolve(await promise); - } catch (error) { - reject(error); - } finally { - customTimers.clearTimeout.call(undefined, timer); - } - })(); - }); +Chat History: +{chat_history} +Follow Up Input: {question} +Standalone question:`)); +const qa_template = (/* unused pure expression or super */ null && (`Use the following pieces of context to answer the question at the end. If you don't know the answer, just say that you don't know, don't try to make up an answer. - cancelablePromise.clear = () => { - customTimers.clearTimeout.call(undefined, timer); - timer = undefined; - }; +{context} - return cancelablePromise; +Question: {question} +Helpful Answer:`)); +/** @deprecated use `ConversationalRetrievalQAChain` instead. */ +class ChatVectorDBQAChain extends (/* unused pure expression or super */ null && (BaseChain)) { + get inputKeys() { + return [this.inputKey, this.chatHistoryKey]; + } + get outputKeys() { + return [this.outputKey]; + } + constructor(fields) { + super(fields); + Object.defineProperty(this, "k", { + enumerable: true, + configurable: true, + writable: true, + value: 4 + }); + Object.defineProperty(this, "inputKey", { + enumerable: true, + configurable: true, + writable: true, + value: "question" + }); + Object.defineProperty(this, "chatHistoryKey", { + enumerable: true, + configurable: true, + writable: true, + value: "chat_history" + }); + Object.defineProperty(this, "outputKey", { + enumerable: true, + configurable: true, + writable: true, + value: "result" + }); + Object.defineProperty(this, "vectorstore", { + enumerable: true, + configurable: true, + writable: true, + value: void 0 + }); + Object.defineProperty(this, "combineDocumentsChain", { + enumerable: true, + configurable: true, + writable: true, + value: void 0 + }); + Object.defineProperty(this, "questionGeneratorChain", { + enumerable: true, + configurable: true, + writable: true, + value: void 0 + }); + Object.defineProperty(this, "returnSourceDocuments", { + enumerable: true, + configurable: true, + writable: true, + value: false + }); + this.vectorstore = fields.vectorstore; + this.combineDocumentsChain = fields.combineDocumentsChain; + this.questionGeneratorChain = fields.questionGeneratorChain; + this.inputKey = fields.inputKey ?? this.inputKey; + this.outputKey = fields.outputKey ?? this.outputKey; + this.k = fields.k ?? this.k; + this.returnSourceDocuments = + fields.returnSourceDocuments ?? this.returnSourceDocuments; + } + /** @ignore */ + async _call(values, runManager) { + if (!(this.inputKey in values)) { + throw new Error(`Question key ${this.inputKey} not found.`); + } + if (!(this.chatHistoryKey in values)) { + throw new Error(`chat history key ${this.inputKey} not found.`); + } + const question = values[this.inputKey]; + const chatHistory = values[this.chatHistoryKey]; + let newQuestion = question; + if (chatHistory.length > 0) { + const result = await this.questionGeneratorChain.call({ + question, + chat_history: chatHistory, + }, runManager?.getChild("question_generator")); + const keys = Object.keys(result); + console.log("_call", values, keys); + if (keys.length === 1) { + newQuestion = result[keys[0]]; + } + else { + throw new Error("Return from llm chain has multiple values, only single values supported."); + } + } + const docs = await this.vectorstore.similaritySearch(newQuestion, this.k, undefined, runManager?.getChild("vectorstore")); + const inputs = { + question: newQuestion, + input_documents: docs, + chat_history: chatHistory, + }; + const result = await this.combineDocumentsChain.call(inputs, runManager?.getChild("combine_documents")); + if (this.returnSourceDocuments) { + return { + ...result, + sourceDocuments: docs, + }; + } + return result; + } + _chainType() { + return "chat-vector-db"; + } + static async deserialize(data, values) { + if (!("vectorstore" in values)) { + throw new Error(`Need to pass in a vectorstore to deserialize VectorDBQAChain`); + } + const { vectorstore } = values; + return new ChatVectorDBQAChain({ + combineDocumentsChain: await BaseChain.deserialize(data.combine_documents_chain), + questionGeneratorChain: await LLMChain.deserialize(data.question_generator), + k: data.k, + vectorstore, + }); + } + serialize() { + return { + _type: this._chainType(), + combine_documents_chain: this.combineDocumentsChain.serialize(), + question_generator: this.questionGeneratorChain.serialize(), + k: this.k, + }; + } + /** + * Creates an instance of ChatVectorDBQAChain using a BaseLanguageModel + * and other options. + * @param llm Instance of BaseLanguageModel used to generate a new question. + * @param vectorstore Instance of VectorStore used for vector operations. + * @param options (Optional) Additional options for creating the ChatVectorDBQAChain instance. + * @returns New instance of ChatVectorDBQAChain. + */ + static fromLLM(llm, vectorstore, options = {}) { + const { questionGeneratorTemplate, qaTemplate, verbose, ...rest } = options; + const question_generator_prompt = PromptTemplate.fromTemplate(questionGeneratorTemplate || question_generator_template); + const qa_prompt = PromptTemplate.fromTemplate(qaTemplate || qa_template); + const qaChain = loadQAStuffChain(llm, { prompt: qa_prompt, verbose }); + const questionGeneratorChain = new LLMChain({ + prompt: question_generator_prompt, + llm, + verbose, + }); + const instance = new this({ + vectorstore, + combineDocumentsChain: qaChain, + questionGeneratorChain, + ...rest, + }); + return instance; + } } -;// CONCATENATED MODULE: ./node_modules/quick-lru/index.js -class QuickLRU extends Map { - constructor(options = {}) { - super(); +// EXTERNAL MODULE: ./node_modules/langchain/dist/util/tiktoken.js + 3 modules +var tiktoken = __nccwpck_require__(7573); +// EXTERNAL MODULE: ./node_modules/langchain/dist/schema/runnable/index.js + 3 modules +var runnable = __nccwpck_require__(4379); +;// CONCATENATED MODULE: ./node_modules/langchain/dist/schema/document.js - if (!(options.maxSize && options.maxSize > 0)) { - throw new TypeError('`maxSize` must be a number greater than 0'); - } +/** + * Abstract base class for document transformation systems. + * + * A document transformation system takes an array of Documents and returns an + * array of transformed Documents. These arrays do not necessarily have to have + * the same length. + * + * One example of this is a text splitter that splits a large document into + * many smaller documents. + */ +class document_BaseDocumentTransformer extends (/* unused pure expression or super */ null && (Runnable)) { + constructor() { + super(...arguments); + Object.defineProperty(this, "lc_namespace", { + enumerable: true, + configurable: true, + writable: true, + value: ["langchain", "document_transformers"] + }); + } + /** + * Method to invoke the document transformation. This method calls the + * transformDocuments method with the provided input. + * @param input The input documents to be transformed. + * @param _options Optional configuration object to customize the behavior of callbacks. + * @returns A Promise that resolves to the transformed documents. + */ + invoke(input, _options) { + return this.transformDocuments(input); + } +} +/** + * Class for document transformers that return exactly one transformed document + * for each input document. + */ +class MappingDocumentTransformer extends (/* unused pure expression or super */ null && (document_BaseDocumentTransformer)) { + async transformDocuments(documents) { + const newDocuments = []; + for (const document of documents) { + const transformedDocument = await this._transformDocument(document); + newDocuments.push(transformedDocument); + } + return newDocuments; + } +} - if (typeof options.maxAge === 'number' && options.maxAge === 0) { - throw new TypeError('`maxAge` must be a number greater than 0'); - } +;// CONCATENATED MODULE: ./node_modules/langchain/dist/text_splitter.js - // TODO: Use private class fields when ESLint supports them. - this.maxSize = options.maxSize; - this.maxAge = options.maxAge || Number.POSITIVE_INFINITY; - this.onEviction = options.onEviction; - this.cache = new Map(); - this.oldCache = new Map(); - this._size = 0; - } - // TODO: Use private class methods when targeting Node.js 16. - _emitEvictions(cache) { - if (typeof this.onEviction !== 'function') { - return; - } - for (const [key, item] of cache) { - this.onEviction(key, item.value); - } - } +class TextSplitter extends (/* unused pure expression or super */ null && (BaseDocumentTransformer)) { + constructor(fields) { + super(fields); + Object.defineProperty(this, "lc_namespace", { + enumerable: true, + configurable: true, + writable: true, + value: ["langchain", "document_transformers", "text_splitters"] + }); + Object.defineProperty(this, "chunkSize", { + enumerable: true, + configurable: true, + writable: true, + value: 1000 + }); + Object.defineProperty(this, "chunkOverlap", { + enumerable: true, + configurable: true, + writable: true, + value: 200 + }); + Object.defineProperty(this, "keepSeparator", { + enumerable: true, + configurable: true, + writable: true, + value: false + }); + Object.defineProperty(this, "lengthFunction", { + enumerable: true, + configurable: true, + writable: true, + value: void 0 + }); + this.chunkSize = fields?.chunkSize ?? this.chunkSize; + this.chunkOverlap = fields?.chunkOverlap ?? this.chunkOverlap; + this.keepSeparator = fields?.keepSeparator ?? this.keepSeparator; + this.lengthFunction = + fields?.lengthFunction ?? ((text) => text.length); + if (this.chunkOverlap >= this.chunkSize) { + throw new Error("Cannot have chunkOverlap >= chunkSize"); + } + } + async transformDocuments(documents, chunkHeaderOptions = {}) { + return this.splitDocuments(documents, chunkHeaderOptions); + } + splitOnSeparator(text, separator) { + let splits; + if (separator) { + if (this.keepSeparator) { + const regexEscapedSeparator = separator.replace(/[/\-\\^$*+?.()|[\]{}]/g, "\\$&"); + splits = text.split(new RegExp(`(?=${regexEscapedSeparator})`)); + } + else { + splits = text.split(separator); + } + } + else { + splits = text.split(""); + } + return splits.filter((s) => s !== ""); + } + async createDocuments(texts, + // eslint-disable-next-line @typescript-eslint/no-explicit-any + metadatas = [], chunkHeaderOptions = {}) { + // if no metadata is provided, we create an empty one for each text + const _metadatas = metadatas.length > 0 ? metadatas : new Array(texts.length).fill({}); + const { chunkHeader = "", chunkOverlapHeader = "(cont'd) ", appendChunkOverlapHeader = false, } = chunkHeaderOptions; + const documents = new Array(); + for (let i = 0; i < texts.length; i += 1) { + const text = texts[i]; + let lineCounterIndex = 1; + let prevChunk = null; + let indexPrevChunk = -1; + for (const chunk of await this.splitText(text)) { + let pageContent = chunkHeader; + // we need to count the \n that are in the text before getting removed by the splitting + const indexChunk = text.indexOf(chunk, indexPrevChunk + 1); + if (prevChunk === null) { + const newLinesBeforeFirstChunk = this.numberOfNewLines(text, 0, indexChunk); + lineCounterIndex += newLinesBeforeFirstChunk; + } + else { + const indexEndPrevChunk = indexPrevChunk + (await this.lengthFunction(prevChunk)); + if (indexEndPrevChunk < indexChunk) { + const numberOfIntermediateNewLines = this.numberOfNewLines(text, indexEndPrevChunk, indexChunk); + lineCounterIndex += numberOfIntermediateNewLines; + } + else if (indexEndPrevChunk > indexChunk) { + const numberOfIntermediateNewLines = this.numberOfNewLines(text, indexChunk, indexEndPrevChunk); + lineCounterIndex -= numberOfIntermediateNewLines; + } + if (appendChunkOverlapHeader) { + pageContent += chunkOverlapHeader; + } + } + const newLinesCount = this.numberOfNewLines(chunk); + const loc = _metadatas[i].loc && typeof _metadatas[i].loc === "object" + ? { ..._metadatas[i].loc } + : {}; + loc.lines = { + from: lineCounterIndex, + to: lineCounterIndex + newLinesCount, + }; + const metadataWithLinesNumber = { + ..._metadatas[i], + loc, + }; + pageContent += chunk; + documents.push(new Document({ + pageContent, + metadata: metadataWithLinesNumber, + })); + lineCounterIndex += newLinesCount; + prevChunk = chunk; + indexPrevChunk = indexChunk; + } + } + return documents; + } + numberOfNewLines(text, start, end) { + const textSection = text.slice(start, end); + return (textSection.match(/\n/g) || []).length; + } + async splitDocuments(documents, chunkHeaderOptions = {}) { + const selectedDocuments = documents.filter((doc) => doc.pageContent !== undefined); + const texts = selectedDocuments.map((doc) => doc.pageContent); + const metadatas = selectedDocuments.map((doc) => doc.metadata); + return this.createDocuments(texts, metadatas, chunkHeaderOptions); + } + joinDocs(docs, separator) { + const text = docs.join(separator).trim(); + return text === "" ? null : text; + } + async mergeSplits(splits, separator) { + const docs = []; + const currentDoc = []; + let total = 0; + for (const d of splits) { + const _len = await this.lengthFunction(d); + if (total + _len + (currentDoc.length > 0 ? separator.length : 0) > + this.chunkSize) { + if (total > this.chunkSize) { + console.warn(`Created a chunk of size ${total}, + +which is longer than the specified ${this.chunkSize}`); + } + if (currentDoc.length > 0) { + const doc = this.joinDocs(currentDoc, separator); + if (doc !== null) { + docs.push(doc); + } + // Keep on popping if: + // - we have a larger chunk than in the chunk overlap + // - or if we still have any chunks and the length is long + while (total > this.chunkOverlap || + (total + _len > this.chunkSize && total > 0)) { + total -= await this.lengthFunction(currentDoc[0]); + currentDoc.shift(); + } + } + } + currentDoc.push(d); + total += _len; + } + const doc = this.joinDocs(currentDoc, separator); + if (doc !== null) { + docs.push(doc); + } + return docs; + } +} +class CharacterTextSplitter extends (/* unused pure expression or super */ null && (TextSplitter)) { + static lc_name() { + return "CharacterTextSplitter"; + } + constructor(fields) { + super(fields); + Object.defineProperty(this, "separator", { + enumerable: true, + configurable: true, + writable: true, + value: "\n\n" + }); + this.separator = fields?.separator ?? this.separator; + } + async splitText(text) { + // First we naively split the large input into a bunch of smaller ones. + const splits = this.splitOnSeparator(text, this.separator); + return this.mergeSplits(splits, this.keepSeparator ? "" : this.separator); + } +} +const SupportedTextSplitterLanguages = (/* unused pure expression or super */ null && ([ + "cpp", + "go", + "java", + "js", + "php", + "proto", + "python", + "rst", + "ruby", + "rust", + "scala", + "swift", + "markdown", + "latex", + "html", + "sol", +])); +class text_splitter_RecursiveCharacterTextSplitter extends (/* unused pure expression or super */ null && (TextSplitter)) { + static lc_name() { + return "RecursiveCharacterTextSplitter"; + } + constructor(fields) { + super(fields); + Object.defineProperty(this, "separators", { + enumerable: true, + configurable: true, + writable: true, + value: ["\n\n", "\n", " ", ""] + }); + this.separators = fields?.separators ?? this.separators; + this.keepSeparator = fields?.keepSeparator ?? true; + } + async _splitText(text, separators) { + const finalChunks = []; + // Get appropriate separator to use + let separator = separators[separators.length - 1]; + let newSeparators; + for (let i = 0; i < separators.length; i += 1) { + const s = separators[i]; + if (s === "") { + separator = s; + break; + } + if (text.includes(s)) { + separator = s; + newSeparators = separators.slice(i + 1); + break; + } + } + // Now that we have the separator, split the text + const splits = this.splitOnSeparator(text, separator); + // Now go merging things, recursively splitting longer texts. + let goodSplits = []; + const _separator = this.keepSeparator ? "" : separator; + for (const s of splits) { + if ((await this.lengthFunction(s)) < this.chunkSize) { + goodSplits.push(s); + } + else { + if (goodSplits.length) { + const mergedText = await this.mergeSplits(goodSplits, _separator); + finalChunks.push(...mergedText); + goodSplits = []; + } + if (!newSeparators) { + finalChunks.push(s); + } + else { + const otherInfo = await this._splitText(s, newSeparators); + finalChunks.push(...otherInfo); + } + } + } + if (goodSplits.length) { + const mergedText = await this.mergeSplits(goodSplits, _separator); + finalChunks.push(...mergedText); + } + return finalChunks; + } + async splitText(text) { + return this._splitText(text, this.separators); + } + static fromLanguage(language, options) { + return new text_splitter_RecursiveCharacterTextSplitter({ + ...options, + separators: text_splitter_RecursiveCharacterTextSplitter.getSeparatorsForLanguage(language), + }); + } + static getSeparatorsForLanguage(language) { + if (language === "cpp") { + return [ + // Split along class definitions + "\nclass ", + // Split along function definitions + "\nvoid ", + "\nint ", + "\nfloat ", + "\ndouble ", + // Split along control flow statements + "\nif ", + "\nfor ", + "\nwhile ", + "\nswitch ", + "\ncase ", + // Split by the normal type of lines + "\n\n", + "\n", + " ", + "", + ]; + } + else if (language === "go") { + return [ + // Split along function definitions + "\nfunc ", + "\nvar ", + "\nconst ", + "\ntype ", + // Split along control flow statements + "\nif ", + "\nfor ", + "\nswitch ", + "\ncase ", + // Split by the normal type of lines + "\n\n", + "\n", + " ", + "", + ]; + } + else if (language === "java") { + return [ + // Split along class definitions + "\nclass ", + // Split along method definitions + "\npublic ", + "\nprotected ", + "\nprivate ", + "\nstatic ", + // Split along control flow statements + "\nif ", + "\nfor ", + "\nwhile ", + "\nswitch ", + "\ncase ", + // Split by the normal type of lines + "\n\n", + "\n", + " ", + "", + ]; + } + else if (language === "js") { + return [ + // Split along function definitions + "\nfunction ", + "\nconst ", + "\nlet ", + "\nvar ", + "\nclass ", + // Split along control flow statements + "\nif ", + "\nfor ", + "\nwhile ", + "\nswitch ", + "\ncase ", + "\ndefault ", + // Split by the normal type of lines + "\n\n", + "\n", + " ", + "", + ]; + } + else if (language === "php") { + return [ + // Split along function definitions + "\nfunction ", + // Split along class definitions + "\nclass ", + // Split along control flow statements + "\nif ", + "\nforeach ", + "\nwhile ", + "\ndo ", + "\nswitch ", + "\ncase ", + // Split by the normal type of lines + "\n\n", + "\n", + " ", + "", + ]; + } + else if (language === "proto") { + return [ + // Split along message definitions + "\nmessage ", + // Split along service definitions + "\nservice ", + // Split along enum definitions + "\nenum ", + // Split along option definitions + "\noption ", + // Split along import statements + "\nimport ", + // Split along syntax declarations + "\nsyntax ", + // Split by the normal type of lines + "\n\n", + "\n", + " ", + "", + ]; + } + else if (language === "python") { + return [ + // First, try to split along class definitions + "\nclass ", + "\ndef ", + "\n\tdef ", + // Now split by the normal type of lines + "\n\n", + "\n", + " ", + "", + ]; + } + else if (language === "rst") { + return [ + // Split along section titles + "\n===\n", + "\n---\n", + "\n***\n", + // Split along directive markers + "\n.. ", + // Split by the normal type of lines + "\n\n", + "\n", + " ", + "", + ]; + } + else if (language === "ruby") { + return [ + // Split along method definitions + "\ndef ", + "\nclass ", + // Split along control flow statements + "\nif ", + "\nunless ", + "\nwhile ", + "\nfor ", + "\ndo ", + "\nbegin ", + "\nrescue ", + // Split by the normal type of lines + "\n\n", + "\n", + " ", + "", + ]; + } + else if (language === "rust") { + return [ + // Split along function definitions + "\nfn ", + "\nconst ", + "\nlet ", + // Split along control flow statements + "\nif ", + "\nwhile ", + "\nfor ", + "\nloop ", + "\nmatch ", + "\nconst ", + // Split by the normal type of lines + "\n\n", + "\n", + " ", + "", + ]; + } + else if (language === "scala") { + return [ + // Split along class definitions + "\nclass ", + "\nobject ", + // Split along method definitions + "\ndef ", + "\nval ", + "\nvar ", + // Split along control flow statements + "\nif ", + "\nfor ", + "\nwhile ", + "\nmatch ", + "\ncase ", + // Split by the normal type of lines + "\n\n", + "\n", + " ", + "", + ]; + } + else if (language === "swift") { + return [ + // Split along function definitions + "\nfunc ", + // Split along class definitions + "\nclass ", + "\nstruct ", + "\nenum ", + // Split along control flow statements + "\nif ", + "\nfor ", + "\nwhile ", + "\ndo ", + "\nswitch ", + "\ncase ", + // Split by the normal type of lines + "\n\n", + "\n", + " ", + "", + ]; + } + else if (language === "markdown") { + return [ + // First, try to split along Markdown headings (starting with level 2) + "\n## ", + "\n### ", + "\n#### ", + "\n##### ", + "\n###### ", + // Note the alternative syntax for headings (below) is not handled here + // Heading level 2 + // --------------- + // End of code block + "```\n\n", + // Horizontal lines + "\n\n***\n\n", + "\n\n---\n\n", + "\n\n___\n\n", + // Note that this splitter doesn't handle horizontal lines defined + // by *three or more* of ***, ---, or ___, but this is not handled + "\n\n", + "\n", + " ", + "", + ]; + } + else if (language === "latex") { + return [ + // First, try to split along Latex sections + "\n\\chapter{", + "\n\\section{", + "\n\\subsection{", + "\n\\subsubsection{", + // Now split by environments + "\n\\begin{enumerate}", + "\n\\begin{itemize}", + "\n\\begin{description}", + "\n\\begin{list}", + "\n\\begin{quote}", + "\n\\begin{quotation}", + "\n\\begin{verse}", + "\n\\begin{verbatim}", + // Now split by math environments + "\n\\begin{align}", + "$$", + "$", + // Now split by the normal type of lines + "\n\n", + "\n", + " ", + "", + ]; + } + else if (language === "html") { + return [ + // First, try to split along HTML tags + "", + "
", + "

", + "
", + "

  • ", + "

    ", + "

    ", + "

    ", + "

    ", + "

    ", + "
    ", + "", + "", + "", + "
    ", + "", + "
      ", + "
        ", + "
        ", + "