mirror of
https://github.com/logancyang/obsidian-copilot.git
synced 2026-07-22 07:50:24 +00:00
chore(deps): drop @langchain/classic; inline ChatBufferMemory + remove dead ChainFactory
Replaces BufferMemory/BufferWindowMemory from @langchain/classic with a minimal in-tree ChatBufferMemory wrapping @langchain/core's InMemoryChatMessageHistory. Deletes the deprecated ChainFactory (chain runners already call chat models directly) and the chain-validation helpers in utils. Bumps @langchain/anthropic to 1.3.29 so BedrockChatModel's tool-schema cast is no longer needed. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
6a71cf8586
commit
0c1a0d605f
15 changed files with 138 additions and 608 deletions
237
package-lock.json
generated
237
package-lock.json
generated
|
|
@ -12,8 +12,7 @@
|
|||
"@dnd-kit/core": "^6.3.1",
|
||||
"@dnd-kit/sortable": "^10.0.0",
|
||||
"@dnd-kit/utilities": "^3.2.2",
|
||||
"@langchain/anthropic": "^1.0.0",
|
||||
"@langchain/classic": "^1.0.9",
|
||||
"@langchain/anthropic": "^1.3.29",
|
||||
"@langchain/core": "^1.1.29",
|
||||
"@langchain/deepseek": "^1.0.0",
|
||||
"@langchain/google-genai": "^2.1.23",
|
||||
|
|
@ -58,8 +57,6 @@
|
|||
"zod": "^3.25.76"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@codemirror/state": "^6.5.2",
|
||||
"@codemirror/view": "^6.36.4",
|
||||
"@eslint-react/eslint-plugin": "^1.38.4",
|
||||
"@google/generative-ai": "^0.24.0",
|
||||
"@jest/globals": "^29.7.0",
|
||||
|
|
@ -123,6 +120,26 @@
|
|||
"node": ">=6.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@anthropic-ai/sdk": {
|
||||
"version": "0.91.1",
|
||||
"resolved": "https://registry.npmjs.org/@anthropic-ai/sdk/-/sdk-0.91.1.tgz",
|
||||
"integrity": "sha512-LAmu761tSN9r66ixvmciswUj/ZC+1Q4iAfpedTfSVLeswRwnY3n2Nb6Tsk+cLPP28aLOPWeMgIuTuCcMC6W/iw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"json-schema-to-ts": "^3.1.1"
|
||||
},
|
||||
"bin": {
|
||||
"anthropic-ai-sdk": "bin/cli"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"zod": "^3.25.0 || ^4.0.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"zod": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/code-frame": {
|
||||
"version": "7.26.2",
|
||||
"resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.26.2.tgz",
|
||||
|
|
@ -649,6 +666,7 @@
|
|||
"integrity": "sha512-FVqsPqtPWKVVL3dPSxy8wEF/ymIEuVzF1PK3VbUgrxXpJUSHQWWZz4JMToquRxnkw+36LTamCZG2iua2Ptq0fA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@marijn/find-cluster-break": "^1.0.0"
|
||||
}
|
||||
|
|
@ -659,6 +677,7 @@
|
|||
"integrity": "sha512-qiS0z1bKs5WOvHIAC0Cybmv4AJSkAXgX5aD6Mqd2epSLlVJsQl8NG23jCVouIgkh4All/mrbdsf2UOLFnJw0tw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@codemirror/state": "^6.5.0",
|
||||
"crelt": "^1.0.6",
|
||||
|
|
@ -2323,137 +2342,39 @@
|
|||
"dev": true
|
||||
},
|
||||
"node_modules/@langchain/anthropic": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@langchain/anthropic/-/anthropic-1.0.0.tgz",
|
||||
"integrity": "sha512-Lud/FrkFmXMYW5R9y0FC+RGdgjBBVQ2JAnG3A8E1I4+sqv5JgJttw3HKRpFkyBUSyacs6LMfSn5dbJ6TT9nMiQ==",
|
||||
"version": "1.3.29",
|
||||
"resolved": "https://registry.npmjs.org/@langchain/anthropic/-/anthropic-1.3.29.tgz",
|
||||
"integrity": "sha512-ep1qBIcV07bajsg3fDqMd39rYwoRLOEK/6lk+MCxlm1YB5SRoKKJAZANrblQ/4RYhZJnxf95c6BSQu8VoNbVAQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@anthropic-ai/sdk": "^0.65.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=20"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@langchain/core": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@langchain/anthropic/node_modules/@anthropic-ai/sdk": {
|
||||
"version": "0.65.0",
|
||||
"resolved": "https://registry.npmjs.org/@anthropic-ai/sdk/-/sdk-0.65.0.tgz",
|
||||
"integrity": "sha512-zIdPOcrCVEI8t3Di40nH4z9EoeyGZfXbYSvWdDLsB/KkaSYMnEgC7gmcgWu83g2NTn1ZTpbMvpdttWDGGIk6zw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"json-schema-to-ts": "^3.1.1"
|
||||
},
|
||||
"bin": {
|
||||
"anthropic-ai-sdk": "bin/cli"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"zod": "^3.25.0 || ^4.0.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"zod": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@langchain/classic": {
|
||||
"version": "1.0.9",
|
||||
"resolved": "https://registry.npmjs.org/@langchain/classic/-/classic-1.0.9.tgz",
|
||||
"integrity": "sha512-UQ6JFLvPPPHHq+c3bM3UjadsugYP013qzk6FMoULpj2oNsVU4Fd66R+V6p1R7gQQRmN4Y7DWRLePn2NzgVYFIA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@langchain/openai": "1.2.2",
|
||||
"@langchain/textsplitters": "1.0.1",
|
||||
"handlebars": "^4.7.8",
|
||||
"js-yaml": "^4.1.1",
|
||||
"jsonpointer": "^5.0.1",
|
||||
"openapi-types": "^12.1.3",
|
||||
"uuid": "^10.0.0",
|
||||
"yaml": "^2.2.1",
|
||||
"@anthropic-ai/sdk": "^0.91.1",
|
||||
"zod": "^3.25.76 || ^4"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=20"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"langsmith": ">=0.4.0 <1.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@langchain/core": "^1.0.0",
|
||||
"cheerio": "*",
|
||||
"peggy": "^3.0.2",
|
||||
"typeorm": "*"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"cheerio": {
|
||||
"optional": true
|
||||
},
|
||||
"peggy": {
|
||||
"optional": true
|
||||
},
|
||||
"typeorm": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@langchain/classic/node_modules/uuid": {
|
||||
"version": "10.0.0",
|
||||
"resolved": "https://registry.npmjs.org/uuid/-/uuid-10.0.0.tgz",
|
||||
"integrity": "sha512-8XkAphELsDnEGrDxUOHB3RGvXz6TeuYSGEZBOjtTtPm2lwhGBjLgOzLHB63IUWfBpNucQjND6d3AOudO+H3RWQ==",
|
||||
"funding": [
|
||||
"https://github.com/sponsors/broofa",
|
||||
"https://github.com/sponsors/ctavan"
|
||||
],
|
||||
"license": "MIT",
|
||||
"bin": {
|
||||
"uuid": "dist/bin/uuid"
|
||||
"@langchain/core": "^1.1.45"
|
||||
}
|
||||
},
|
||||
"node_modules/@langchain/core": {
|
||||
"version": "1.1.29",
|
||||
"resolved": "https://registry.npmjs.org/@langchain/core/-/core-1.1.29.tgz",
|
||||
"integrity": "sha512-BPoegTtIdZX4gl2kxcSXAlLrrJFl1cxeRsk9DM/wlIuvyPrFwjWqrEK5NwF5diDt5XSArhQxIFaifGAl4F7fgw==",
|
||||
"version": "1.1.46",
|
||||
"resolved": "https://registry.npmjs.org/@langchain/core/-/core-1.1.46.tgz",
|
||||
"integrity": "sha512-i8rDC83BpItxChCw4Lf+6tAr+k+OUcbirc5ZkrhI9ywYWmvxegUljLGOGYvtJNTbEAIFkhYIODPE5QRqyjF6sA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@cfworker/json-schema": "^4.0.2",
|
||||
"ansi-styles": "^5.0.0",
|
||||
"camelcase": "6",
|
||||
"decamelize": "1.2.0",
|
||||
"@standard-schema/spec": "^1.1.0",
|
||||
"js-tiktoken": "^1.0.12",
|
||||
"langsmith": ">=0.5.0 <1.0.0",
|
||||
"mustache": "^4.2.0",
|
||||
"p-queue": "^6.6.2",
|
||||
"uuid": "^11.1.0",
|
||||
"zod": "^3.25.76 || ^4"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=20"
|
||||
}
|
||||
},
|
||||
"node_modules/@langchain/core/node_modules/ansi-styles": {
|
||||
"version": "5.2.0",
|
||||
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz",
|
||||
"integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/chalk/ansi-styles?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/@langchain/core/node_modules/camelcase": {
|
||||
"version": "6.3.0",
|
||||
"resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz",
|
||||
"integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==",
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/@langchain/core/node_modules/p-queue": {
|
||||
"version": "6.6.2",
|
||||
"resolved": "https://registry.npmjs.org/p-queue/-/p-queue-6.6.2.tgz",
|
||||
|
|
@ -2845,7 +2766,8 @@
|
|||
"resolved": "https://registry.npmjs.org/@marijn/find-cluster-break/-/find-cluster-break-1.0.2.tgz",
|
||||
"integrity": "sha512-l0h88YhZFyKdXIFNfSWpyjStDjGHwZ/U7iobcK1cQQD8sejsONdQtTVU+1wVN1PBw40PiiHB1vA5S7VTfQiP9g==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
"license": "MIT",
|
||||
"peer": true
|
||||
},
|
||||
"node_modules/@mixmark-io/domino": {
|
||||
"version": "2.2.0",
|
||||
|
|
@ -6169,6 +6091,12 @@
|
|||
"@sinonjs/commons": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@standard-schema/spec": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@standard-schema/spec/-/spec-1.1.0.tgz",
|
||||
"integrity": "sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@szmarczak/http-timer": {
|
||||
"version": "4.0.6",
|
||||
"resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-4.0.6.tgz",
|
||||
|
|
@ -7149,7 +7077,8 @@
|
|||
"node_modules/argparse": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
|
||||
"integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q=="
|
||||
"integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/aria-hidden": {
|
||||
"version": "1.2.4",
|
||||
|
|
@ -8014,7 +7943,8 @@
|
|||
"resolved": "https://registry.npmjs.org/crelt/-/crelt-1.0.6.tgz",
|
||||
"integrity": "sha512-VQ2MBenTq1fWZUH9DJNGti7kKv6EeAuYr3cLwxUWhIu1baTaXh4Ib5W2CqHVqib4/MqbYGJqiL3Zb8GJZr3l4g==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
"license": "MIT",
|
||||
"peer": true
|
||||
},
|
||||
"node_modules/cross-spawn": {
|
||||
"version": "7.0.6",
|
||||
|
|
@ -8215,14 +8145,6 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"node_modules/decamelize": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz",
|
||||
"integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==",
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/decimal.js": {
|
||||
"version": "10.4.3",
|
||||
"resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.4.3.tgz",
|
||||
|
|
@ -10695,27 +10617,6 @@
|
|||
"undici-types": "~5.26.4"
|
||||
}
|
||||
},
|
||||
"node_modules/handlebars": {
|
||||
"version": "4.7.8",
|
||||
"resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.8.tgz",
|
||||
"integrity": "sha512-vafaFqs8MZkRrSX7sFVUdo3ap/eNiLnb4IakshzvP56X5Nr1iGKAIqdX6tMlm6HcNRIkr6AxO5jFEoJzzpT8aQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"minimist": "^1.2.5",
|
||||
"neo-async": "^2.6.2",
|
||||
"source-map": "^0.6.1",
|
||||
"wordwrap": "^1.0.0"
|
||||
},
|
||||
"bin": {
|
||||
"handlebars": "bin/handlebars"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=0.4.7"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"uglify-js": "^3.1.4"
|
||||
}
|
||||
},
|
||||
"node_modules/has-bigints": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz",
|
||||
|
|
@ -12746,6 +12647,7 @@
|
|||
"version": "4.1.1",
|
||||
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz",
|
||||
"integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"argparse": "^2.0.1"
|
||||
|
|
@ -12929,15 +12831,6 @@
|
|||
"graceful-fs": "^4.1.6"
|
||||
}
|
||||
},
|
||||
"node_modules/jsonpointer": {
|
||||
"version": "5.0.1",
|
||||
"resolved": "https://registry.npmjs.org/jsonpointer/-/jsonpointer-5.0.1.tgz",
|
||||
"integrity": "sha512-p/nXbhSEcu3pZRdkW1OfJhpsVtW1gd4Wa1fnQc9YLiTfAjn0312eMKimbdIQzuZl9aa9xUGaRlP9T/CJE/ditQ==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/jsx-ast-utils": {
|
||||
"version": "3.3.5",
|
||||
"resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.3.5.tgz",
|
||||
|
|
@ -13359,6 +13252,7 @@
|
|||
"version": "1.2.8",
|
||||
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz",
|
||||
"integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
|
|
@ -13459,12 +13353,6 @@
|
|||
"integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/neo-async": {
|
||||
"version": "2.6.2",
|
||||
"resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz",
|
||||
"integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/node-domexception": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz",
|
||||
|
|
@ -13931,12 +13819,6 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"node_modules/openapi-types": {
|
||||
"version": "12.1.3",
|
||||
"resolved": "https://registry.npmjs.org/openapi-types/-/openapi-types-12.1.3.tgz",
|
||||
"integrity": "sha512-N4YtSYJqghVu4iek2ZUvcN/0aqH1kRDuNqzcycDxhOUpg7GdvLa2F3DgS6yBNhInhv2r/6I0Flkn7CqL8+nIcw==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/optionator": {
|
||||
"version": "0.9.4",
|
||||
"resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz",
|
||||
|
|
@ -15331,6 +15213,7 @@
|
|||
"version": "0.6.1",
|
||||
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
|
||||
"integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
|
|
@ -15608,7 +15491,8 @@
|
|||
"resolved": "https://registry.npmjs.org/style-mod/-/style-mod-4.1.2.tgz",
|
||||
"integrity": "sha512-wnD1HyVqpJUI2+eKZ+eo1UwghftP6yuFheBqqe+bWCotBjC2K1YnteJILRMs3SM4V/0dLEW1SC27MWP5y+mwmw==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
"license": "MIT",
|
||||
"peer": true
|
||||
},
|
||||
"node_modules/sucrase": {
|
||||
"version": "3.35.0",
|
||||
|
|
@ -16338,19 +16222,6 @@
|
|||
"typescript": ">=4.8.4 <6.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/uglify-js": {
|
||||
"version": "3.19.3",
|
||||
"resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.19.3.tgz",
|
||||
"integrity": "sha512-v3Xu+yuwBXisp6QYTcH4UbH+xYJXqnq2m/LtQVWKWzYc1iehYnLixoQDN9FH6/j9/oybfd6W9Ghwkl8+UMKTKQ==",
|
||||
"license": "BSD-2-Clause",
|
||||
"optional": true,
|
||||
"bin": {
|
||||
"uglifyjs": "bin/uglifyjs"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=0.8.0"
|
||||
}
|
||||
},
|
||||
"node_modules/unbox-primitive": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.1.0.tgz",
|
||||
|
|
@ -16513,7 +16384,8 @@
|
|||
"version": "2.2.6",
|
||||
"resolved": "https://registry.npmjs.org/w3c-keyname/-/w3c-keyname-2.2.6.tgz",
|
||||
"integrity": "sha512-f+fciywl1SJEniZHD6H+kUO8gOnwIr7f4ijKA6+ZvJFjeGi1r4PDLl53Ayud9O/rk64RqgoQine0feoeOU0kXg==",
|
||||
"dev": true
|
||||
"dev": true,
|
||||
"peer": true
|
||||
},
|
||||
"node_modules/w3c-xmlserializer": {
|
||||
"version": "4.0.0",
|
||||
|
|
@ -16707,12 +16579,6 @@
|
|||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/wordwrap": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz",
|
||||
"integrity": "sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/wrap-ansi": {
|
||||
"version": "7.0.0",
|
||||
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
|
||||
|
|
@ -16822,6 +16688,7 @@
|
|||
"version": "2.9.0",
|
||||
"resolved": "https://registry.npmjs.org/yaml/-/yaml-2.9.0.tgz",
|
||||
"integrity": "sha512-2AvhNX3mb8zd6Zy7INTtSpl1F15HW6Wnqj0srWlkKLcpYl/gMIMJiyuGq2KeI2YFxUPjdlB+3Lc10seMLtL4cA==",
|
||||
"dev": true,
|
||||
"license": "ISC",
|
||||
"bin": {
|
||||
"yaml": "bin.mjs"
|
||||
|
|
|
|||
|
|
@ -33,8 +33,6 @@
|
|||
},
|
||||
"license": "AGPL-3.0",
|
||||
"devDependencies": {
|
||||
"@codemirror/state": "^6.5.2",
|
||||
"@codemirror/view": "^6.36.4",
|
||||
"@eslint-react/eslint-plugin": "^1.38.4",
|
||||
"@google/generative-ai": "^0.24.0",
|
||||
"@jest/globals": "^29.7.0",
|
||||
|
|
@ -76,8 +74,7 @@
|
|||
"@dnd-kit/core": "^6.3.1",
|
||||
"@dnd-kit/sortable": "^10.0.0",
|
||||
"@dnd-kit/utilities": "^3.2.2",
|
||||
"@langchain/anthropic": "^1.0.0",
|
||||
"@langchain/classic": "^1.0.9",
|
||||
"@langchain/anthropic": "^1.3.29",
|
||||
"@langchain/core": "^1.1.29",
|
||||
"@langchain/deepseek": "^1.0.0",
|
||||
"@langchain/google-genai": "^2.1.23",
|
||||
|
|
|
|||
|
|
@ -142,9 +142,7 @@ export class BedrockChatModel extends BaseChatModel<BedrockChatModelCallOptions>
|
|||
let inputSchema: Record<string, unknown> = { type: "object", properties: {} };
|
||||
if (tool.schema) {
|
||||
// Use LangChain's schema conversion utilities
|
||||
inputSchema = (
|
||||
isInteropZodSchema(tool.schema) ? toJsonSchema(tool.schema) : tool.schema
|
||||
) as Record<string, unknown>;
|
||||
inputSchema = isInteropZodSchema(tool.schema) ? toJsonSchema(tool.schema) : tool.schema;
|
||||
}
|
||||
return {
|
||||
name: tool.name,
|
||||
|
|
|
|||
|
|
@ -5,7 +5,6 @@ import {
|
|||
SetChainOptions,
|
||||
setChainType,
|
||||
} from "@/aiParams";
|
||||
import ChainFactory, { Document } from "@/chainFactory";
|
||||
import { ChainType } from "@/chainType";
|
||||
import { BUILTIN_CHAT_MODELS, USER_SENDER } from "@/constants";
|
||||
import {
|
||||
|
|
@ -20,14 +19,14 @@ import { logError, logInfo } from "@/logger";
|
|||
import { getSettings, subscribeToSettingsChange } from "@/settings/model";
|
||||
import { getSystemPrompt } from "@/system-prompts/systemPromptBuilder";
|
||||
import { ChatMessage } from "@/types/message";
|
||||
import { findCustomModel, isOSeriesModel, isSupportedChain } from "@/utils";
|
||||
import { findCustomModel, isOSeriesModel } from "@/utils";
|
||||
import { MissingModelKeyError } from "@/error";
|
||||
import {
|
||||
ChatPromptTemplate,
|
||||
HumanMessagePromptTemplate,
|
||||
MessagesPlaceholder,
|
||||
} from "@langchain/core/prompts";
|
||||
import { RunnableSequence } from "@langchain/core/runnables";
|
||||
import { Document } from "@langchain/core/documents";
|
||||
import { App, Notice } from "obsidian";
|
||||
import ChatModelManager from "./chatModelManager";
|
||||
import MemoryManager from "./memoryManager";
|
||||
|
|
@ -35,10 +34,6 @@ import PromptManager from "./promptManager";
|
|||
import { UserMemoryManager } from "@/memory/UserMemoryManager";
|
||||
|
||||
export default class ChainManager {
|
||||
// TODO: These chains are deprecated since we now use direct chat model calls in chain runners
|
||||
// Consider removing after verifying no dependencies remain
|
||||
private chain: RunnableSequence;
|
||||
private retrievalChain: RunnableSequence;
|
||||
private retrievedDocuments: Document[] = [];
|
||||
|
||||
public getRetrievedDocuments(): Document[] {
|
||||
|
|
@ -74,16 +69,6 @@ export default class ChainManager {
|
|||
await this.createChainWithNewModel();
|
||||
}
|
||||
|
||||
// TODO: These methods are deprecated - chain runners now use direct chat model calls
|
||||
// Remove after confirming no usage remains
|
||||
public getChain(): RunnableSequence {
|
||||
return this.chain;
|
||||
}
|
||||
|
||||
public getRetrievalChain(): RunnableSequence {
|
||||
return this.retrievalChain;
|
||||
}
|
||||
|
||||
private validateChainType(chainType: ChainType): void {
|
||||
if (chainType === undefined || chainType === null) throw new Error("No chain type set");
|
||||
}
|
||||
|
|
@ -100,17 +85,6 @@ export default class ChainManager {
|
|||
}
|
||||
}
|
||||
|
||||
// TODO: This method is deprecated - chain validation no longer needed
|
||||
// Remove after confirming no dependencies
|
||||
private validateChainInitialization() {
|
||||
if (!this.chain || !isSupportedChain(this.chain)) {
|
||||
logInfo("Reinitializing chat chain after detecting missing or unsupported instance.");
|
||||
void this.createChainWithNewModel({}, false).catch((err) =>
|
||||
logError("createChainWithNewModel failed", err)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
public storeRetrieverDocuments(documents: Document[]) {
|
||||
this.retrievedDocuments = documents;
|
||||
}
|
||||
|
|
@ -175,9 +149,6 @@ export default class ChainManager {
|
|||
this.pendingModelError = null;
|
||||
}
|
||||
|
||||
// Must update the chatModel for chain because ChainFactory always
|
||||
// retrieves the old chain without the chatModel change if it exists!
|
||||
// Create a new chain with the new chatModel
|
||||
await this.setChain(chainType, options);
|
||||
logInfo(`Setting model to ${newModelKey}`);
|
||||
} catch (error) {
|
||||
|
|
@ -187,8 +158,6 @@ export default class ChainManager {
|
|||
}
|
||||
}
|
||||
|
||||
// TODO: This method is deprecated - chain runners now handle chain logic directly
|
||||
// Remove after confirming no usage remains
|
||||
async setChain(chainType: ChainType, options: SetChainOptions = {}): Promise<void> {
|
||||
if (!this.chatModelManager.validateChatModel(this.chatModelManager.getChatModel())) {
|
||||
console.error("setChain failed: No chat model set.");
|
||||
|
|
@ -197,98 +166,15 @@ export default class ChainManager {
|
|||
|
||||
this.validateChainType(chainType);
|
||||
|
||||
// Get chatModel, memory, prompt, and embeddingAPI from respective managers
|
||||
const chatModel = this.chatModelManager.getChatModel();
|
||||
const memory = this.memoryManager.getMemory();
|
||||
const chatPrompt = this.promptManager.getChatPrompt();
|
||||
|
||||
switch (chainType) {
|
||||
case ChainType.LLM_CHAIN: {
|
||||
// TODO: LLMChainRunner now handles this directly without chains
|
||||
this.chain = ChainFactory.createNewLLMChain({
|
||||
llm: chatModel,
|
||||
memory: memory,
|
||||
prompt: options.prompt || chatPrompt,
|
||||
abortController: options.abortController,
|
||||
});
|
||||
|
||||
setChainType(ChainType.LLM_CHAIN);
|
||||
break;
|
||||
}
|
||||
|
||||
case ChainType.VAULT_QA_CHAIN: {
|
||||
// TODO: VaultQAChainRunner now handles this directly without chains
|
||||
await this.initializeQAChain(options);
|
||||
|
||||
// Create retriever based on semantic search setting
|
||||
const settings = getSettings();
|
||||
const retriever = settings.enableSemanticSearchV3
|
||||
? new (await import("@/search/hybridRetriever")).HybridRetriever({
|
||||
minSimilarityScore: 0.01,
|
||||
maxK: settings.maxSourceChunks,
|
||||
salientTerms: [],
|
||||
})
|
||||
: new (await import("@/search/v3/TieredLexicalRetriever")).TieredLexicalRetriever(app, {
|
||||
minSimilarityScore: 0.01,
|
||||
maxK: settings.maxSourceChunks,
|
||||
salientTerms: [],
|
||||
textWeight: undefined,
|
||||
returnAll: false,
|
||||
useRerankerThreshold: undefined,
|
||||
});
|
||||
|
||||
// Create new conversational retrieval chain
|
||||
this.retrievalChain = ChainFactory.createConversationalRetrievalChain(
|
||||
{
|
||||
llm: chatModel,
|
||||
retriever: retriever,
|
||||
systemMessage: getSystemPrompt(),
|
||||
},
|
||||
this.storeRetrieverDocuments.bind(this) as (
|
||||
documents: import("@langchain/core/documents").Document[]
|
||||
) => void,
|
||||
getSettings().debug
|
||||
);
|
||||
|
||||
setChainType(ChainType.VAULT_QA_CHAIN);
|
||||
if (getSettings().debug) {
|
||||
logInfo("New Vault QA chain with hybrid retriever created for entire vault");
|
||||
logInfo("Set chain:", ChainType.VAULT_QA_CHAIN);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case ChainType.COPILOT_PLUS_CHAIN: {
|
||||
// For initial load of the plugin
|
||||
await this.initializeQAChain(options);
|
||||
this.chain = ChainFactory.createNewLLMChain({
|
||||
llm: chatModel,
|
||||
memory: memory,
|
||||
prompt: options.prompt || chatPrompt,
|
||||
abortController: options.abortController,
|
||||
});
|
||||
|
||||
setChainType(ChainType.COPILOT_PLUS_CHAIN);
|
||||
break;
|
||||
}
|
||||
|
||||
case ChainType.PROJECT_CHAIN: {
|
||||
// For initial load of the plugin
|
||||
await this.initializeQAChain(options);
|
||||
this.chain = ChainFactory.createNewLLMChain({
|
||||
llm: chatModel,
|
||||
memory: memory,
|
||||
prompt: options.prompt || chatPrompt,
|
||||
abortController: options.abortController,
|
||||
});
|
||||
setChainType(ChainType.PROJECT_CHAIN);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
this.validateChainType(chainType);
|
||||
break;
|
||||
if (
|
||||
chainType === ChainType.VAULT_QA_CHAIN ||
|
||||
chainType === ChainType.COPILOT_PLUS_CHAIN ||
|
||||
chainType === ChainType.PROJECT_CHAIN
|
||||
) {
|
||||
await this.initializeQAChain(options);
|
||||
}
|
||||
|
||||
setChainType(chainType);
|
||||
}
|
||||
|
||||
private getChainRunner(): ChainRunner {
|
||||
|
|
@ -346,7 +232,6 @@ export default class ChainManager {
|
|||
);
|
||||
|
||||
this.validateChatModel();
|
||||
this.validateChainInitialization();
|
||||
|
||||
const chatModel = this.chatModelManager.getChatModel();
|
||||
|
||||
|
|
|
|||
58
src/LLMProviders/chatBufferMemory.ts
Normal file
58
src/LLMProviders/chatBufferMemory.ts
Normal file
|
|
@ -0,0 +1,58 @@
|
|||
import { BaseChatMessageHistory, InMemoryChatMessageHistory } from "@langchain/core/chat_history";
|
||||
import { BaseMessage } from "@langchain/core/messages";
|
||||
|
||||
export interface ChatBufferMemoryOptions {
|
||||
k?: number;
|
||||
memoryKey?: string;
|
||||
inputKey?: string;
|
||||
returnMessages?: boolean;
|
||||
chatHistory?: BaseChatMessageHistory;
|
||||
}
|
||||
|
||||
/**
|
||||
* Minimal in-process replacement for `BufferMemory` / `BufferWindowMemory`
|
||||
* from `@langchain/classic/memory`. Implements the narrow API surface used
|
||||
* by the project (loadMemoryVariables / saveContext / clear / chatHistory)
|
||||
* so we can drop the `@langchain/classic` dep.
|
||||
*/
|
||||
export class ChatBufferMemory {
|
||||
readonly chatHistory: BaseChatMessageHistory;
|
||||
private readonly k?: number;
|
||||
private readonly memoryKey: string;
|
||||
private readonly inputKey?: string;
|
||||
|
||||
constructor(options: ChatBufferMemoryOptions = {}) {
|
||||
this.k = options.k;
|
||||
this.memoryKey = options.memoryKey ?? "history";
|
||||
this.inputKey = options.inputKey;
|
||||
this.chatHistory = options.chatHistory ?? new InMemoryChatMessageHistory();
|
||||
}
|
||||
|
||||
async loadMemoryVariables(
|
||||
_: Record<string, unknown> = {}
|
||||
): Promise<Record<string, BaseMessage[]>> {
|
||||
const messages = await this.chatHistory.getMessages();
|
||||
const windowed =
|
||||
this.k !== undefined && messages.length > this.k ? messages.slice(-this.k) : messages;
|
||||
return { [this.memoryKey]: windowed };
|
||||
}
|
||||
|
||||
async saveContext(
|
||||
input: Record<string, unknown>,
|
||||
output: Record<string, unknown>
|
||||
): Promise<void> {
|
||||
const inputKey = this.inputKey ?? Object.keys(input)[0];
|
||||
const inputValue = input[inputKey];
|
||||
const outputValue = output[Object.keys(output)[0]];
|
||||
await this.chatHistory.addUserMessage(stringify(inputValue));
|
||||
await this.chatHistory.addAIMessage(stringify(outputValue));
|
||||
}
|
||||
|
||||
async clear(): Promise<void> {
|
||||
await this.chatHistory.clear();
|
||||
}
|
||||
}
|
||||
|
||||
function stringify(value: unknown): string {
|
||||
return typeof value === "string" ? value : JSON.stringify(value);
|
||||
}
|
||||
|
|
@ -1,12 +1,12 @@
|
|||
import { compactAssistantOutput } from "@/context/ChatHistoryCompactor";
|
||||
import { logInfo } from "@/logger";
|
||||
import { getSettings, subscribeToSettingsChange } from "@/settings/model";
|
||||
import { BaseChatMemory, BufferWindowMemory } from "@langchain/classic/memory";
|
||||
import { BaseChatMessageHistory } from "@langchain/core/chat_history";
|
||||
import { ChatBufferMemory } from "./chatBufferMemory";
|
||||
|
||||
export default class MemoryManager {
|
||||
private static instance: MemoryManager;
|
||||
private memory: BaseChatMemory;
|
||||
private memory: ChatBufferMemory;
|
||||
private debug: boolean;
|
||||
|
||||
private constructor() {
|
||||
|
|
@ -27,7 +27,7 @@ export default class MemoryManager {
|
|||
|
||||
private initMemory(chatHistory?: BaseChatMessageHistory): void {
|
||||
const chatContextTurns = getSettings().contextTurns;
|
||||
this.memory = new BufferWindowMemory({
|
||||
this.memory = new ChatBufferMemory({
|
||||
k: chatContextTurns * 2,
|
||||
memoryKey: "history",
|
||||
inputKey: "input",
|
||||
|
|
@ -39,7 +39,7 @@ export default class MemoryManager {
|
|||
}
|
||||
}
|
||||
|
||||
getMemory(): BaseChatMemory {
|
||||
getMemory(): ChatBufferMemory {
|
||||
return this.memory;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,208 +0,0 @@
|
|||
// TODO(logan): This entire file is deprecated since we moved to direct chat model calls in chain runners
|
||||
// Consider removing after verifying no dependencies remain
|
||||
|
||||
import { BaseLanguageModel } from "@langchain/core/language_models/base";
|
||||
import { StringOutputParser } from "@langchain/core/output_parsers";
|
||||
import { ChatPromptTemplate, PromptTemplate } from "@langchain/core/prompts";
|
||||
import { BaseRetriever } from "@langchain/core/retrievers";
|
||||
import { RunnablePassthrough, RunnableSequence } from "@langchain/core/runnables";
|
||||
import { BaseChatMemory } from "@langchain/classic/memory";
|
||||
import { formatDocumentsAsString } from "@langchain/classic/util/document";
|
||||
import { ChainType } from "./chainType";
|
||||
import { logInfo } from "./logger";
|
||||
import { removeErrorTags, removeThinkTags } from "./utils";
|
||||
|
||||
export interface LLMChainInput {
|
||||
llm: BaseLanguageModel;
|
||||
memory: BaseChatMemory;
|
||||
prompt: ChatPromptTemplate;
|
||||
abortController?: AbortController;
|
||||
}
|
||||
|
||||
export interface RetrievalChainParams {
|
||||
llm: BaseLanguageModel;
|
||||
retriever: BaseRetriever;
|
||||
options?: {
|
||||
returnSourceDocuments?: boolean;
|
||||
};
|
||||
}
|
||||
|
||||
export interface ConversationalRetrievalChainParams {
|
||||
llm: BaseLanguageModel;
|
||||
retriever: BaseRetriever;
|
||||
systemMessage: string;
|
||||
options?: {
|
||||
returnSourceDocuments?: boolean;
|
||||
questionGeneratorTemplate?: string;
|
||||
qaTemplate?: string;
|
||||
};
|
||||
}
|
||||
|
||||
export interface Document<T = Record<string, unknown>> {
|
||||
// Structure of Document, possibly including pageContent, metadata, etc.
|
||||
pageContent: string;
|
||||
metadata: T;
|
||||
}
|
||||
|
||||
type ConversationalRetrievalQAChainInput = {
|
||||
question: string;
|
||||
chat_history: [string, string][];
|
||||
};
|
||||
|
||||
// Issue where conversational retrieval chain gives rephrased question
|
||||
// when streaming: https://github.com/hwchase17/langchainjs/issues/754#issuecomment-1540257078
|
||||
// Temp workaround triggers CORS issue 'refused to set header user-agent'
|
||||
|
||||
class ChainFactory {
|
||||
public static instances: Map<string, RunnableSequence> = new Map();
|
||||
|
||||
/**
|
||||
* Create a new LLM chain using the provided LLMChainInput.
|
||||
*
|
||||
* @param {LLMChainInput} args - the input for creating the LLM chain
|
||||
* @return {RunnableSequence} the newly created LLM chain
|
||||
*/
|
||||
public static createNewLLMChain(args: LLMChainInput): RunnableSequence {
|
||||
const { llm, memory, prompt, abortController } = args;
|
||||
|
||||
const model = llm.withConfig({ signal: abortController?.signal });
|
||||
const instance = RunnableSequence.from([
|
||||
{
|
||||
input: (initialInput: { input: unknown }) => initialInput.input,
|
||||
memory: () => memory.loadMemoryVariables({}),
|
||||
},
|
||||
{
|
||||
input: (previousOutput: { input: unknown; memory: { history: unknown } }) =>
|
||||
previousOutput.input,
|
||||
history: (previousOutput: { input: unknown; memory: { history: unknown } }) =>
|
||||
previousOutput.memory.history,
|
||||
},
|
||||
prompt,
|
||||
model,
|
||||
]);
|
||||
ChainFactory.instances.set(ChainType.LLM_CHAIN, instance);
|
||||
logInfo("New LLM chain created.");
|
||||
return instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the LLM chain singleton from the map.
|
||||
*
|
||||
* @param {LLMChainInput} args - the input for the LLM chain
|
||||
* @return {RunnableSequence} the LLM chain instance
|
||||
*/
|
||||
public static getLLMChainFromMap(args: LLMChainInput): RunnableSequence {
|
||||
let instance = ChainFactory.instances.get(ChainType.LLM_CHAIN);
|
||||
if (!instance) {
|
||||
instance = ChainFactory.createNewLLMChain(args);
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a conversational retrieval chain with the given parameters. Not a singleton.
|
||||
*
|
||||
* Example invocation:
|
||||
*
|
||||
* ```ts
|
||||
* const conversationalRetrievalChain = ChainFactory.createConversationalRetrievalChain({
|
||||
* llm: model,
|
||||
* retriever: retriever
|
||||
* });
|
||||
*
|
||||
* const response = await conversationalRetrievalChain.invoke({
|
||||
* question: "What are they made out of?",
|
||||
* chat_history: [
|
||||
* [
|
||||
* "What is the powerhouse of the cell?",
|
||||
* "The powerhouse of the cell is the mitochondria.",
|
||||
* ],
|
||||
* ],
|
||||
* });
|
||||
* ```
|
||||
*
|
||||
* @param {ConversationalRetrievalChainParams} args - the parameters for the retrieval chain
|
||||
* @return {RunnableSequence} a new conversational retrieval chain
|
||||
*/
|
||||
public static createConversationalRetrievalChain(
|
||||
args: ConversationalRetrievalChainParams,
|
||||
onDocumentsRetrieved: (documents: Document[]) => void,
|
||||
debug?: boolean
|
||||
): RunnableSequence {
|
||||
const { llm, retriever, systemMessage } = args;
|
||||
|
||||
// NOTE: This is a tricky part of the Conversational RAG. Weaker models may fail this instruction
|
||||
// and lose the follow up question altogether.
|
||||
const condenseQuestionTemplate = `Given the following conversation and a follow up question,
|
||||
summarize the conversation as context and keep the follow up question unchanged, in its original language.
|
||||
If the follow up question is unrelated to its preceding messages, return this follow up question directly.
|
||||
If it is related, then combine the summary and the follow up question to construct a standalone question.
|
||||
Make sure to keep any [[]] wrapped note titles in the question unchanged.
|
||||
|
||||
Chat History:
|
||||
{chat_history}
|
||||
Follow Up Input: {question}
|
||||
Standalone question:`;
|
||||
const CONDENSE_QUESTION_PROMPT = PromptTemplate.fromTemplate(condenseQuestionTemplate);
|
||||
|
||||
const answerTemplate = `{system_message}
|
||||
|
||||
Answer the question with as detailed as possible based only on the following context:
|
||||
{context}
|
||||
|
||||
Question: {question}
|
||||
`;
|
||||
const ANSWER_PROMPT = PromptTemplate.fromTemplate(answerTemplate);
|
||||
|
||||
const formatChatHistory = (chatHistory: [string, string][]) => {
|
||||
const formattedDialogueTurns = chatHistory.map(
|
||||
(dialogueTurn) => `Human: ${dialogueTurn[0]}\nAssistant: ${dialogueTurn[1]}`
|
||||
);
|
||||
return formattedDialogueTurns.join("\n");
|
||||
};
|
||||
|
||||
const standaloneQuestionChain = RunnableSequence.from([
|
||||
{
|
||||
question: (input: ConversationalRetrievalQAChainInput) => {
|
||||
if (debug) logInfo("Input Question: ", input.question);
|
||||
return input.question;
|
||||
},
|
||||
chat_history: (input: ConversationalRetrievalQAChainInput) => {
|
||||
const formattedChatHistory = formatChatHistory(input.chat_history);
|
||||
if (debug) logInfo("Formatted Chat History: ", formattedChatHistory);
|
||||
return formattedChatHistory;
|
||||
},
|
||||
},
|
||||
CONDENSE_QUESTION_PROMPT,
|
||||
llm,
|
||||
new StringOutputParser(),
|
||||
(output) => {
|
||||
const thinkTagsCleaned = removeThinkTags(output);
|
||||
const cleanedOutput = removeErrorTags(thinkTagsCleaned);
|
||||
if (debug) logInfo("Standalone Question: ", cleanedOutput);
|
||||
return cleanedOutput;
|
||||
},
|
||||
]);
|
||||
|
||||
const formatDocumentsAsStringAndStore = async (documents: Document[]) => {
|
||||
// Store or log documents for debugging
|
||||
onDocumentsRetrieved(documents);
|
||||
return formatDocumentsAsString(documents);
|
||||
};
|
||||
|
||||
const answerChain = RunnableSequence.from([
|
||||
{
|
||||
context: retriever.pipe(formatDocumentsAsStringAndStore),
|
||||
question: new RunnablePassthrough(),
|
||||
system_message: () => systemMessage,
|
||||
},
|
||||
ANSWER_PROMPT,
|
||||
llm,
|
||||
]);
|
||||
|
||||
const conversationalRetrievalQAChain = standaloneQuestionChain.pipe(answerChain);
|
||||
return conversationalRetrievalQAChain as RunnableSequence;
|
||||
}
|
||||
}
|
||||
|
||||
export default ChainFactory;
|
||||
|
|
@ -4,7 +4,6 @@
|
|||
*/
|
||||
|
||||
import { RunnableSequence } from "@langchain/core/runnables";
|
||||
import { BaseChatMemory, BufferMemory } from "@langchain/classic/memory";
|
||||
import {
|
||||
ChatPromptTemplate,
|
||||
HumanMessagePromptTemplate,
|
||||
|
|
@ -12,13 +11,14 @@ import {
|
|||
SystemMessagePromptTemplate,
|
||||
} from "@langchain/core/prompts";
|
||||
import ChatModelManager from "@/LLMProviders/chatModelManager";
|
||||
import { ChatBufferMemory } from "@/LLMProviders/chatBufferMemory";
|
||||
import { CustomModel } from "@/aiParams";
|
||||
|
||||
/**
|
||||
* Creates a new BufferMemory instance for chat history.
|
||||
* Creates a new ChatBufferMemory instance for chat history.
|
||||
*/
|
||||
export function createChatMemory(): BufferMemory {
|
||||
return new BufferMemory({
|
||||
export function createChatMemory(): ChatBufferMemory {
|
||||
return new ChatBufferMemory({
|
||||
returnMessages: true,
|
||||
memoryKey: "history",
|
||||
});
|
||||
|
|
@ -35,7 +35,7 @@ export function createChatMemory(): BufferMemory {
|
|||
export async function createChatChain(
|
||||
selectedModel: CustomModel,
|
||||
systemPrompt: string,
|
||||
memory: BaseChatMemory
|
||||
memory: ChatBufferMemory
|
||||
): Promise<RunnableSequence> {
|
||||
const chatModel = await ChatModelManager.getInstance().createModelInstance(selectedModel);
|
||||
|
||||
|
|
|
|||
|
|
@ -1,13 +1,3 @@
|
|||
// Mock chainFactory before importing anything else to avoid import errors
|
||||
jest.mock("@/chainFactory", () => ({
|
||||
ChainType: {
|
||||
LLM_CHAIN: "llm_chain",
|
||||
VAULT_QA_CHAIN: "vault_qa",
|
||||
COPILOT_PLUS_CHAIN: "copilot_plus",
|
||||
PROJECT_CHAIN: "project",
|
||||
},
|
||||
}));
|
||||
|
||||
import { ContextProcessor } from "@/contextProcessor";
|
||||
import { DATAVIEW_BLOCK_TAG } from "@/constants";
|
||||
|
||||
|
|
|
|||
|
|
@ -1,11 +1,3 @@
|
|||
jest.mock("@/chainFactory", () => ({
|
||||
ChainType: {
|
||||
LLM_CHAIN: "llm_chain",
|
||||
COPILOT_PLUS_CHAIN: "copilot_plus",
|
||||
PROJECT_CHAIN: "project_chain",
|
||||
},
|
||||
}));
|
||||
|
||||
import { ContextProcessor } from "@/contextProcessor";
|
||||
import type { FileParserManager } from "@/tools/FileParserManager";
|
||||
import { EMBEDDED_NOTE_TAG } from "@/constants";
|
||||
|
|
|
|||
|
|
@ -12,14 +12,6 @@ jest.mock("@/chatUtils", () => ({
|
|||
updateChatMemory: jest.fn(),
|
||||
}));
|
||||
|
||||
jest.mock("@/chainFactory", () => ({
|
||||
ChainType: {
|
||||
LLM_CHAIN: "llm_chain",
|
||||
COPILOT_PLUS_CHAIN: "copilot_plus_chain",
|
||||
PROJECT_CHAIN: "project_chain",
|
||||
},
|
||||
}));
|
||||
|
||||
jest.mock("./ChatPersistenceManager", () => ({
|
||||
ChatPersistenceManager: jest.fn().mockImplementation(() => ({
|
||||
saveChat: jest.fn().mockResolvedValue({ success: true, path: "/test/path.md" }),
|
||||
|
|
|
|||
|
|
@ -9,14 +9,6 @@
|
|||
import { PromptContextEnvelope, PromptLayerSegment } from "@/context/PromptContextTypes";
|
||||
|
||||
// Minimal mocks to avoid deep dependency chains
|
||||
jest.mock("@/chainFactory", () => ({
|
||||
ChainType: {
|
||||
LLM_CHAIN: "llm_chain",
|
||||
COPILOT_PLUS_CHAIN: "copilot_plus_chain",
|
||||
PROJECT_CHAIN: "project_chain",
|
||||
},
|
||||
}));
|
||||
|
||||
jest.mock("@/aiParams", () => ({
|
||||
getSelectedTextContexts: jest.fn().mockReturnValue([]),
|
||||
}));
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@
|
|||
|
||||
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
|
||||
import type { RunnableSequence } from "@langchain/core/runnables";
|
||||
import type { BaseChatMemory } from "@langchain/classic/memory";
|
||||
import type { ChatBufferMemory } from "@/LLMProviders/chatBufferMemory";
|
||||
|
||||
import type { CustomModel } from "@/aiParams";
|
||||
import { createChatChain, createChatMemory } from "@/commands/customCommandChatEngine";
|
||||
|
|
@ -70,7 +70,7 @@ export interface StreamingChatSessionApi {
|
|||
reset: () => void;
|
||||
|
||||
/** Get the current memory instance (for saving partial context on stop). */
|
||||
getMemory: () => BaseChatMemory | null;
|
||||
getMemory: () => ChatBufferMemory | null;
|
||||
|
||||
/** Get the latest streaming text from ref (bypasses RAF throttle). */
|
||||
getLatestStreamingText: () => string;
|
||||
|
|
@ -78,7 +78,7 @@ export interface StreamingChatSessionApi {
|
|||
|
||||
interface ChainAndMemory {
|
||||
chain: RunnableSequence;
|
||||
memory: BaseChatMemory;
|
||||
memory: ChatBufferMemory;
|
||||
}
|
||||
|
||||
/** Returns a stable key for caching chain per model. */
|
||||
|
|
@ -129,7 +129,7 @@ export function useStreamingChatSession(
|
|||
onNonAbortErrorRef.current = onNonAbortError;
|
||||
}, [onNoModel, onNonAbortError]);
|
||||
|
||||
const memoryRef = useRef<BaseChatMemory | null>(null);
|
||||
const memoryRef = useRef<ChatBufferMemory | null>(null);
|
||||
const chainRef = useRef<RunnableSequence | null>(null);
|
||||
const currentModelKeyRef = useRef<string | null>(null);
|
||||
const currentSystemPromptRef = useRef<string | null>(null);
|
||||
|
|
@ -215,7 +215,7 @@ export function useStreamingChatSession(
|
|||
return !hasSavedContextOnceRef.current;
|
||||
}, []);
|
||||
|
||||
const getMemory = useCallback((): BaseChatMemory | null => {
|
||||
const getMemory = useCallback((): ChatBufferMemory | null => {
|
||||
return memoryRef.current;
|
||||
}, []);
|
||||
|
||||
|
|
@ -283,7 +283,7 @@ export function useStreamingChatSession(
|
|||
const thinkStreamer = new ThinkBlockStreamer(turnScopedDelta, excludeThinking);
|
||||
|
||||
let didNonAbortError = false;
|
||||
let memory: BaseChatMemory | null = null;
|
||||
let memory: ChatBufferMemory | null = null;
|
||||
let prompt = "";
|
||||
let committed: string | null = null;
|
||||
|
||||
|
|
|
|||
|
|
@ -86,19 +86,6 @@ Array.prototype.contains = Array.prototype.includes;
|
|||
// Increase test timeout to 120 seconds for real LLM calls
|
||||
jest.setTimeout(120000);
|
||||
|
||||
// Mock only the essential dependencies
|
||||
jest.mock("@/chainFactory", () => ({
|
||||
ChainType: {
|
||||
LLM_CHAIN: "llm_chain",
|
||||
VAULT_QA_CHAIN: "vault_qa",
|
||||
COPILOT_PLUS_CHAIN: "copilot_plus",
|
||||
PROJECT_CHAIN: "project",
|
||||
},
|
||||
default: jest.fn().mockImplementation(() => ({
|
||||
instances: new Map(),
|
||||
})),
|
||||
}));
|
||||
|
||||
// Mock Obsidian - essential for tool initialization
|
||||
jest.mock("obsidian", () => ({
|
||||
App: jest.fn(),
|
||||
|
|
|
|||
22
src/utils.ts
22
src/utils.ts
|
|
@ -3,7 +3,6 @@
|
|||
// eslint-disable-next-line import/no-nodejs-modules
|
||||
import { Buffer } from "buffer";
|
||||
|
||||
import { Document } from "@/chainFactory";
|
||||
import { ChainType } from "@/chainType";
|
||||
import {
|
||||
ALLOWED_NOTE_CONTEXT_EXTENSIONS,
|
||||
|
|
@ -19,9 +18,8 @@ import {
|
|||
import { logInfo, logWarn } from "@/logger";
|
||||
import { CopilotSettings } from "@/settings/model";
|
||||
import { BaseChatModel } from "@langchain/core/language_models/chat_models";
|
||||
import { Document } from "@langchain/core/documents";
|
||||
import { MemoryVariables } from "@langchain/core/memory";
|
||||
import { RunnableSequence } from "@langchain/core/runnables";
|
||||
import { BaseChain, RetrievalQAChain } from "@langchain/classic/chains";
|
||||
import { DateTime } from "luxon";
|
||||
import { MarkdownView, Notice, TFile, Vault, normalizePath, requestUrl } from "obsidian";
|
||||
import { CustomModel } from "./aiParams";
|
||||
|
|
@ -254,24 +252,6 @@ export function getNotesFromTags(vault: Vault, tags: string[], noteFiles?: TFile
|
|||
return filesWithTag;
|
||||
}
|
||||
|
||||
// TODO: These chain validation functions are deprecated
|
||||
// Remove after confirming chainManager no longer uses them
|
||||
const isLLMChain = (chain: RunnableSequence): chain is RunnableSequence => {
|
||||
const c = chain as unknown as Record<string, unknown>;
|
||||
const last = c.last as Record<string, unknown> | undefined;
|
||||
return Boolean(last?.modelName || last?.model);
|
||||
};
|
||||
|
||||
const isRetrievalQAChain = (chain: BaseChain): chain is RetrievalQAChain => {
|
||||
const c = chain as unknown as Record<string, unknown>;
|
||||
const last = c.last as Record<string, unknown> | undefined;
|
||||
return last?.retriever !== undefined;
|
||||
};
|
||||
|
||||
export const isSupportedChain = (chain: RunnableSequence): chain is RunnableSequence => {
|
||||
return isLLMChain(chain) || isRetrievalQAChain(chain);
|
||||
};
|
||||
|
||||
export interface FormattedDateTime {
|
||||
fileName: string;
|
||||
display: string;
|
||||
|
|
|
|||
Loading…
Reference in a new issue