Merge branch 'main' into local-pr-3734
This commit is contained in:
@@ -1,13 +0,0 @@
|
||||
diff --git a/src/markdown-loader.js b/src/markdown-loader.js
|
||||
index eaf30b114a273e68abbb92c8b07018495e63f4cb..4b06519bdb51845e4693fe877da9de01c7a81039 100644
|
||||
--- a/src/markdown-loader.js
|
||||
+++ b/src/markdown-loader.js
|
||||
@@ -21,7 +21,7 @@ export class MarkdownLoader extends BaseLoader {
|
||||
? (await getSafe(this.filePathOrUrl, { format: 'buffer' })).body
|
||||
: await streamToBuffer(fs.createReadStream(this.filePathOrUrl));
|
||||
this.debug('MarkdownLoader stream created');
|
||||
- const result = micromark(buffer, { extensions: [gfm(), mdxJsx()], htmlExtensions: [gfmHtml()] });
|
||||
+ const result = micromark(buffer, { extensions: [gfm()], htmlExtensions: [gfmHtml()] });
|
||||
this.debug('Markdown parsed...');
|
||||
const webLoader = new WebLoader({
|
||||
urlOrContent: result,
|
||||
@@ -1,158 +0,0 @@
|
||||
diff --git a/src/loaders/local-path-loader.d.ts b/src/loaders/local-path-loader.d.ts
|
||||
index 48c20e68c469cd309be2dc8f28e44c1bd04a26e9..1c16d83bcbf9b7140292793d6cbb8c04281949d9 100644
|
||||
--- a/src/loaders/local-path-loader.d.ts
|
||||
+++ b/src/loaders/local-path-loader.d.ts
|
||||
@@ -4,8 +4,10 @@ export declare class LocalPathLoader extends BaseLoader<{
|
||||
}> {
|
||||
private readonly debug;
|
||||
private readonly path;
|
||||
- constructor({ path }: {
|
||||
+ constructor({ path, chunkSize, chunkOverlap }: {
|
||||
path: string;
|
||||
+ chunkSize?: number;
|
||||
+ chunkOverlap?: number;
|
||||
});
|
||||
getUnfilteredChunks(): AsyncGenerator<{
|
||||
metadata: {
|
||||
diff --git a/src/loaders/local-path-loader.js b/src/loaders/local-path-loader.js
|
||||
index 4cf8a6bd1d890244c8ec49d4a05ee3bd58861c79..ec8215b01195a21ef20f3c5d56ecc99f186bb596 100644
|
||||
--- a/src/loaders/local-path-loader.js
|
||||
+++ b/src/loaders/local-path-loader.js
|
||||
@@ -8,8 +8,8 @@ import { BaseLoader } from '@llm-tools/embedjs-interfaces';
|
||||
export class LocalPathLoader extends BaseLoader {
|
||||
debug = createDebugMessages('embedjs:loader:LocalPathLoader');
|
||||
path;
|
||||
- constructor({ path }) {
|
||||
- super(`LocalPathLoader_${md5(path)}`, { path });
|
||||
+ constructor({ path, chunkSize, chunkOverlap }) {
|
||||
+ super(`LocalPathLoader_${md5(path)}`, { path }, chunkSize ?? 1000, chunkOverlap ?? 0);
|
||||
this.path = path;
|
||||
}
|
||||
async *getUnfilteredChunks() {
|
||||
@@ -36,10 +36,12 @@ export class LocalPathLoader extends BaseLoader {
|
||||
const extension = currentPath.split('.').pop().toLowerCase();
|
||||
if (extension === 'md' || extension === 'mdx')
|
||||
mime = 'text/markdown';
|
||||
+ if (extension === 'txt')
|
||||
+ mime = 'text/plain';
|
||||
this.debug(`File '${this.path}' mime type updated to 'text/markdown'`);
|
||||
}
|
||||
try {
|
||||
- const loader = await createLoaderFromMimeType(currentPath, mime);
|
||||
+ const loader = await createLoaderFromMimeType(currentPath, mime, this.chunkSize, this.chunkOverlap);
|
||||
for await (const result of await loader.getUnfilteredChunks()) {
|
||||
yield {
|
||||
pageContent: result.pageContent,
|
||||
diff --git a/src/util/mime.d.ts b/src/util/mime.d.ts
|
||||
index 57f56a1b8edc98366af9f84d671676c41c2f01ca..14be3b5727cff6eb1978838045e9a788f8f53bfb 100644
|
||||
--- a/src/util/mime.d.ts
|
||||
+++ b/src/util/mime.d.ts
|
||||
@@ -1,2 +1,2 @@
|
||||
import { BaseLoader } from '@llm-tools/embedjs-interfaces';
|
||||
-export declare function createLoaderFromMimeType(loaderData: string, mimeType: string): Promise<BaseLoader>;
|
||||
+export declare function createLoaderFromMimeType(loaderData: string, mimeType: string, chunkSize?: number, chunkOverlap?: number): Promise<BaseLoader>;
|
||||
diff --git a/src/util/mime.js b/src/util/mime.js
|
||||
index b6426a859968e2bf6206795f70333e90ae27aeb7..16ae2adb863f8d7abfa757f1c5cc39f6bb1c44fa 100644
|
||||
--- a/src/util/mime.js
|
||||
+++ b/src/util/mime.js
|
||||
@@ -1,7 +1,9 @@
|
||||
import mime from 'mime';
|
||||
import createDebugMessages from 'debug';
|
||||
import { TextLoader } from '../loaders/text-loader.js';
|
||||
-export async function createLoaderFromMimeType(loaderData, mimeType) {
|
||||
+import fs from 'node:fs'
|
||||
+
|
||||
+export async function createLoaderFromMimeType(loaderData, mimeType, chunkSize, chunkOverlap) {
|
||||
createDebugMessages('embedjs:util:createLoaderFromMimeType')(`Incoming mime type '${mimeType}'`);
|
||||
switch (mimeType) {
|
||||
case 'application/msword':
|
||||
@@ -10,7 +12,7 @@ export async function createLoaderFromMimeType(loaderData, mimeType) {
|
||||
throw new Error('Package `@llm-tools/embedjs-loader-msoffice` needs to be installed to load docx files');
|
||||
});
|
||||
createDebugMessages('embedjs:util:createLoaderFromMimeType')('Dynamically imported DocxLoader');
|
||||
- return new DocxLoader({ filePathOrUrl: loaderData });
|
||||
+ return new DocxLoader({ filePathOrUrl: loaderData, chunkSize, chunkOverlap });
|
||||
}
|
||||
case 'application/vnd.ms-excel':
|
||||
case 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet': {
|
||||
@@ -18,21 +20,21 @@ export async function createLoaderFromMimeType(loaderData, mimeType) {
|
||||
throw new Error('Package `@llm-tools/embedjs-loader-msoffice` needs to be installed to load excel files');
|
||||
});
|
||||
createDebugMessages('embedjs:util:createLoaderFromMimeType')('Dynamically imported ExcelLoader');
|
||||
- return new ExcelLoader({ filePathOrUrl: loaderData });
|
||||
+ return new ExcelLoader({ filePathOrUrl: loaderData, chunkSize, chunkOverlap });
|
||||
}
|
||||
case 'application/pdf': {
|
||||
const { PdfLoader } = await import('@llm-tools/embedjs-loader-pdf').catch(() => {
|
||||
throw new Error('Package `@llm-tools/embedjs-loader-pdf` needs to be installed to load PDF files');
|
||||
});
|
||||
createDebugMessages('embedjs:util:createLoaderFromMimeType')('Dynamically imported PdfLoader');
|
||||
- return new PdfLoader({ filePathOrUrl: loaderData });
|
||||
+ return new PdfLoader({ filePathOrUrl: loaderData, chunkSize, chunkOverlap });
|
||||
}
|
||||
case 'application/vnd.openxmlformats-officedocument.presentationml.presentation': {
|
||||
const { PptLoader } = await import('@llm-tools/embedjs-loader-msoffice').catch(() => {
|
||||
throw new Error('Package `@llm-tools/embedjs-loader-msoffice` needs to be installed to load pptx files');
|
||||
});
|
||||
createDebugMessages('embedjs:util:createLoaderFromMimeType')('Dynamically imported PptLoader');
|
||||
- return new PptLoader({ filePathOrUrl: loaderData });
|
||||
+ return new PptLoader({ filePathOrUrl: loaderData, chunkSize, chunkOverlap });
|
||||
}
|
||||
case 'text/plain': {
|
||||
const fineType = mime.getType(loaderData);
|
||||
@@ -42,24 +44,24 @@ export async function createLoaderFromMimeType(loaderData, mimeType) {
|
||||
throw new Error('Package `@llm-tools/embedjs-loader-csv` needs to be installed to load CSV files');
|
||||
});
|
||||
createDebugMessages('embedjs:util:createLoaderFromMimeType')('Dynamically imported CsvLoader');
|
||||
- return new CsvLoader({ filePathOrUrl: loaderData });
|
||||
+ return new CsvLoader({ filePathOrUrl: loaderData, chunkSize, chunkOverlap });
|
||||
}
|
||||
- else
|
||||
- return new TextLoader({ text: loaderData });
|
||||
+ const content = fs.readFileSync(loaderData, 'utf-8');
|
||||
+ return new TextLoader({ text: content, chunkSize, chunkOverlap });
|
||||
}
|
||||
case 'application/csv': {
|
||||
const { CsvLoader } = await import('@llm-tools/embedjs-loader-csv').catch(() => {
|
||||
throw new Error('Package `@llm-tools/embedjs-loader-csv` needs to be installed to load CSV files');
|
||||
});
|
||||
createDebugMessages('embedjs:util:createLoaderFromMimeType')('Dynamically imported CsvLoader');
|
||||
- return new CsvLoader({ filePathOrUrl: loaderData });
|
||||
+ return new CsvLoader({ filePathOrUrl: loaderData, chunkSize, chunkOverlap });
|
||||
}
|
||||
case 'text/html': {
|
||||
const { WebLoader } = await import('@llm-tools/embedjs-loader-web').catch(() => {
|
||||
throw new Error('Package `@llm-tools/embedjs-loader-web` needs to be installed to load web documents');
|
||||
});
|
||||
createDebugMessages('embedjs:util:createLoaderFromMimeType')('Dynamically imported WebLoader');
|
||||
- return new WebLoader({ urlOrContent: loaderData });
|
||||
+ return new WebLoader({ urlOrContent: loaderData, chunkSize, chunkOverlap });
|
||||
}
|
||||
case 'text/xml': {
|
||||
const { SitemapLoader } = await import('@llm-tools/embedjs-loader-sitemap').catch(() => {
|
||||
@@ -67,14 +69,14 @@ export async function createLoaderFromMimeType(loaderData, mimeType) {
|
||||
});
|
||||
createDebugMessages('embedjs:util:createLoaderFromMimeType')('Dynamically imported SitemapLoader');
|
||||
if (await SitemapLoader.test(loaderData)) {
|
||||
- return new SitemapLoader({ url: loaderData });
|
||||
+ return new SitemapLoader({ url: loaderData, chunkSize, chunkOverlap });
|
||||
}
|
||||
//This is not a Sitemap but is still XML
|
||||
const { XmlLoader } = await import('@llm-tools/embedjs-loader-xml').catch(() => {
|
||||
throw new Error('Package `@llm-tools/embedjs-loader-xml` needs to be installed to load XML documents');
|
||||
});
|
||||
createDebugMessages('embedjs:util:createLoaderFromMimeType')('Dynamically imported XmlLoader');
|
||||
- return new XmlLoader({ filePathOrUrl: loaderData });
|
||||
+ return new XmlLoader({ filePathOrUrl: loaderData, chunkSize, chunkOverlap });
|
||||
}
|
||||
case 'text/x-markdown':
|
||||
case 'text/markdown': {
|
||||
@@ -82,7 +84,7 @@ export async function createLoaderFromMimeType(loaderData, mimeType) {
|
||||
throw new Error('Package `@llm-tools/embedjs-loader-markdown` needs to be installed to load markdown files');
|
||||
});
|
||||
createDebugMessages('embedjs:util:createLoaderFromMimeType')('Dynamically imported MarkdownLoader');
|
||||
- return new MarkdownLoader({ filePathOrUrl: loaderData });
|
||||
+ return new MarkdownLoader({ filePathOrUrl: loaderData, chunkSize, chunkOverlap });
|
||||
}
|
||||
case 'image/png':
|
||||
case 'image/jpeg': {
|
||||
@@ -84,8 +84,9 @@ https://docs.cherry-ai.com
|
||||
|
||||
# 🌈 Theme
|
||||
|
||||
Theme Gallery: https://cherrycss.com
|
||||
Aero Theme: https://github.com/hakadao/CherryStudio-Aero
|
||||
- Theme Gallery: https://cherrycss.com
|
||||
- Aero Theme: https://github.com/hakadao/CherryStudio-Aero
|
||||
- PaperMaterial Theme: https://github.com/rainoffallingstar/CherryStudio-PaperMaterial
|
||||
|
||||
Welcome PR for more themes
|
||||
|
||||
|
||||
+10
-10
@@ -12,16 +12,16 @@ export default defineConfig({
|
||||
plugins: [
|
||||
externalizeDepsPlugin({
|
||||
exclude: [
|
||||
'@llm-tools/embedjs',
|
||||
'@llm-tools/embedjs-openai',
|
||||
'@llm-tools/embedjs-loader-web',
|
||||
'@llm-tools/embedjs-loader-markdown',
|
||||
'@llm-tools/embedjs-loader-msoffice',
|
||||
'@llm-tools/embedjs-loader-xml',
|
||||
'@llm-tools/embedjs-loader-pdf',
|
||||
'@llm-tools/embedjs-loader-sitemap',
|
||||
'@llm-tools/embedjs-libsql',
|
||||
'@llm-tools/embedjs-loader-image',
|
||||
'@cherrystudio/embedjs',
|
||||
'@cherrystudio/embedjs-openai',
|
||||
'@cherrystudio/embedjs-loader-web',
|
||||
'@cherrystudio/embedjs-loader-markdown',
|
||||
'@cherrystudio/embedjs-loader-msoffice',
|
||||
'@cherrystudio/embedjs-loader-xml',
|
||||
'@cherrystudio/embedjs-loader-pdf',
|
||||
'@cherrystudio/embedjs-loader-sitemap',
|
||||
'@cherrystudio/embedjs-libsql',
|
||||
'@cherrystudio/embedjs-loader-image',
|
||||
'p-queue',
|
||||
'webdav'
|
||||
]
|
||||
|
||||
+17
-19
@@ -50,21 +50,22 @@
|
||||
"prepare": "husky"
|
||||
},
|
||||
"dependencies": {
|
||||
"@cherrystudio/embedjs": "^0.1.28",
|
||||
"@cherrystudio/embedjs-libsql": "^0.1.28",
|
||||
"@cherrystudio/embedjs-loader-csv": "^0.1.28",
|
||||
"@cherrystudio/embedjs-loader-image": "^0.1.28",
|
||||
"@cherrystudio/embedjs-loader-markdown": "^0.1.28",
|
||||
"@cherrystudio/embedjs-loader-msoffice": "^0.1.28",
|
||||
"@cherrystudio/embedjs-loader-pdf": "^0.1.28",
|
||||
"@cherrystudio/embedjs-loader-sitemap": "^0.1.28",
|
||||
"@cherrystudio/embedjs-loader-web": "^0.1.28",
|
||||
"@cherrystudio/embedjs-loader-xml": "^0.1.28",
|
||||
"@cherrystudio/embedjs-openai": "^0.1.28",
|
||||
"@cherrystudio/mac-system-ocr": "^0.1.0",
|
||||
"@electron-toolkit/utils": "^3.0.0",
|
||||
"@electron/notarize": "^2.5.0",
|
||||
"@google/generative-ai": "^0.21.0",
|
||||
"@langchain/community": "^0.3.36",
|
||||
"@llm-tools/embedjs": "patch:@llm-tools/embedjs@npm%3A0.1.28#~/.yarn/patches/@llm-tools-embedjs-npm-0.1.28-8e4393fa2d.patch",
|
||||
"@llm-tools/embedjs-libsql": "^0.1.28",
|
||||
"@llm-tools/embedjs-loader-csv": "^0.1.28",
|
||||
"@llm-tools/embedjs-loader-markdown": "patch:@llm-tools/embedjs-loader-markdown@npm%3A0.1.28#~/.yarn/patches/@llm-tools-embedjs-loader-markdown-npm-0.1.28-81647ffac6.patch",
|
||||
"@llm-tools/embedjs-loader-msoffice": "^0.1.28",
|
||||
"@llm-tools/embedjs-loader-pdf": "^0.1.28",
|
||||
"@llm-tools/embedjs-loader-sitemap": "^0.1.28",
|
||||
"@llm-tools/embedjs-loader-web": "^0.1.28",
|
||||
"@llm-tools/embedjs-loader-xml": "^0.1.28",
|
||||
"@llm-tools/embedjs-openai": "^0.1.28",
|
||||
"@mistralai/mistralai": "^1.5.2",
|
||||
"@modelcontextprotocol/sdk": "patch:@modelcontextprotocol/sdk@npm%3A1.6.1#~/.yarn/patches/@modelcontextprotocol-sdk-npm-1.6.1-b46313efe7.patch",
|
||||
"@notionhq/client": "^2.2.15",
|
||||
@@ -95,6 +96,7 @@
|
||||
"@agentic/exa": "^7.3.3",
|
||||
"@agentic/searxng": "^7.3.3",
|
||||
"@agentic/tavily": "^7.3.3",
|
||||
"@ant-design/v5-patch-for-react-19": "^1.0.3",
|
||||
"@anthropic-ai/sdk": "^0.38.0",
|
||||
"@electron-toolkit/eslint-config-prettier": "^3.0.0",
|
||||
"@electron-toolkit/eslint-config-ts": "^3.0.0",
|
||||
@@ -106,7 +108,6 @@
|
||||
"@google/genai": "^0.4.0",
|
||||
"@hello-pangea/dnd": "^16.6.0",
|
||||
"@kangfenmao/keyv-storage": "^0.1.0",
|
||||
"@llm-tools/embedjs-loader-image": "^0.1.28",
|
||||
"@notionhq/client": "^2.2.15",
|
||||
"@reduxjs/toolkit": "^2.2.5",
|
||||
"@tavily/core": "patch:@tavily/core@npm%3A0.3.1#~/.yarn/patches/@tavily-core-npm-0.3.1-fe69bf2bea.patch",
|
||||
@@ -119,8 +120,8 @@
|
||||
"@types/node": "^18.19.9",
|
||||
"@types/pako": "^1.0.2",
|
||||
"@types/pdf-parse": "^1.1.4",
|
||||
"@types/react": "^18.2.48",
|
||||
"@types/react-dom": "^18.2.18",
|
||||
"@types/react": "^19.0.12",
|
||||
"@types/react-dom": "^19.0.4",
|
||||
"@types/react-infinite-scroll-component": "^5.0.0",
|
||||
"@types/tinycolor2": "^1",
|
||||
"@vitejs/plugin-react": "^4.2.1",
|
||||
@@ -154,8 +155,9 @@
|
||||
"openai": "patch:openai@npm%3A4.77.3#~/.yarn/patches/openai-npm-4.77.3-59c6d42e7a.patch",
|
||||
"p-queue": "^8.1.0",
|
||||
"prettier": "^3.5.3",
|
||||
"react": "^18.2.0",
|
||||
"react-dom": "^18.2.0",
|
||||
"rc-virtual-list": "^3.18.5",
|
||||
"react": "^19.0.0",
|
||||
"react-dom": "^19.0.0",
|
||||
"react-hotkeys-hook": "^4.6.1",
|
||||
"react-i18next": "^14.1.2",
|
||||
"react-infinite-scroll-component": "^6.1.0",
|
||||
@@ -182,10 +184,6 @@
|
||||
"uuid": "^10.0.0",
|
||||
"vite": "^5.0.12"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": "^17.0.0 || ^18.0.0",
|
||||
"react-dom": "^17.0.0 || ^18.0.0"
|
||||
},
|
||||
"resolutions": {
|
||||
"pdf-parse@npm:1.1.1": "patch:pdf-parse@npm%3A1.1.1#~/.yarn/patches/pdf-parse-npm-1.1.1-04a6109b2a.patch",
|
||||
"@langchain/openai@npm:^0.3.16": "patch:@langchain/openai@npm%3A0.3.16#~/.yarn/patches/@langchain-openai-npm-0.3.16-e525b59526.patch",
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { BaseEmbeddings } from '@llm-tools/embedjs-interfaces'
|
||||
import type { BaseEmbeddings } from '@cherrystudio/embedjs-interfaces'
|
||||
import { KnowledgeBaseParams } from '@types'
|
||||
|
||||
import EmbeddingsFactory from './EmbeddingsFactory'
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import type { BaseEmbeddings } from '@llm-tools/embedjs-interfaces'
|
||||
import { OpenAiEmbeddings } from '@llm-tools/embedjs-openai'
|
||||
import { AzureOpenAiEmbeddings } from '@llm-tools/embedjs-openai/src/azure-openai-embeddings'
|
||||
import type { BaseEmbeddings } from '@cherrystudio/embedjs-interfaces'
|
||||
import { OpenAiEmbeddings } from '@cherrystudio/embedjs-openai'
|
||||
import { AzureOpenAiEmbeddings } from '@cherrystudio/embedjs-openai/src/azure-openai-embeddings'
|
||||
import { getInstanceName } from '@main/utils'
|
||||
import { KnowledgeBaseParams } from '@types'
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { BaseEmbeddings } from '@cherrystudio/embedjs-interfaces'
|
||||
import { VoyageEmbeddings as _VoyageEmbeddings } from '@langchain/community/embeddings/voyage'
|
||||
import { BaseEmbeddings } from '@llm-tools/embedjs-interfaces'
|
||||
|
||||
export default class VoyageEmbeddings extends BaseEmbeddings {
|
||||
private model: _VoyageEmbeddings
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import * as fs from 'node:fs'
|
||||
|
||||
import { JsonLoader } from '@llm-tools/embedjs'
|
||||
import { JsonLoader } from '@cherrystudio/embedjs'
|
||||
|
||||
/**
|
||||
* Drafts 应用导出的笔记文件加载器
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { BaseLoader } from '@cherrystudio/embedjs-interfaces'
|
||||
import { cleanString } from '@cherrystudio/embedjs-utils'
|
||||
import { RecursiveCharacterTextSplitter } from '@langchain/textsplitters'
|
||||
import { BaseLoader } from '@llm-tools/embedjs-interfaces'
|
||||
import { cleanString } from '@llm-tools/embedjs-utils'
|
||||
import { getTempDir } from '@main/utils/file'
|
||||
import Logger from 'electron-log'
|
||||
import EPub from 'epub'
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import * as fs from 'node:fs'
|
||||
|
||||
import { JsonLoader, LocalPathLoader, RAGApplication, TextLoader } from '@llm-tools/embedjs'
|
||||
import type { AddLoaderReturn } from '@llm-tools/embedjs-interfaces'
|
||||
import { WebLoader } from '@llm-tools/embedjs-loader-web'
|
||||
import { JsonLoader, LocalPathLoader, RAGApplication, TextLoader } from '@cherrystudio/embedjs'
|
||||
import type { AddLoaderReturn } from '@cherrystudio/embedjs-interfaces'
|
||||
import { WebLoader } from '@cherrystudio/embedjs-loader-web'
|
||||
import { LoaderReturn } from '@shared/config/types'
|
||||
import { FileType, KnowledgeBaseParams } from '@types'
|
||||
import Logger from 'electron-log'
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { BaseLoader } from '@cherrystudio/embedjs-interfaces'
|
||||
import { cleanString } from '@cherrystudio/embedjs-utils'
|
||||
import { RecursiveCharacterTextSplitter } from '@langchain/textsplitters'
|
||||
import { BaseLoader } from '@llm-tools/embedjs-interfaces'
|
||||
import { cleanString } from '@llm-tools/embedjs-utils'
|
||||
import md5 from 'md5'
|
||||
import { OfficeParserConfig, parseOfficeAsync } from 'officeparser'
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { ExtractChunkData } from '@llm-tools/embedjs-interfaces'
|
||||
import type { ExtractChunkData } from '@cherrystudio/embedjs-interfaces'
|
||||
import { KnowledgeBaseParams } from '@types'
|
||||
|
||||
export default abstract class BaseReranker {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { ExtractChunkData } from '@llm-tools/embedjs-interfaces'
|
||||
import type { ExtractChunkData } from '@cherrystudio/embedjs-interfaces'
|
||||
import { KnowledgeBaseParams } from '@types'
|
||||
|
||||
import BaseReranker from './BaseReranker'
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { ExtractChunkData } from '@llm-tools/embedjs-interfaces'
|
||||
import { ExtractChunkData } from '@cherrystudio/embedjs-interfaces'
|
||||
import { KnowledgeBaseParams } from '@types'
|
||||
import axios from 'axios'
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { ExtractChunkData } from '@llm-tools/embedjs-interfaces'
|
||||
import type { ExtractChunkData } from '@cherrystudio/embedjs-interfaces'
|
||||
import { KnowledgeBaseParams } from '@types'
|
||||
|
||||
import BaseReranker from './BaseReranker'
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { ExtractChunkData } from '@llm-tools/embedjs-interfaces'
|
||||
import type { ExtractChunkData } from '@cherrystudio/embedjs-interfaces'
|
||||
import { KnowledgeBaseParams } from '@types'
|
||||
import axios from 'axios'
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { ExtractChunkData } from '@llm-tools/embedjs-interfaces'
|
||||
import { ExtractChunkData } from '@cherrystudio/embedjs-interfaces'
|
||||
import { KnowledgeBaseParams } from '@types'
|
||||
import axios from 'axios'
|
||||
|
||||
|
||||
@@ -16,11 +16,11 @@
|
||||
import * as fs from 'node:fs'
|
||||
import path from 'node:path'
|
||||
|
||||
import { RAGApplication, RAGApplicationBuilder, TextLoader } from '@llm-tools/embedjs'
|
||||
import type { ExtractChunkData } from '@llm-tools/embedjs-interfaces'
|
||||
import { LibSqlDb } from '@llm-tools/embedjs-libsql'
|
||||
import { SitemapLoader } from '@llm-tools/embedjs-loader-sitemap'
|
||||
import { WebLoader } from '@llm-tools/embedjs-loader-web'
|
||||
import { RAGApplication, RAGApplicationBuilder, TextLoader } from '@cherrystudio/embedjs'
|
||||
import type { ExtractChunkData } from '@cherrystudio/embedjs-interfaces'
|
||||
import { LibSqlDb } from '@cherrystudio/embedjs-libsql'
|
||||
import { SitemapLoader } from '@cherrystudio/embedjs-loader-sitemap'
|
||||
import { WebLoader } from '@cherrystudio/embedjs-loader-web'
|
||||
import Embeddings from '@main/embeddings/Embeddings'
|
||||
import { addFileLoader } from '@main/loader'
|
||||
import OcrProvider from '@main/ocr/OcrProvider'
|
||||
|
||||
Vendored
+2
-1
@@ -1,5 +1,6 @@
|
||||
import { ExtractChunkData } from '@cherrystudio/embedjs-interfaces'
|
||||
import { ElectronAPI } from '@electron-toolkit/preload'
|
||||
import { ExtractChunkData } from '@llm-tools/embedjs-interfaces'
|
||||
import type { FileMetadataResponse, ListFilesResponse, UploadFileResponse } from '@google/generative-ai/server'
|
||||
import type { MCPServer, MCPTool } from '@renderer/types'
|
||||
import {
|
||||
AppInfo,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import type { ExtractChunkData } from '@cherrystudio/embedjs-interfaces'
|
||||
import { electronAPI } from '@electron-toolkit/preload'
|
||||
import type { ExtractChunkData } from '@llm-tools/embedjs-interfaces'
|
||||
import { FileType, KnowledgeBaseParams, KnowledgeItem, MCPServer, Shortcut, WebDavConfig } from '@types'
|
||||
import { contextBridge, ipcRenderer, OpenDialogOptions, shell } from 'electron'
|
||||
import { CreateDirectoryOptions } from 'webdav'
|
||||
|
||||
@@ -21,7 +21,7 @@ import PaintingsPage from './pages/paintings/PaintingsPage'
|
||||
import SettingsPage from './pages/settings/SettingsPage'
|
||||
import TranslatePage from './pages/translate/TranslatePage'
|
||||
|
||||
function App(): JSX.Element {
|
||||
function App(): React.ReactElement {
|
||||
return (
|
||||
<Provider store={store}>
|
||||
<StyleSheetManager>
|
||||
|
||||
@@ -8,6 +8,7 @@ import {
|
||||
OnDragStartResponder,
|
||||
ResponderProvided
|
||||
} from '@hello-pangea/dnd'
|
||||
import VirtualList from 'rc-virtual-list'
|
||||
import { droppableReorder } from '@renderer/utils'
|
||||
import { FC } from 'react'
|
||||
|
||||
@@ -47,26 +48,28 @@ const DragableList: FC<Props<any>> = ({
|
||||
<Droppable droppableId="droppable" {...droppableProps}>
|
||||
{(provided) => (
|
||||
<div {...provided.droppableProps} ref={provided.innerRef} style={style}>
|
||||
{list.map((item, index) => {
|
||||
const id = item.id || item
|
||||
return (
|
||||
<Draggable key={`draggable_${id}_${index}`} draggableId={id} index={index}>
|
||||
{(provided) => (
|
||||
<div
|
||||
ref={provided.innerRef}
|
||||
{...provided.draggableProps}
|
||||
{...provided.dragHandleProps}
|
||||
style={{
|
||||
...listStyle,
|
||||
...provided.draggableProps.style,
|
||||
marginBottom: 8
|
||||
}}>
|
||||
{children(item, index)}
|
||||
</div>
|
||||
)}
|
||||
</Draggable>
|
||||
)
|
||||
})}
|
||||
<VirtualList data={list} itemKey="id">
|
||||
{(item, index) => {
|
||||
const id = item.id || item
|
||||
return (
|
||||
<Draggable key={`draggable_${id}_${index}`} draggableId={id} index={index}>
|
||||
{(provided) => (
|
||||
<div
|
||||
ref={provided.innerRef}
|
||||
{...provided.draggableProps}
|
||||
{...provided.dragHandleProps}
|
||||
style={{
|
||||
...listStyle,
|
||||
...provided.draggableProps.style,
|
||||
marginBottom: 8
|
||||
}}>
|
||||
{children(item, index)}
|
||||
</div>
|
||||
)}
|
||||
</Draggable>
|
||||
)
|
||||
}}
|
||||
</VirtualList>
|
||||
{provided.placeholder}
|
||||
</div>
|
||||
)}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { throttle } from 'lodash'
|
||||
import { FC, forwardRef, useCallback, useEffect, useRef, useState } from 'react'
|
||||
import { FC, useCallback, useEffect, useRef, useState } from 'react'
|
||||
import styled from 'styled-components'
|
||||
|
||||
interface Props extends React.HTMLAttributes<HTMLDivElement> {
|
||||
@@ -7,7 +7,7 @@ interface Props extends React.HTMLAttributes<HTMLDivElement> {
|
||||
ref?: any
|
||||
}
|
||||
|
||||
const Scrollbar: FC<Props> = forwardRef<HTMLDivElement, Props>((props, ref) => {
|
||||
const Scrollbar: FC<Props> = ({ ref, ...props }: Props & { ref?: React.RefObject<HTMLDivElement | null> }) => {
|
||||
const [isScrolling, setIsScrolling] = useState(false)
|
||||
const timeoutRef = useRef<NodeJS.Timeout | null>(null)
|
||||
|
||||
@@ -35,7 +35,7 @@ const Scrollbar: FC<Props> = forwardRef<HTMLDivElement, Props>((props, ref) => {
|
||||
{props.children}
|
||||
</Container>
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
const Container = styled.div<{ isScrolling: boolean; right?: boolean }>`
|
||||
overflow-y: auto;
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
import { isMac } from '@renderer/config/constant'
|
||||
import useNavBackgroundColor from '@renderer/hooks/useNavBackgroundColor'
|
||||
import { FC, PropsWithChildren } from 'react'
|
||||
import type { FC, PropsWithChildren } from 'react'
|
||||
import type { HTMLAttributes } from 'react'
|
||||
import styled from 'styled-components'
|
||||
|
||||
type Props = PropsWithChildren & JSX.IntrinsicElements['div']
|
||||
type Props = PropsWithChildren & HTMLAttributes<HTMLDivElement>
|
||||
|
||||
export const Navbar: FC<Props> = ({ children, ...props }) => {
|
||||
const backgroundColor = useNavBackgroundColor()
|
||||
|
||||
@@ -149,6 +149,7 @@ const visionAllowedModels = [
|
||||
'qwen-vl',
|
||||
'qwen2-vl',
|
||||
'qwen2.5-vl',
|
||||
'qwen2.5-omni',
|
||||
'qvq',
|
||||
'internvl2',
|
||||
'grok-vision-beta',
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
import isPropValid from '@emotion/is-prop-valid'
|
||||
import { ReactNode } from 'react'
|
||||
import type { ReactNode } from 'react'
|
||||
import { StyleSheetManager as StyledComponentsStyleSheetManager } from 'styled-components'
|
||||
|
||||
interface StyleSheetManagerProps {
|
||||
children: ReactNode
|
||||
}
|
||||
|
||||
const StyleSheetManager = ({ children }: StyleSheetManagerProps): JSX.Element => {
|
||||
const StyleSheetManager = ({ children }: StyleSheetManagerProps): React.ReactElement => {
|
||||
return (
|
||||
<StyledComponentsStyleSheetManager
|
||||
shouldForwardProp={(prop, element) => {
|
||||
|
||||
@@ -1,16 +1,11 @@
|
||||
import { useTheme } from '@renderer/context/ThemeProvider'
|
||||
import { useMermaid } from '@renderer/hooks/useMermaid'
|
||||
import { useSettings } from '@renderer/hooks/useSettings'
|
||||
import { CodeStyleVarious, ThemeMode } from '@renderer/types'
|
||||
import React, { createContext, PropsWithChildren, useContext, useEffect, useMemo, useState } from 'react'
|
||||
import {
|
||||
BundledLanguage,
|
||||
bundledLanguages,
|
||||
BundledTheme,
|
||||
bundledThemes,
|
||||
createHighlighter,
|
||||
HighlighterGeneric
|
||||
} from 'shiki'
|
||||
import { type CodeStyleVarious, ThemeMode } from '@renderer/types'
|
||||
import type React from 'react'
|
||||
import { createContext, type PropsWithChildren, use, useCallback, useEffect, useMemo, useState } from 'react'
|
||||
import type { BundledLanguage, BundledTheme, HighlighterGeneric } from 'shiki'
|
||||
import { bundledLanguages, bundledThemes, createHighlighter } from 'shiki'
|
||||
|
||||
interface SyntaxHighlighterContextType {
|
||||
codeToHtml: (code: string, language: string) => Promise<string>
|
||||
@@ -51,42 +46,47 @@ export const SyntaxHighlighterProvider: React.FC<PropsWithChildren> = ({ childre
|
||||
initHighlighter()
|
||||
}, [highlighterTheme])
|
||||
|
||||
const codeToHtml = async (code: string, language: string) => {
|
||||
if (!highlighter) return ''
|
||||
const codeToHtml = useCallback(
|
||||
async (_code: string, language: string) => {
|
||||
{
|
||||
if (!highlighter) return ''
|
||||
|
||||
const languageMap: Record<string, string> = {
|
||||
vab: 'vb'
|
||||
}
|
||||
const languageMap: Record<string, string> = {
|
||||
vab: 'vb'
|
||||
}
|
||||
|
||||
const mappedLanguage = languageMap[language] || language
|
||||
const mappedLanguage = languageMap[language] || language
|
||||
|
||||
code = code?.trimEnd() ?? ''
|
||||
const escapedCode = code?.replace(/[<>]/g, (char) => ({ '<': '<', '>': '>' })[char]!)
|
||||
const code = _code?.trimEnd() ?? ''
|
||||
const escapedCode = code?.replace(/[<>]/g, (char) => ({ '<': '<', '>': '>' })[char]!)
|
||||
|
||||
try {
|
||||
if (!highlighter.getLoadedLanguages().includes(mappedLanguage as BundledLanguage)) {
|
||||
if (mappedLanguage in bundledLanguages || mappedLanguage === 'text') {
|
||||
await highlighter.loadLanguage(mappedLanguage as BundledLanguage)
|
||||
} else {
|
||||
try {
|
||||
if (!highlighter.getLoadedLanguages().includes(mappedLanguage as BundledLanguage)) {
|
||||
if (mappedLanguage in bundledLanguages || mappedLanguage === 'text') {
|
||||
await highlighter.loadLanguage(mappedLanguage as BundledLanguage)
|
||||
} else {
|
||||
return `<pre style="padding: 10px"><code>${escapedCode}</code></pre>`
|
||||
}
|
||||
}
|
||||
|
||||
return highlighter.codeToHtml(code, {
|
||||
lang: mappedLanguage,
|
||||
theme: highlighterTheme
|
||||
})
|
||||
} catch (error) {
|
||||
console.warn(`Error highlighting code for language '${mappedLanguage}':`, error)
|
||||
return `<pre style="padding: 10px"><code>${escapedCode}</code></pre>`
|
||||
}
|
||||
}
|
||||
|
||||
return highlighter.codeToHtml(code, {
|
||||
lang: mappedLanguage,
|
||||
theme: highlighterTheme
|
||||
})
|
||||
} catch (error) {
|
||||
console.warn(`Error highlighting code for language '${mappedLanguage}':`, error)
|
||||
return `<pre style="padding: 10px"><code>${escapedCode}</code></pre>`
|
||||
}
|
||||
}
|
||||
},
|
||||
[highlighter, highlighterTheme]
|
||||
)
|
||||
|
||||
return <SyntaxHighlighterContext.Provider value={{ codeToHtml }}>{children}</SyntaxHighlighterContext.Provider>
|
||||
}
|
||||
|
||||
export const useSyntaxHighlighter = () => {
|
||||
const context = useContext(SyntaxHighlighterContext)
|
||||
const context = use(SyntaxHighlighterContext)
|
||||
if (!context) {
|
||||
throw new Error('useSyntaxHighlighter must be used within a SyntaxHighlighterProvider')
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { isMac } from '@renderer/config/constant'
|
||||
import { useSettings } from '@renderer/hooks/useSettings'
|
||||
import { ThemeMode } from '@renderer/types'
|
||||
import React, { createContext, PropsWithChildren, useContext, useEffect, useState } from 'react'
|
||||
import React, { createContext, PropsWithChildren, use, useEffect, useState } from 'react'
|
||||
|
||||
interface ThemeContextType {
|
||||
theme: ThemeMode
|
||||
@@ -64,4 +64,4 @@ export const ThemeProvider: React.FC<ThemeProviderProps> = ({ children, defaultT
|
||||
)
|
||||
}
|
||||
|
||||
export const useTheme = () => useContext(ThemeContext)
|
||||
export const useTheme = () => use(ThemeContext)
|
||||
|
||||
@@ -1,17 +1,19 @@
|
||||
import { EVENT_NAMES, EventEmitter } from '@renderer/services/EventService'
|
||||
import { estimateMessageUsage } from '@renderer/services/TokenService'
|
||||
import store, { useAppDispatch, useAppSelector } from '@renderer/store'
|
||||
import {
|
||||
clearStreamMessage,
|
||||
clearTopicMessages,
|
||||
commitStreamMessage,
|
||||
deleteMessageAction,
|
||||
resendMessage,
|
||||
selectDisplayCount,
|
||||
selectTopicLoading,
|
||||
selectTopicMessages,
|
||||
setStreamMessage,
|
||||
setTopicLoading,
|
||||
updateMessage,
|
||||
updateMessages
|
||||
updateMessages,
|
||||
updateMessageThunk
|
||||
} from '@renderer/store/messages'
|
||||
import type { Assistant, Message, Topic } from '@renderer/types'
|
||||
import { abortCompletion } from '@renderer/utils/abortController'
|
||||
@@ -26,17 +28,15 @@ import { TopicManager } from './useTopic'
|
||||
*/
|
||||
export function useMessageOperations(topic: Topic) {
|
||||
const dispatch = useAppDispatch()
|
||||
const messages = useAppSelector((state) => selectTopicMessages(state, topic.id))
|
||||
|
||||
/**
|
||||
* 删除单个消息
|
||||
*/
|
||||
const deleteMessage = useCallback(
|
||||
async (message: Message) => {
|
||||
const newMessages = messages.filter((m) => m.id !== message.id)
|
||||
await dispatch(updateMessages(topic, newMessages))
|
||||
async (id: string) => {
|
||||
await dispatch(deleteMessageAction(topic, id))
|
||||
},
|
||||
[dispatch, topic, messages]
|
||||
[dispatch, topic]
|
||||
)
|
||||
|
||||
/**
|
||||
@@ -44,10 +44,9 @@ export function useMessageOperations(topic: Topic) {
|
||||
*/
|
||||
const deleteGroupMessages = useCallback(
|
||||
async (askId: string) => {
|
||||
const newMessages = messages.filter((m) => m.askId !== askId)
|
||||
await dispatch(updateMessages(topic, newMessages))
|
||||
await dispatch(deleteMessageAction(topic, askId, 'askId'))
|
||||
},
|
||||
[dispatch, topic, messages]
|
||||
[dispatch, topic]
|
||||
)
|
||||
|
||||
/**
|
||||
@@ -55,13 +54,17 @@ export function useMessageOperations(topic: Topic) {
|
||||
*/
|
||||
const editMessage = useCallback(
|
||||
async (messageId: string, updates: Partial<Message>) => {
|
||||
await dispatch(
|
||||
updateMessage({
|
||||
topicId: topic.id,
|
||||
messageId,
|
||||
updates
|
||||
})
|
||||
)
|
||||
// 如果更新包含内容变更,重新计算 token
|
||||
if ('content' in updates) {
|
||||
const messages = store.getState().messages.messagesByTopic[topic.id]
|
||||
const message = messages?.find((m) => m.id === messageId)
|
||||
if (message) {
|
||||
const updatedMessage = { ...message, ...updates }
|
||||
const usage = await estimateMessageUsage(updatedMessage)
|
||||
updates.usage = usage
|
||||
}
|
||||
}
|
||||
await dispatch(updateMessageThunk(topic.id, messageId, updates))
|
||||
},
|
||||
[dispatch, topic.id]
|
||||
)
|
||||
@@ -148,7 +151,6 @@ export function useMessageOperations(topic: Topic) {
|
||||
EventEmitter.emit(EVENT_NAMES.NEW_CONTEXT)
|
||||
}, [])
|
||||
|
||||
const loading = useAppSelector((state) => selectTopicLoading(state, topic.id))
|
||||
const displayCount = useAppSelector(selectDisplayCount)
|
||||
// /**
|
||||
// * 获取当前消息列表
|
||||
@@ -200,8 +202,6 @@ export function useMessageOperations(topic: Topic) {
|
||||
)
|
||||
|
||||
return {
|
||||
messages,
|
||||
loading,
|
||||
displayCount,
|
||||
updateMessages: updateMessagesAction,
|
||||
deleteMessage,
|
||||
@@ -219,3 +219,13 @@ export function useMessageOperations(topic: Topic) {
|
||||
resumeMessage
|
||||
}
|
||||
}
|
||||
|
||||
export const useTopicMessages = (topic: Topic) => {
|
||||
const messages = useAppSelector((state) => selectTopicMessages(state, topic.id))
|
||||
return messages
|
||||
}
|
||||
|
||||
export const useTopicLoading = (topic: Topic) => {
|
||||
const loading = useAppSelector((state) => selectTopicLoading(state, topic.id))
|
||||
return loading
|
||||
}
|
||||
|
||||
@@ -32,7 +32,9 @@
|
||||
"title": "Agents"
|
||||
},
|
||||
"assistants": {
|
||||
"title": "Assistants",
|
||||
"abbr": "Assistant",
|
||||
"settings.title": "Assistant Settings",
|
||||
"clear.content": "Clearing the topic will delete all topics and files in the assistant. Are you sure you want to continue?",
|
||||
"clear.title": "Clear topics",
|
||||
"copy.title": "Copy Assistant",
|
||||
@@ -53,7 +55,7 @@
|
||||
"settings.reasoning_effort.medium": "medium",
|
||||
"settings.reasoning_effort.off": "off",
|
||||
"settings.reasoning_effort.tip": "Only supports OpenAI o-series and Anthropic reasoning models",
|
||||
"title": "Assistants"
|
||||
"settings.more": "Assistant Settings"
|
||||
},
|
||||
"auth": {
|
||||
"error": "API key automatically obtained failed, please get it manually",
|
||||
@@ -1123,7 +1125,7 @@
|
||||
"docs_more_details": "for more details",
|
||||
"get_api_key": "Get API Key",
|
||||
"is_not_support_array_content": "Enable compatible mode",
|
||||
"no_models": "Please add models first before checking the API connection",
|
||||
"no_models_for_check": "No models available for checking (e.g. chat models)",
|
||||
"not_checked": "Not Checked",
|
||||
"remove_duplicate_keys": "Remove Duplicate Keys",
|
||||
"remove_invalid_keys": "Remove Invalid Keys",
|
||||
|
||||
@@ -32,7 +32,9 @@
|
||||
"title": "エージェント"
|
||||
},
|
||||
"assistants": {
|
||||
"title": "アシスタント",
|
||||
"abbr": "アシスタント",
|
||||
"settings.title": "アシスタント設定",
|
||||
"clear.content": "トピックをクリアすると、アシスタント内のすべてのトピックとファイルが削除されます。続行しますか?",
|
||||
"clear.title": "トピックをクリア",
|
||||
"copy.title": "アシスタントをコピー",
|
||||
@@ -53,7 +55,7 @@
|
||||
"settings.reasoning_effort.medium": "中程度",
|
||||
"settings.reasoning_effort.off": "オフ",
|
||||
"settings.reasoning_effort.tip": "OpenAIのoシリーズとAnthropicの推論モデルのみサポートしています",
|
||||
"title": "アシスタント"
|
||||
"settings.more": "アシスタント設定"
|
||||
},
|
||||
"auth": {
|
||||
"error": "APIキーの自動取得に失敗しました。手動で取得してください",
|
||||
@@ -1122,7 +1124,7 @@
|
||||
"docs_more_details": "詳細を確認",
|
||||
"get_api_key": "APIキーを取得",
|
||||
"is_not_support_array_content": "互換モードを有効にする",
|
||||
"no_models": "API接続をチェックする前に、モデルを追加してください",
|
||||
"no_models_for_check": "チェックするモデルがありません(例:会話モデル)",
|
||||
"not_checked": "未チェック",
|
||||
"remove_duplicate_keys": "重複キーを削除",
|
||||
"remove_invalid_keys": "無効なキーを削除",
|
||||
|
||||
@@ -32,7 +32,9 @@
|
||||
"title": "Агенты"
|
||||
},
|
||||
"assistants": {
|
||||
"title": "Ассистенты",
|
||||
"abbr": "Ассистент",
|
||||
"settings.title": "Настройки ассистента",
|
||||
"clear.content": "Очистка топика удалит все топики и файлы в ассистенте. Вы уверены, что хотите продолжить?",
|
||||
"clear.title": "Очистить топики",
|
||||
"copy.title": "Копировать ассистента",
|
||||
@@ -53,7 +55,7 @@
|
||||
"settings.reasoning_effort.medium": "Средняя",
|
||||
"settings.reasoning_effort.off": "Выключено",
|
||||
"settings.reasoning_effort.tip": "Поддерживается только моделями с рассуждением OpenAI o-series и Anthropic",
|
||||
"title": "Ассистенты"
|
||||
"settings.more": "Настройки ассистента"
|
||||
},
|
||||
"auth": {
|
||||
"error": "Автоматический получение ключа API не удалось, пожалуйста, получите ключ вручную",
|
||||
@@ -1122,7 +1124,7 @@
|
||||
"docs_more_details": "для получения дополнительной информации",
|
||||
"get_api_key": "Получить ключ API",
|
||||
"is_not_support_array_content": "Включить совместимый режим",
|
||||
"no_models": "Пожалуйста, добавьте модели перед проверкой соединения с API",
|
||||
"no_models_for_check": "Нет моделей для проверки (например, диалоговые модели)",
|
||||
"not_checked": "Не проверено",
|
||||
"remove_duplicate_keys": "Удалить дубликаты ключей",
|
||||
"remove_invalid_keys": "Удалить недействительные ключи",
|
||||
|
||||
@@ -32,7 +32,9 @@
|
||||
"title": "智能体"
|
||||
},
|
||||
"assistants": {
|
||||
"title": "助手",
|
||||
"abbr": "助手",
|
||||
"settings.title": "助手设置",
|
||||
"clear.content": "清空话题会删除助手下所有话题和文件,确定要继续吗?",
|
||||
"clear.title": "清空话题",
|
||||
"copy.title": "复制助手",
|
||||
@@ -53,7 +55,7 @@
|
||||
"settings.reasoning_effort.medium": "中",
|
||||
"settings.reasoning_effort.off": "关",
|
||||
"settings.reasoning_effort.tip": "仅支持 OpenAI o-series 和 Anthropic 推理模型",
|
||||
"title": "助手"
|
||||
"settings.more": "助手设置"
|
||||
},
|
||||
"auth": {
|
||||
"error": "自动获取密钥失败,请手动获取",
|
||||
@@ -1126,7 +1128,7 @@
|
||||
"docs_more_details": "获取更多详情",
|
||||
"get_api_key": "点击这里获取密钥",
|
||||
"is_not_support_array_content": "开启兼容模式",
|
||||
"no_models": "请先添加模型再检查 API 连接",
|
||||
"no_models_for_check": "没有可以被检查的模型(例如对话模型)",
|
||||
"not_checked": "未检查",
|
||||
"remove_duplicate_keys": "移除重复密钥",
|
||||
"remove_invalid_keys": "删除无效密钥",
|
||||
|
||||
@@ -32,7 +32,9 @@
|
||||
"title": "智慧代理人"
|
||||
},
|
||||
"assistants": {
|
||||
"title": "助手",
|
||||
"abbr": "助手",
|
||||
"settings.title": "助手設定",
|
||||
"clear.content": "清空話題會刪除助手下所有主題和檔案,確定要繼續嗎?",
|
||||
"clear.title": "清空話題",
|
||||
"copy.title": "複製助手",
|
||||
@@ -52,8 +54,8 @@
|
||||
"settings.reasoning_effort.low": "短",
|
||||
"settings.reasoning_effort.medium": "中",
|
||||
"settings.reasoning_effort.off": "關",
|
||||
"settings.reasoning_effort.tip": "僅支援 OpenAI o 系列和 Anthropic 推理模型",
|
||||
"title": "助手"
|
||||
"settings.reasoning_effort.tip": "僅支援 OpenAI o-series 和 Anthropic 推理模型",
|
||||
"settings.more": "助手設定"
|
||||
},
|
||||
"auth": {
|
||||
"error": "自動取得金鑰失敗,請手動取得",
|
||||
@@ -1122,7 +1124,7 @@
|
||||
"docs_more_details": "檢視更多細節",
|
||||
"get_api_key": "點選這裡取得金鑰",
|
||||
"is_not_support_array_content": "開啟相容模式",
|
||||
"no_models": "請先新增模型再檢查 API 連接",
|
||||
"no_models_for_check": "沒有可以被檢查的模型(例如對話模型)",
|
||||
"not_checked": "未檢查",
|
||||
"remove_duplicate_keys": "移除重複金鑰",
|
||||
"remove_invalid_keys": "刪除無效金鑰",
|
||||
|
||||
@@ -1,13 +1,16 @@
|
||||
import './assets/styles/index.scss'
|
||||
import '@ant-design/v5-patch-for-react-19'
|
||||
|
||||
import ReactDOM from 'react-dom/client'
|
||||
import { createRoot } from 'react-dom/client'
|
||||
|
||||
import App from './App'
|
||||
import MiniApp from './windows/mini/App'
|
||||
|
||||
if (location.hash === '#/mini') {
|
||||
document.getElementById('spinner')?.remove()
|
||||
ReactDOM.createRoot(document.getElementById('root') as HTMLElement).render(<MiniApp />)
|
||||
const root = createRoot(document.getElementById('root') as HTMLElement)
|
||||
root.render(<MiniApp />)
|
||||
} else {
|
||||
ReactDOM.createRoot(document.getElementById('root') as HTMLElement).render(<App />)
|
||||
const root = createRoot(document.getElementById('root') as HTMLElement)
|
||||
root.render(<App />)
|
||||
}
|
||||
|
||||
@@ -1,14 +1,20 @@
|
||||
import { EllipsisOutlined } from '@ant-design/icons'
|
||||
import { Agent } from '@renderer/types'
|
||||
import type { Agent } from '@renderer/types'
|
||||
import { getLeadingEmoji } from '@renderer/utils'
|
||||
import { Dropdown } from 'antd'
|
||||
import { FC, memo } from 'react'
|
||||
import { type FC, memo } from 'react'
|
||||
import styled from 'styled-components'
|
||||
|
||||
interface Props {
|
||||
agent: Agent
|
||||
onClick: () => void
|
||||
contextMenu?: { label: string; onClick: () => void }[]
|
||||
contextMenu?: {
|
||||
key: string
|
||||
label: string
|
||||
icon?: React.ReactNode
|
||||
danger?: boolean
|
||||
onClick: () => void
|
||||
}[]
|
||||
menuItems?: {
|
||||
key: string
|
||||
label: string
|
||||
@@ -58,9 +64,14 @@ const AgentCard: FC<Props> = ({ agent, onClick, contextMenu, menuItems }) => {
|
||||
<Dropdown
|
||||
menu={{
|
||||
items: contextMenu.map((item) => ({
|
||||
key: item.label,
|
||||
label: item.label,
|
||||
onClick: () => item.onClick()
|
||||
...item,
|
||||
onClick: (e) => {
|
||||
e.domEvent.stopPropagation()
|
||||
e.domEvent.preventDefault()
|
||||
setTimeout(() => {
|
||||
item.onClick()
|
||||
}, 0)
|
||||
}
|
||||
}))
|
||||
}}
|
||||
trigger={['contextMenu']}>
|
||||
|
||||
@@ -2,7 +2,7 @@ import { DeleteOutlined, EditOutlined, PlusOutlined, SortAscendingOutlined } fro
|
||||
import { useAgents } from '@renderer/hooks/useAgents'
|
||||
import AssistantSettingsPopup from '@renderer/pages/settings/AssistantSettings'
|
||||
import { createAssistantFromAgent } from '@renderer/services/AssistantService'
|
||||
import { Agent } from '@renderer/types'
|
||||
import type { Agent } from '@renderer/types'
|
||||
import { Col, Row } from 'antd'
|
||||
import { useCallback, useMemo } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
@@ -45,7 +45,7 @@ const MyAgents: React.FC<Props> = ({ onClick, search }) => {
|
||||
return (
|
||||
<Row gutter={[20, 20]}>
|
||||
{filteredAgents.map((agent) => {
|
||||
const dropdownMenuItems = [
|
||||
const menuItems = [
|
||||
{
|
||||
key: 'edit',
|
||||
label: t('agents.edit.title'),
|
||||
@@ -73,29 +73,9 @@ const MyAgents: React.FC<Props> = ({ onClick, search }) => {
|
||||
}
|
||||
]
|
||||
|
||||
const contextMenuItems = [
|
||||
{
|
||||
label: t('agents.edit.title'),
|
||||
onClick: () => AssistantSettingsPopup.show({ assistant: agent })
|
||||
},
|
||||
{
|
||||
label: t('agents.add.button'),
|
||||
onClick: () => createAssistantFromAgent(agent)
|
||||
},
|
||||
{
|
||||
label: t('common.delete'),
|
||||
onClick: () => handleDelete(agent)
|
||||
}
|
||||
]
|
||||
|
||||
return (
|
||||
<Col span={6} key={agent.id}>
|
||||
<AgentCard
|
||||
agent={agent}
|
||||
onClick={() => onClick?.(agent)}
|
||||
contextMenu={contextMenuItems}
|
||||
menuItems={dropdownMenuItems}
|
||||
/>
|
||||
<AgentCard agent={agent} onClick={() => onClick?.(agent)} contextMenu={menuItems} menuItems={menuItems} />
|
||||
</Col>
|
||||
)
|
||||
})}
|
||||
|
||||
@@ -13,7 +13,7 @@ import TranslateButton from '@renderer/components/TranslateButton'
|
||||
import { isFunctionCallingModel, isGenerateImageModel, isVisionModel, isWebSearchModel } from '@renderer/config/models'
|
||||
import db from '@renderer/databases'
|
||||
import { useAssistant } from '@renderer/hooks/useAssistant'
|
||||
import { useMessageOperations } from '@renderer/hooks/useMessageOperations'
|
||||
import { useMessageOperations, useTopicLoading } from '@renderer/hooks/useMessageOperations'
|
||||
import { modelGenerating, useRuntime } from '@renderer/hooks/useRuntime'
|
||||
import { useMessageStyle, useSettings } from '@renderer/hooks/useSettings'
|
||||
import { useShortcut, useShortcutDisplay } from '@renderer/hooks/useShortcuts'
|
||||
@@ -83,10 +83,11 @@ const Inputbar: FC<Props> = ({ assistant: _assistant, setActiveTopic, topic }) =
|
||||
const containerRef = useRef(null)
|
||||
const { searching } = useRuntime()
|
||||
const { isBubbleStyle } = useMessageStyle()
|
||||
const { loading, pauseMessages } = useMessageOperations(topic)
|
||||
const { pauseMessages } = useMessageOperations(topic)
|
||||
const loading = useTopicLoading(topic)
|
||||
const dispatch = useAppDispatch()
|
||||
const [spaceClickCount, setSpaceClickCount] = useState(0)
|
||||
const spaceClickTimer = useRef<NodeJS.Timeout>()
|
||||
const spaceClickTimer = useRef<NodeJS.Timeout>(null)
|
||||
const [isTranslating, setIsTranslating] = useState(false)
|
||||
const [selectedKnowledgeBases, setSelectedKnowledgeBases] = useState<KnowledgeBase[]>([])
|
||||
const [mentionModels, setMentionModels] = useState<Model[]>([])
|
||||
@@ -96,7 +97,7 @@ const Inputbar: FC<Props> = ({ assistant: _assistant, setActiveTopic, topic }) =
|
||||
const [textareaHeight, setTextareaHeight] = useState<number>()
|
||||
const startDragY = useRef<number>(0)
|
||||
const startHeight = useRef<number>(0)
|
||||
const currentMessageId = useRef<string>()
|
||||
const currentMessageId = useRef<string>('')
|
||||
const isVision = useMemo(() => isVisionModel(model), [model])
|
||||
const supportExts = useMemo(() => [...textExts, ...documentExts, ...(isVision ? imageExts : [])], [isVision])
|
||||
const navigate = useNavigate()
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { PushpinOutlined } from '@ant-design/icons'
|
||||
import ModelTags from '@renderer/components/ModelTags'
|
||||
import { getModelLogo, isEmbeddingModel } from '@renderer/config/models'
|
||||
import { getModelLogo, isEmbeddingModel, isRerankModel } from '@renderer/config/models'
|
||||
import db from '@renderer/databases'
|
||||
import { useProviders } from '@renderer/hooks/useProvider'
|
||||
import { EVENT_NAMES, EventEmitter } from '@renderer/services/EventService'
|
||||
@@ -67,6 +67,7 @@ const MentionModelsButton: FC<Props> = ({ mentionModels, onMentionModel: onSelec
|
||||
.map((p) => {
|
||||
const filteredModels = sortBy(p.models, ['group', 'name'])
|
||||
.filter((m) => !isEmbeddingModel(m))
|
||||
.filter((m) => !isRerankModel(m))
|
||||
// Filter out pinned models from regular groups
|
||||
.filter((m) => !pinnedModels.includes(getModelUniqId(m)))
|
||||
// Filter by search text
|
||||
|
||||
@@ -26,7 +26,7 @@ const CodeBlock: React.FC<CodeBlockProps> = ({ children, className }) => {
|
||||
const match = /language-(\w+)/.exec(className || '') || children?.includes('\n')
|
||||
const { codeShowLineNumbers, fontSize, codeCollapsible, codeWrappable } = useSettings()
|
||||
const language = match?.[1] ?? 'text'
|
||||
const [html, setHtml] = useState<string>('')
|
||||
// const [html, setHtml] = useState<string>('')
|
||||
const { codeToHtml } = useSyntaxHighlighter()
|
||||
const [isExpanded, setIsExpanded] = useState(!codeCollapsible)
|
||||
const [isUnwrapped, setIsUnwrapped] = useState(!codeWrappable)
|
||||
@@ -40,17 +40,14 @@ const CodeBlock: React.FC<CodeBlockProps> = ({ children, className }) => {
|
||||
useEffect(() => {
|
||||
const loadHighlightedCode = async () => {
|
||||
const highlightedHtml = await codeToHtml(children, language)
|
||||
setHtml(highlightedHtml)
|
||||
if (codeContentRef.current) {
|
||||
codeContentRef.current.innerHTML = highlightedHtml
|
||||
setShouldShowExpandButton(codeContentRef.current.scrollHeight > 350)
|
||||
}
|
||||
}
|
||||
loadHighlightedCode()
|
||||
}, [children, language, codeToHtml])
|
||||
|
||||
useEffect(() => {
|
||||
if (codeContentRef.current) {
|
||||
setShouldShowExpandButton(codeContentRef.current.scrollHeight > 350)
|
||||
}
|
||||
}, [html])
|
||||
|
||||
useEffect(() => {
|
||||
if (!codeCollapsible) {
|
||||
setIsExpanded(true)
|
||||
@@ -112,7 +109,7 @@ const CodeBlock: React.FC<CodeBlockProps> = ({ children, className }) => {
|
||||
isShowLineNumbers={codeShowLineNumbers}
|
||||
isUnwrapped={isUnwrapped}
|
||||
isCodeWrappable={codeWrappable}
|
||||
dangerouslySetInnerHTML={{ __html: html }}
|
||||
// dangerouslySetInnerHTML={{ __html: html }}
|
||||
style={{
|
||||
border: '0.5px solid var(--color-code-background)',
|
||||
borderTopLeftRadius: 0,
|
||||
|
||||
@@ -50,7 +50,7 @@ const CustomNode: FC<{ data: any }> = ({ data }) => {
|
||||
let title = ''
|
||||
let backgroundColor = 'var(--bg-color)'
|
||||
let gradientColor = 'rgba(0, 0, 0, 0.03)'
|
||||
let avatar: JSX.Element | null = null
|
||||
let avatar: React.ReactNode | null = null
|
||||
|
||||
// 根据消息类型设置不同的样式和图标
|
||||
if (nodeType === 'user') {
|
||||
|
||||
@@ -163,7 +163,7 @@ const MessageItem: FC<Props> = ({
|
||||
isLastMessage={isLastMessage}
|
||||
isAssistantMessage={isAssistantMessage}
|
||||
isGrouped={isGrouped}
|
||||
messageContainerRef={messageContainerRef}
|
||||
messageContainerRef={messageContainerRef as React.RefObject<HTMLDivElement>}
|
||||
setModel={setModel}
|
||||
/>
|
||||
</MessageFooter>
|
||||
|
||||
@@ -6,11 +6,11 @@ import { useSettings } from '@renderer/hooks/useSettings'
|
||||
import { getMessageModelId } from '@renderer/services/MessagesService'
|
||||
import { getModelName } from '@renderer/services/ModelService'
|
||||
import { useAppDispatch } from '@renderer/store'
|
||||
import { updateMessage } from '@renderer/store/messages'
|
||||
import { Message } from '@renderer/types'
|
||||
import { updateMessageThunk } from '@renderer/store/messages'
|
||||
import type { Message } from '@renderer/types'
|
||||
import { isEmoji, removeLeadingEmoji } from '@renderer/utils'
|
||||
import { Avatar } from 'antd'
|
||||
import { FC, useCallback, useEffect, useRef, useState } from 'react'
|
||||
import { type FC, useCallback, useEffect, useRef, useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import styled from 'styled-components'
|
||||
interface MessageLineProps {
|
||||
@@ -100,15 +100,9 @@ const MessageAnchorLine: FC<MessageLineProps> = ({ messages }) => {
|
||||
(message: Message) => {
|
||||
const groupMessages = messages.filter((m) => m.askId === message.askId)
|
||||
if (groupMessages.length > 1) {
|
||||
groupMessages.forEach((m) => {
|
||||
dispatch(
|
||||
updateMessage({
|
||||
topicId: m.topicId,
|
||||
messageId: m.id,
|
||||
updates: { foldSelected: m.id === message.id }
|
||||
})
|
||||
)
|
||||
})
|
||||
for (const m of groupMessages) {
|
||||
dispatch(updateMessageThunk(m.topicId, m.id, { foldSelected: m.id === message.id }))
|
||||
}
|
||||
|
||||
setTimeout(() => {
|
||||
const messageElement = document.getElementById(`message-${message.id}`)
|
||||
|
||||
@@ -145,7 +145,7 @@ const MessageGroup = ({ messages, topic, hidePresetMessages }: Props) => {
|
||||
key={message.id}
|
||||
className={classNames({
|
||||
'group-message-wrapper': message.role === 'assistant' && isHorizontal && isGrouped,
|
||||
[multiModelMessageStyle]: true,
|
||||
[multiModelMessageStyle]: isGrouped,
|
||||
selected: 'foldSelected' in message ? message.foldSelected : index === 0
|
||||
})}>
|
||||
<MessageStream {...messageProps} />
|
||||
|
||||
@@ -1,9 +1,12 @@
|
||||
import { ArrowsAltOutlined, ShrinkOutlined } from '@ant-design/icons'
|
||||
import ModelAvatar from '@renderer/components/Avatar/ModelAvatar'
|
||||
import Scrollbar from '@renderer/components/Scrollbar'
|
||||
import { useSettings } from '@renderer/hooks/useSettings'
|
||||
import { useAppDispatch } from '@renderer/store'
|
||||
import { setFoldDisplayMode } from '@renderer/store/settings'
|
||||
import { Message, Model } from '@renderer/types'
|
||||
import { Avatar, Segmented as AntdSegmented, Tooltip } from 'antd'
|
||||
import { FC, useState } from 'react'
|
||||
import { FC } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import styled from 'styled-components'
|
||||
|
||||
@@ -15,26 +18,27 @@ interface MessageGroupModelListProps {
|
||||
type DisplayMode = 'compact' | 'expanded'
|
||||
|
||||
const MessageGroupModelList: FC<MessageGroupModelListProps> = ({ messages, setSelectedMessage }) => {
|
||||
const dispatch = useAppDispatch()
|
||||
const { t } = useTranslation()
|
||||
const [displayMode, setDisplayMode] = useState<DisplayMode>('expanded')
|
||||
const isCompact = displayMode === 'compact'
|
||||
const { foldDisplayMode } = useSettings()
|
||||
const isCompact = foldDisplayMode === 'compact'
|
||||
|
||||
return (
|
||||
<ModelsWrapper>
|
||||
<DisplayModeToggle displayMode={displayMode} onClick={() => setDisplayMode(isCompact ? 'expanded' : 'compact')}>
|
||||
<DisplayModeToggle displayMode={foldDisplayMode} onClick={() => dispatch(setFoldDisplayMode(isCompact ? 'expanded' : 'compact'))}>
|
||||
<Tooltip
|
||||
title={
|
||||
displayMode === 'compact'
|
||||
foldDisplayMode === 'compact'
|
||||
? t(`message.message.multi_model_style.fold.expand`)
|
||||
: t('message.message.multi_model_style.fold.compress')
|
||||
}
|
||||
placement="top">
|
||||
{displayMode === 'compact' ? <ArrowsAltOutlined /> : <ShrinkOutlined />}
|
||||
{foldDisplayMode === 'compact' ? <ArrowsAltOutlined /> : <ShrinkOutlined />}
|
||||
</Tooltip>
|
||||
</DisplayModeToggle>
|
||||
|
||||
<ModelsContainer $displayMode={displayMode}>
|
||||
{displayMode === 'compact' ? (
|
||||
<ModelsContainer $displayMode={foldDisplayMode}>
|
||||
{foldDisplayMode === 'compact' ? (
|
||||
/* Compact style display */
|
||||
<Avatar.Group className="avatar-group">
|
||||
{messages.map((message, index) => (
|
||||
|
||||
@@ -17,12 +17,12 @@ import SelectModelPopup from '@renderer/components/Popups/SelectModelPopup'
|
||||
import TextEditPopup from '@renderer/components/Popups/TextEditPopup'
|
||||
import { isReasoningModel } from '@renderer/config/models'
|
||||
import { TranslateLanguageOptions } from '@renderer/config/translate'
|
||||
import { useMessageOperations } from '@renderer/hooks/useMessageOperations'
|
||||
import { useMessageOperations, useTopicLoading } from '@renderer/hooks/useMessageOperations'
|
||||
import { EVENT_NAMES, EventEmitter } from '@renderer/services/EventService'
|
||||
import { getMessageTitle, resetAssistantMessage } from '@renderer/services/MessagesService'
|
||||
import { translateText } from '@renderer/services/TranslateService'
|
||||
import { Message, Model } from '@renderer/types'
|
||||
import { Assistant, Topic } from '@renderer/types'
|
||||
import type { Message, Model } from '@renderer/types'
|
||||
import type { Assistant, Topic } from '@renderer/types'
|
||||
import { captureScrollableDivAsBlob, captureScrollableDivAsDataURL, removeTrailingDoubleSpaces } from '@renderer/utils'
|
||||
import {
|
||||
exportMarkdownToJoplin,
|
||||
@@ -62,15 +62,9 @@ const MessageMenubar: FC<Props> = (props) => {
|
||||
const [showRegenerateTooltip, setShowRegenerateTooltip] = useState(false)
|
||||
const [showDeleteTooltip, setShowDeleteTooltip] = useState(false)
|
||||
const assistantModel = assistant?.model
|
||||
const {
|
||||
loading,
|
||||
editMessage,
|
||||
setStreamMessage,
|
||||
deleteMessage,
|
||||
resendMessage,
|
||||
commitStreamMessage,
|
||||
clearStreamMessage
|
||||
} = useMessageOperations(topic)
|
||||
const { editMessage, setStreamMessage, deleteMessage, resendMessage, commitStreamMessage, clearStreamMessage } =
|
||||
useMessageOperations(topic)
|
||||
const loading = useTopicLoading(topic)
|
||||
|
||||
const isUserMessage = message.role === 'user'
|
||||
|
||||
@@ -382,7 +376,7 @@ const MessageMenubar: FC<Props> = (props) => {
|
||||
okButtonProps={{ danger: true }}
|
||||
icon={<QuestionCircleOutlined style={{ color: 'red' }} />}
|
||||
onOpenChange={(open) => open && setShowDeleteTooltip(false)}
|
||||
onConfirm={() => deleteMessage(message)}>
|
||||
onConfirm={() => deleteMessage(message.id)}>
|
||||
<ActionButton className="message-action-button" onClick={(e) => e.stopPropagation()}>
|
||||
<Tooltip
|
||||
title={t('common.delete')}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { CheckOutlined, ExpandOutlined, LoadingOutlined } from '@ant-design/icons'
|
||||
import { useSettings } from '@renderer/hooks/useSettings'
|
||||
import { MCPToolResponse, Message } from '@renderer/types'
|
||||
import { Message } from '@renderer/types'
|
||||
import { Collapse, message as antdMessage, Modal, Tooltip } from 'antd'
|
||||
import { isEmpty } from 'lodash'
|
||||
import { FC, useMemo, useState } from 'react'
|
||||
@@ -42,9 +42,9 @@ const MessageTools: FC<Props> = ({ message }) => {
|
||||
|
||||
// Format tool responses for collapse items
|
||||
const getCollapseItems = () => {
|
||||
const items: { key: string; label: JSX.Element; children: React.ReactNode }[] = []
|
||||
const items: { key: string; label: React.ReactNode; children: React.ReactNode }[] = []
|
||||
// Add tool responses
|
||||
toolResponses.forEach((toolResponse: MCPToolResponse) => {
|
||||
for (const toolResponse of toolResponses) {
|
||||
const { id, tool, status, response } = toolResponse
|
||||
const isInvoking = status === 'invoking'
|
||||
const isDone = status === 'done'
|
||||
@@ -105,7 +105,7 @@ const MessageTools: FC<Props> = ({ message }) => {
|
||||
</ToolResponseContainer>
|
||||
)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
return items
|
||||
}
|
||||
@@ -129,7 +129,9 @@ const MessageTools: FC<Props> = ({ message }) => {
|
||||
onCancel={() => setExpandedResponse(null)}
|
||||
footer={null}
|
||||
width="80%"
|
||||
bodyStyle={{ maxHeight: '80vh', overflow: 'auto' }}>
|
||||
styles={{
|
||||
body: { maxHeight: '80vh', overflow: 'auto' }
|
||||
}}>
|
||||
{expandedResponse && (
|
||||
<ExpandedResponseContainer style={{ fontFamily, fontSize }}>
|
||||
<ActionButton
|
||||
|
||||
@@ -2,7 +2,7 @@ import Scrollbar from '@renderer/components/Scrollbar'
|
||||
import { LOAD_MORE_COUNT } from '@renderer/config/constant'
|
||||
import db from '@renderer/databases'
|
||||
import { useAssistant } from '@renderer/hooks/useAssistant'
|
||||
import { useMessageOperations } from '@renderer/hooks/useMessageOperations'
|
||||
import { useMessageOperations, useTopicLoading, useTopicMessages } from '@renderer/hooks/useMessageOperations'
|
||||
import { useSettings } from '@renderer/hooks/useSettings'
|
||||
import { useShortcut } from '@renderer/hooks/useShortcuts'
|
||||
import { autoRenameTopic, getTopic } from '@renderer/hooks/useTopic'
|
||||
@@ -38,6 +38,42 @@ interface MessagesProps {
|
||||
setActiveTopic: (topic: Topic) => void
|
||||
}
|
||||
|
||||
const computeDisplayMessages = (messages: Message[], startIndex: number, displayCount: number) => {
|
||||
const reversedMessages = [...messages].reverse()
|
||||
|
||||
// 如果剩余消息数量小于 displayCount,直接返回所有剩余消息
|
||||
if (reversedMessages.length - startIndex <= displayCount) {
|
||||
return reversedMessages.slice(startIndex)
|
||||
}
|
||||
|
||||
const userIdSet = new Set() // 用户消息 id 集合
|
||||
const assistantIdSet = new Set() // 助手消息 askId 集合
|
||||
const displayMessages: Message[] = []
|
||||
|
||||
// 处理单条消息的函数
|
||||
const processMessage = (message: Message) => {
|
||||
if (!message) return
|
||||
|
||||
const idSet = message.role === 'user' ? userIdSet : assistantIdSet
|
||||
const messageId = message.role === 'user' ? message.id : message.askId
|
||||
|
||||
if (!idSet.has(messageId)) {
|
||||
idSet.add(messageId)
|
||||
displayMessages.push(message)
|
||||
return
|
||||
}
|
||||
// 如果是相同 askId 的助手消息,也要显示
|
||||
displayMessages.push(message)
|
||||
}
|
||||
|
||||
// 遍历消息直到满足显示数量要求
|
||||
for (let i = startIndex; i < reversedMessages.length && userIdSet.size + assistantIdSet.size < displayCount; i++) {
|
||||
processMessage(reversedMessages[i])
|
||||
}
|
||||
|
||||
return displayMessages
|
||||
}
|
||||
|
||||
const Messages: React.FC<MessagesProps> = ({ assistant, topic, setActiveTopic }) => {
|
||||
const { t } = useTranslation()
|
||||
const { showTopics, topicPosition, showAssistants, messageNavigation } = useSettings()
|
||||
@@ -48,9 +84,9 @@ const Messages: React.FC<MessagesProps> = ({ assistant, topic, setActiveTopic })
|
||||
const [hasMore, setHasMore] = useState(false)
|
||||
const [isLoadingMore, setIsLoadingMore] = useState(false)
|
||||
const [isProcessingContext, setIsProcessingContext] = useState(false)
|
||||
const { messages, displayCount, loading, updateMessages, clearTopicMessages, deleteMessage } =
|
||||
useMessageOperations(topic)
|
||||
|
||||
const messages = useTopicMessages(topic)
|
||||
const { displayCount, updateMessages, clearTopicMessages, deleteMessage } = useMessageOperations(topic)
|
||||
const loading = useTopicLoading(topic)
|
||||
const messagesRef = useRef<Message[]>(messages)
|
||||
|
||||
useEffect(() => {
|
||||
@@ -58,9 +94,7 @@ const Messages: React.FC<MessagesProps> = ({ assistant, topic, setActiveTopic })
|
||||
}, [messages])
|
||||
|
||||
useEffect(() => {
|
||||
const reversedMessages = [...messages].reverse()
|
||||
const newDisplayMessages = reversedMessages.slice(0, displayCount)
|
||||
|
||||
const newDisplayMessages = computeDisplayMessages(messages, 0, displayCount)
|
||||
setDisplayMessages(newDisplayMessages)
|
||||
setHasMore(messages.length > displayCount)
|
||||
}, [messages, displayCount])
|
||||
@@ -73,7 +107,15 @@ const Messages: React.FC<MessagesProps> = ({ assistant, topic, setActiveTopic })
|
||||
}, [showAssistants, showTopics, topicPosition])
|
||||
|
||||
const scrollToBottom = useCallback(() => {
|
||||
setTimeout(() => containerRef.current?.scrollTo({ top: containerRef.current.scrollHeight, behavior: 'auto' }), 50)
|
||||
if (containerRef.current) {
|
||||
requestAnimationFrame(() => {
|
||||
if (containerRef.current) {
|
||||
containerRef.current.scrollTo({
|
||||
top: containerRef.current.scrollHeight
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
}, [])
|
||||
|
||||
useEffect(() => {
|
||||
@@ -122,7 +164,7 @@ const Messages: React.FC<MessagesProps> = ({ assistant, topic, setActiveTopic })
|
||||
const lastMessage = last(messages)
|
||||
|
||||
if (lastMessage?.type === 'clear') {
|
||||
await deleteMessage(lastMessage)
|
||||
await deleteMessage(lastMessage.id)
|
||||
scrollToBottom()
|
||||
return
|
||||
}
|
||||
@@ -183,10 +225,9 @@ const Messages: React.FC<MessagesProps> = ({ assistant, topic, setActiveTopic })
|
||||
setIsLoadingMore(true)
|
||||
setTimeout(() => {
|
||||
const currentLength = displayMessages.length
|
||||
const reversedMessages = [...messages].reverse()
|
||||
const moreMessages = reversedMessages.slice(currentLength, currentLength + LOAD_MORE_COUNT)
|
||||
const newMessages = computeDisplayMessages(messages, currentLength, LOAD_MORE_COUNT)
|
||||
|
||||
setDisplayMessages((prev) => [...prev, ...moreMessages])
|
||||
setDisplayMessages((prev) => [...prev, ...newMessages])
|
||||
setHasMore(currentLength + LOAD_MORE_COUNT < messages.length)
|
||||
setIsLoadingMore(false)
|
||||
}, 300)
|
||||
@@ -214,8 +255,8 @@ const Messages: React.FC<MessagesProps> = ({ assistant, topic, setActiveTopic })
|
||||
next={loadMoreMessages}
|
||||
hasMore={hasMore}
|
||||
loader={null}
|
||||
inverse={true}
|
||||
scrollableTarget="messages">
|
||||
scrollableTarget="messages"
|
||||
inverse>
|
||||
<ScrollContainer>
|
||||
<LoaderContainer $loading={isLoadingMore}>
|
||||
<BeatLoader size={8} color="var(--color-text-2)" />
|
||||
@@ -232,9 +273,7 @@ const Messages: React.FC<MessagesProps> = ({ assistant, topic, setActiveTopic })
|
||||
</InfiniteScroll>
|
||||
<Prompt assistant={assistant} key={assistant.prompt} topic={topic} />
|
||||
</NarrowLayout>
|
||||
|
||||
{messageNavigation === 'anchor' && <MessageAnchorLine messages={displayMessages} />}
|
||||
|
||||
{messageNavigation === 'buttons' && <ChatNavigation containerId="messages" />}
|
||||
</Container>
|
||||
)
|
||||
|
||||
@@ -153,7 +153,6 @@ const Container = styled.div`
|
||||
justify-content: space-between;
|
||||
padding: 7px 10px;
|
||||
position: relative;
|
||||
margin: 0 10px;
|
||||
font-family: Ubuntu;
|
||||
border-radius: var(--list-item-border-radius);
|
||||
border: 0.5px solid transparent;
|
||||
|
||||
@@ -78,8 +78,7 @@ const Assistants: FC<AssistantsTabProps> = ({
|
||||
const Container = styled(Scrollbar)`
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
padding-top: 11px;
|
||||
user-select: none;
|
||||
padding: 10px;
|
||||
`
|
||||
|
||||
const AssistantAddItem = styled.div`
|
||||
@@ -88,7 +87,6 @@ const AssistantAddItem = styled.div`
|
||||
justify-content: space-between;
|
||||
padding: 7px 12px;
|
||||
position: relative;
|
||||
margin: 0 10px;
|
||||
padding-right: 35px;
|
||||
font-family: Ubuntu;
|
||||
border-radius: var(--list-item-border-radius);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { CheckOutlined, QuestionCircleOutlined, ReloadOutlined } from '@ant-design/icons'
|
||||
import { CheckOutlined, QuestionCircleOutlined, ReloadOutlined, SettingOutlined } from '@ant-design/icons'
|
||||
import { HStack } from '@renderer/components/Layout'
|
||||
import Scrollbar from '@renderer/components/Scrollbar'
|
||||
import {
|
||||
@@ -13,6 +13,7 @@ import { codeThemes } from '@renderer/context/SyntaxHighlighterProvider'
|
||||
import { useAssistant } from '@renderer/hooks/useAssistant'
|
||||
import { useSettings } from '@renderer/hooks/useSettings'
|
||||
import { SettingDivider, SettingRow, SettingRowTitle, SettingSubtitle } from '@renderer/pages/settings'
|
||||
import AssistantSettingsPopup from '@renderer/pages/settings/AssistantSettings'
|
||||
import { getDefaultModel } from '@renderer/services/AssistantService'
|
||||
import { useAppDispatch } from '@renderer/store'
|
||||
import {
|
||||
@@ -37,7 +38,7 @@ import {
|
||||
} from '@renderer/store/settings'
|
||||
import { Assistant, AssistantSettings, CodeStyleVarious, ThemeMode, TranslateLanguageVarious } from '@renderer/types'
|
||||
import { modalConfirm } from '@renderer/utils'
|
||||
import { Col, InputNumber, Row, Segmented, Select, Slider, Switch, Tooltip } from 'antd'
|
||||
import { Button, Col, InputNumber, Row, Segmented, Select, Slider, Switch, Tooltip } from 'antd'
|
||||
import { FC, useEffect, useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import styled from 'styled-components'
|
||||
@@ -145,11 +146,19 @@ const SettingsTab: FC<Props> = (props) => {
|
||||
return (
|
||||
<Container className="settings-tab">
|
||||
<SettingGroup style={{ marginTop: 10 }}>
|
||||
<SettingSubtitle style={{ marginTop: 0 }}>
|
||||
{t('settings.messages.model.title')}{' '}
|
||||
<Tooltip title={t('chat.settings.reset')}>
|
||||
<ReloadOutlined onClick={onReset} style={{ cursor: 'pointer', fontSize: 12, padding: '0 3px' }} />
|
||||
</Tooltip>
|
||||
<SettingSubtitle style={{ marginTop: 0, display: 'flex', justifyContent: 'space-between' }}>
|
||||
<HStack alignItems="center">
|
||||
{t('assistants.settings.title')}{' '}
|
||||
<Tooltip title={t('chat.settings.reset')}>
|
||||
<ReloadOutlined onClick={onReset} style={{ cursor: 'pointer', fontSize: 12, padding: '0 3px' }} />
|
||||
</Tooltip>
|
||||
</HStack>
|
||||
<Button
|
||||
type="text"
|
||||
size="small"
|
||||
icon={<SettingOutlined />}
|
||||
onClick={() => AssistantSettingsPopup.show({ assistant, tab: 'model' })}
|
||||
/>
|
||||
</SettingSubtitle>
|
||||
<SettingDivider />
|
||||
<Row align="middle">
|
||||
|
||||
@@ -56,7 +56,7 @@ const Topics: FC<Props> = ({ assistant: _assistant, activeTopic, setActiveTopic
|
||||
const borderRadius = showTopicTime ? 12 : 'var(--list-item-border-radius)'
|
||||
|
||||
const [deletingTopicId, setDeletingTopicId] = useState<string | null>(null)
|
||||
const deleteTimerRef = useRef<NodeJS.Timeout>()
|
||||
const deleteTimerRef = useRef<NodeJS.Timeout>(null)
|
||||
|
||||
const pendingTopics = useMemo(() => {
|
||||
return new Set<string>()
|
||||
@@ -410,14 +410,11 @@ const Topics: FC<Props> = ({ assistant: _assistant, activeTopic, setActiveTopic
|
||||
const Container = styled(Scrollbar)`
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
padding-top: 11px;
|
||||
user-select: none;
|
||||
padding: 10px;
|
||||
`
|
||||
|
||||
const TopicListItem = styled.div`
|
||||
padding: 7px 12px;
|
||||
margin-left: 10px;
|
||||
margin-right: 4px;
|
||||
border-radius: var(--list-item-border-radius);
|
||||
font-family: Ubuntu;
|
||||
font-size: 13px;
|
||||
@@ -429,6 +426,7 @@ const TopicListItem = styled.div`
|
||||
cursor: pointer;
|
||||
border: 0.5px solid transparent;
|
||||
position: relative;
|
||||
width: calc(var(--assistants-width) - 20px);
|
||||
.menu {
|
||||
opacity: 0;
|
||||
color: var(--color-text-3);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { ExtractChunkData } from '@llm-tools/embedjs-interfaces'
|
||||
import type { ExtractChunkData } from '@cherrystudio/embedjs-interfaces'
|
||||
import { TopView } from '@renderer/components/TopView'
|
||||
import { DEFAULT_KNOWLEDGE_THRESHOLD } from '@renderer/config/constant'
|
||||
import { getFileFromUrl, getKnowledgeBaseParams } from '@renderer/services/KnowledgeService'
|
||||
|
||||
@@ -23,11 +23,12 @@ import { translateText } from '@renderer/services/TranslateService'
|
||||
import { useAppDispatch } from '@renderer/store'
|
||||
import { DEFAULT_PAINTING } from '@renderer/store/paintings'
|
||||
import { setGenerating } from '@renderer/store/runtime'
|
||||
import { FileType, Painting } from '@renderer/types'
|
||||
import type { FileType, Painting } from '@renderer/types'
|
||||
import { getErrorMessage } from '@renderer/utils'
|
||||
import { Button, Input, InputNumber, Radio, Select, Slider, Switch, Tooltip } from 'antd'
|
||||
import TextArea from 'antd/es/input/TextArea'
|
||||
import { FC, useEffect, useRef, useState } from 'react'
|
||||
import type { FC } from 'react'
|
||||
import { useEffect, useRef, useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import styled from 'styled-components'
|
||||
|
||||
@@ -243,7 +244,7 @@ const PaintingsPage: FC = () => {
|
||||
const { autoTranslateWithSpace } = useSettings()
|
||||
const [spaceClickCount, setSpaceClickCount] = useState(0)
|
||||
const [isTranslating, setIsTranslating] = useState(false)
|
||||
const spaceClickTimer = useRef<NodeJS.Timeout>()
|
||||
const spaceClickTimer = useRef<NodeJS.Timeout>(null)
|
||||
|
||||
const translate = async () => {
|
||||
if (isTranslating) {
|
||||
|
||||
@@ -16,16 +16,19 @@ import AssistantPromptSettings from './AssistantPromptSettings'
|
||||
|
||||
interface AssistantSettingPopupShowParams {
|
||||
assistant: Assistant
|
||||
tab?: AssistantSettingPopupTab
|
||||
}
|
||||
|
||||
type AssistantSettingPopupTab = 'prompt' | 'model' | 'messages' | 'knowledge_base'
|
||||
|
||||
interface Props extends AssistantSettingPopupShowParams {
|
||||
resolve: (assistant: Assistant) => void
|
||||
}
|
||||
|
||||
const AssistantSettingPopupContainer: React.FC<Props> = ({ resolve, ...props }) => {
|
||||
const AssistantSettingPopupContainer: React.FC<Props> = ({ resolve, tab, ...props }) => {
|
||||
const [open, setOpen] = useState(true)
|
||||
const { t } = useTranslation()
|
||||
const [menu, setMenu] = useState('prompt')
|
||||
const [menu, setMenu] = useState<AssistantSettingPopupTab>(tab || 'prompt')
|
||||
|
||||
const _useAssistant = useAssistant(props.assistant.id)
|
||||
const _useAgent = useAgent(props.assistant.id)
|
||||
@@ -94,10 +97,10 @@ const AssistantSettingPopupContainer: React.FC<Props> = ({ resolve, ...props })
|
||||
<LeftMenu>
|
||||
<Menu
|
||||
style={{ width: 220, padding: 5, background: 'transparent' }}
|
||||
defaultSelectedKeys={['prompt']}
|
||||
defaultSelectedKeys={[tab || 'prompt']}
|
||||
mode="vertical"
|
||||
items={items}
|
||||
onSelect={({ key }) => setMenu(key as string)}
|
||||
onSelect={({ key }) => setMenu(key as AssistantSettingPopupTab)}
|
||||
/>
|
||||
</LeftMenu>
|
||||
<Settings>
|
||||
|
||||
@@ -37,7 +37,7 @@ const DataSettings: FC = () => {
|
||||
const [appInfo, setAppInfo] = useState<AppInfo>()
|
||||
const { size, removeAllFiles } = useKnowledgeFiles()
|
||||
const { theme } = useTheme()
|
||||
const [menu, setMenu] = useState<string>('common')
|
||||
const [menu, setMenu] = useState<string>('data')
|
||||
|
||||
//joplin icon needs to be updated into iconfont
|
||||
const JoplinIcon = () => (
|
||||
|
||||
@@ -152,7 +152,12 @@ const PopupContainer: React.FC<Props> = ({ server, create, resolve }) => {
|
||||
width={600}
|
||||
transitionName="ant-move-down"
|
||||
centered
|
||||
bodyStyle={{ maxHeight: '70vh', overflowY: 'auto' }}>
|
||||
styles={{
|
||||
body: {
|
||||
maxHeight: '70vh',
|
||||
overflowY: 'auto'
|
||||
}
|
||||
}}>
|
||||
<Form form={form} layout="vertical">
|
||||
<Form.Item
|
||||
name="name"
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { CheckOutlined, ExportOutlined, HeartOutlined, LoadingOutlined, SettingOutlined } from '@ant-design/icons'
|
||||
import { HStack } from '@renderer/components/Layout'
|
||||
import OAuthButton from '@renderer/components/OAuth/OAuthButton'
|
||||
import { isEmbeddingModel, isRerankModel } from '@renderer/config/models'
|
||||
import { PROVIDER_CONFIG } from '@renderer/config/providers'
|
||||
import { useTheme } from '@renderer/context/ThemeProvider'
|
||||
import { useProvider } from '@renderer/hooks/useProvider'
|
||||
@@ -91,12 +92,14 @@ const ProviderSetting: FC<Props> = ({ provider: _provider }) => {
|
||||
const onUpdateApiVersion = () => updateProvider({ ...provider, apiVersion })
|
||||
|
||||
const onHealthCheck = async () => {
|
||||
if (isEmpty(models)) {
|
||||
const modelsToCheck = models.filter((model) => !isRerankModel(model))
|
||||
|
||||
if (isEmpty(modelsToCheck)) {
|
||||
window.message.error({
|
||||
key: 'no-models',
|
||||
style: { marginTop: '3vh' },
|
||||
duration: 5,
|
||||
content: t('settings.provider.no_models')
|
||||
content: t('settings.provider.no_models_for_check')
|
||||
})
|
||||
return
|
||||
}
|
||||
@@ -124,7 +127,7 @@ const ProviderSetting: FC<Props> = ({ provider: _provider }) => {
|
||||
}
|
||||
|
||||
// Prepare the list of models to be checked
|
||||
const initialStatuses = models.map((model) => ({
|
||||
const initialStatuses = modelsToCheck.map((model) => ({
|
||||
model,
|
||||
checking: true,
|
||||
status: undefined
|
||||
@@ -135,7 +138,7 @@ const ProviderSetting: FC<Props> = ({ provider: _provider }) => {
|
||||
const checkResults = await checkModelsHealth(
|
||||
{
|
||||
provider: { ...provider, apiHost },
|
||||
models,
|
||||
models: modelsToCheck,
|
||||
apiKeys: result.apiKeys,
|
||||
isConcurrent: result.isConcurrent
|
||||
},
|
||||
@@ -180,12 +183,14 @@ const ProviderSetting: FC<Props> = ({ provider: _provider }) => {
|
||||
}
|
||||
|
||||
const onCheckApi = async () => {
|
||||
if (isEmpty(models)) {
|
||||
const modelsToCheck = models.filter((model) => !isEmbeddingModel(model) && !isRerankModel(model))
|
||||
|
||||
if (isEmpty(modelsToCheck)) {
|
||||
window.message.error({
|
||||
key: 'no-models',
|
||||
style: { marginTop: '3vh' },
|
||||
duration: 5,
|
||||
content: t('settings.provider.no_models')
|
||||
content: t('settings.provider.no_models_for_check')
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { TopView } from '@renderer/components/TopView'
|
||||
import { isEmbeddingModel } from '@renderer/config/models'
|
||||
import { isEmbeddingModel, isRerankModel } from '@renderer/config/models'
|
||||
import i18n from '@renderer/i18n'
|
||||
import { Provider } from '@renderer/types'
|
||||
import { Modal, Select } from 'antd'
|
||||
@@ -16,7 +16,7 @@ interface Props extends ShowParams {
|
||||
}
|
||||
|
||||
const PopupContainer: React.FC<Props> = ({ provider, resolve, reject }) => {
|
||||
const models = orderBy(provider.models, 'group').filter((i) => !isEmbeddingModel(i))
|
||||
const models = orderBy(provider.models, 'group').filter((i) => !isEmbeddingModel(i) && !isRerankModel(i))
|
||||
const [open, setOpen] = useState(true)
|
||||
const [model, setModel] = useState(first(models))
|
||||
|
||||
|
||||
@@ -280,7 +280,11 @@ const ShortcutSettings: FC = () => {
|
||||
<HStack alignItems="center" style={{ position: 'relative' }}>
|
||||
{isEditing ? (
|
||||
<ShortcutInput
|
||||
ref={(el) => el && (inputRefs.current[record.key] = el)}
|
||||
ref={(el) => {
|
||||
if (el) {
|
||||
inputRefs.current[record.key] = el
|
||||
}
|
||||
}}
|
||||
value={formatShortcut(shortcut)}
|
||||
placeholder={t('settings.shortcuts.press_shortcut')}
|
||||
onKeyDown={(e) => handleKeyDown(e, record)}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { ExtractChunkData } from '@llm-tools/embedjs-interfaces'
|
||||
import type { ExtractChunkData } from '@cherrystudio/embedjs-interfaces'
|
||||
import { DEFAULT_KNOWLEDGE_DOCUMENT_COUNT, DEFAULT_KNOWLEDGE_THRESHOLD } from '@renderer/config/constant'
|
||||
import { getEmbeddingMaxContext } from '@renderer/config/embedings'
|
||||
import AiProvider from '@renderer/providers/AiProvider'
|
||||
|
||||
@@ -175,6 +175,7 @@ export function getAssistantMessage({ assistant, topic }: { assistant: Assistant
|
||||
|
||||
export function getGroupedMessages(messages: Message[]): { [key: string]: (Message & { index: number })[] } {
|
||||
const groups: { [key: string]: (Message & { index: number })[] } = {}
|
||||
|
||||
messages.forEach((message, index) => {
|
||||
const key = message.askId ? 'assistant' + message.askId : 'user' + message.id
|
||||
if (key && !groups[key]) {
|
||||
@@ -182,6 +183,7 @@ export function getGroupedMessages(messages: Message[]): { [key: string]: (Messa
|
||||
}
|
||||
groups[key].unshift({ ...message, index })
|
||||
})
|
||||
|
||||
return groups
|
||||
}
|
||||
|
||||
|
||||
@@ -6,9 +6,9 @@ import { fetchChatCompletion } from '@renderer/services/ApiService'
|
||||
import { getAssistantMessage, resetAssistantMessage } from '@renderer/services/MessagesService'
|
||||
import type { AppDispatch, RootState } from '@renderer/store'
|
||||
import type { Assistant, Message, Topic } from '@renderer/types'
|
||||
import { Model } from '@renderer/types'
|
||||
import type { Model } from '@renderer/types'
|
||||
import { clearTopicQueue, getTopicQueue, waitForTopicQueue } from '@renderer/utils/queue'
|
||||
import { cloneDeep, isEmpty, throttle } from 'lodash'
|
||||
import { isEmpty, throttle } from 'lodash'
|
||||
|
||||
export interface MessagesState {
|
||||
messagesByTopic: Record<string, Message[]>
|
||||
@@ -113,14 +113,10 @@ const messagesSlice = createSlice({
|
||||
) => {
|
||||
const { topicId, messageId, updates } = action.payload
|
||||
const topicMessages = state.messagesByTopic[topicId]
|
||||
|
||||
if (topicMessages) {
|
||||
const message = topicMessages.find((msg) => msg.id === messageId)
|
||||
if (message) {
|
||||
Object.assign(message, updates)
|
||||
db.topics.update(topicId, {
|
||||
messages: topicMessages.map((m) => (m.id === message.id ? cloneDeep(message) : cloneDeep(m)))
|
||||
})
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -255,7 +251,7 @@ export const sendMessage =
|
||||
const isGroupedMessage = messageToReset.length > 1
|
||||
const resetMessage = resetAssistantMessage(m, isGroupedMessage ? m.model : assistant.model)
|
||||
// 更新状态
|
||||
dispatch(updateMessage({ topicId: topic.id, messageId: m.id, updates: resetMessage }))
|
||||
dispatch(updateMessageThunk(topic.id, m.id, resetMessage))
|
||||
// 使用重置后的消息
|
||||
return resetMessage
|
||||
})
|
||||
@@ -263,7 +259,7 @@ export const sendMessage =
|
||||
const { model, id } = messageToReset
|
||||
const resetMessage = resetAssistantMessage(messageToReset, model)
|
||||
// 更新状态
|
||||
dispatch(updateMessage({ topicId: topic.id, messageId: id, updates: resetMessage }))
|
||||
dispatch(updateMessageThunk(topic.id, id, resetMessage))
|
||||
// 使用重置后的消息
|
||||
assistantMessages.push(resetMessage)
|
||||
}
|
||||
@@ -396,10 +392,9 @@ export const sendMessage =
|
||||
} catch (error: any) {
|
||||
console.error('Error in chat completion:', error)
|
||||
dispatch(
|
||||
updateMessage({
|
||||
topicId: topic.id,
|
||||
messageId: assistantMessage.id,
|
||||
updates: { status: 'error', error: { message: error.message } }
|
||||
updateMessageThunk(topic.id, assistantMessage.id, {
|
||||
status: 'error',
|
||||
error: { message: error.message }
|
||||
})
|
||||
)
|
||||
dispatch(clearStreamMessage({ topicId: topic.id, messageId: assistantMessage.id }))
|
||||
@@ -448,10 +443,9 @@ export const resendMessage =
|
||||
const userMessage = topicMessages.find((m) => m.id === message.askId && m.role === 'user')
|
||||
if (!userMessage) {
|
||||
dispatch(
|
||||
updateMessage({
|
||||
topicId: topic.id,
|
||||
messageId: message.id,
|
||||
updates: { status: 'error', error: { message: i18n.t('error.user_message_not_found') } }
|
||||
updateMessageThunk(topic.id, message.id, {
|
||||
status: 'error',
|
||||
error: { message: i18n.t('error.user_message_not_found') }
|
||||
})
|
||||
)
|
||||
console.error(i18n.t('error.user_message_not_found'))
|
||||
@@ -521,6 +515,14 @@ export const clearTopicMessagesThunk = (topic: Topic) => async (dispatch: AppDis
|
||||
}
|
||||
}
|
||||
|
||||
export const deleteMessageAction =
|
||||
(topic: Topic, id: string, idType: 'id' | 'askId' = 'id') =>
|
||||
async (dispatch: AppDispatch, getState: () => RootState) => {
|
||||
const messages = getState().messages.messagesByTopic[topic.id] || []
|
||||
const newMessages = messages.filter((m) => m[idType] !== id)
|
||||
await dispatch(updateMessages(topic, newMessages))
|
||||
}
|
||||
|
||||
// 修改的 updateMessages thunk,同时更新缓存
|
||||
export const updateMessages = (topic: Topic, messages: Message[]) => async (dispatch: AppDispatch) => {
|
||||
try {
|
||||
@@ -534,6 +536,28 @@ export const updateMessages = (topic: Topic, messages: Message[]) => async (disp
|
||||
}
|
||||
}
|
||||
|
||||
// 新增一个 thunk 来处理消息更新
|
||||
export const updateMessageThunk =
|
||||
(topicId: string, messageId: string, updates: Partial<Message>) =>
|
||||
async (dispatch: AppDispatch, getState: () => RootState) => {
|
||||
try {
|
||||
// 先更新 Redux 状态
|
||||
dispatch(updateMessage({ topicId, messageId, updates }))
|
||||
|
||||
// 然后同步到数据库
|
||||
const state = getState()
|
||||
const topicMessages = state.messages.messagesByTopic[topicId]
|
||||
if (topicMessages) {
|
||||
await db.topics.update(topicId, {
|
||||
messages: topicMessages
|
||||
})
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Failed to update message:', error)
|
||||
dispatch(setError(error instanceof Error ? error.message : 'Failed to update message'))
|
||||
}
|
||||
}
|
||||
|
||||
// Selectors
|
||||
export const selectCurrentTopicId = (state: RootState): string | null => {
|
||||
const messagesState = state.messages
|
||||
@@ -546,11 +570,10 @@ export const selectTopicMessages = createSelector(
|
||||
)
|
||||
|
||||
// 获取特定话题的loading状态
|
||||
export const selectTopicLoading = (state: RootState, topicId?: string): boolean => {
|
||||
const messagesState = state.messages as MessagesState
|
||||
const currentTopicId = topicId || messagesState.currentTopic?.id || ''
|
||||
return currentTopicId ? (messagesState.loadingByTopic[currentTopicId] ?? false) : false
|
||||
}
|
||||
export const selectTopicLoading = createSelector(
|
||||
[(state: RootState) => state.messages.loadingByTopic, (_, topicId?: string) => topicId],
|
||||
(loadingByTopic, topicId) => (topicId ? (loadingByTopic[topicId] ?? false) : false)
|
||||
)
|
||||
|
||||
export const selectDisplayCount = (state: RootState): number => {
|
||||
const messagesState = state.messages as MessagesState
|
||||
|
||||
@@ -805,6 +805,7 @@ const migrateConfig = {
|
||||
state.settings.autoCheckUpdate = !state.settings.manualUpdateCheck
|
||||
// @ts-ignore eslint-disable-next-line
|
||||
delete state.settings.manualUpdateCheck
|
||||
state.settings.gridPopoverTrigger = 'click'
|
||||
return state
|
||||
},
|
||||
'86': (state: RootState) => {
|
||||
|
||||
@@ -53,6 +53,7 @@ export interface SettingsState {
|
||||
mathEngine: 'MathJax' | 'KaTeX'
|
||||
messageStyle: 'plain' | 'bubble'
|
||||
codeStyle: CodeStyleVarious
|
||||
foldDisplayMode: 'expanded' | 'compact'
|
||||
gridColumns: number
|
||||
gridPopoverTrigger: 'hover' | 'click'
|
||||
messageNavigation: 'none' | 'buttons' | 'anchor'
|
||||
@@ -135,8 +136,9 @@ const initialState: SettingsState = {
|
||||
mathEngine: 'KaTeX',
|
||||
messageStyle: 'plain',
|
||||
codeStyle: 'auto',
|
||||
foldDisplayMode: 'expanded',
|
||||
gridColumns: 2,
|
||||
gridPopoverTrigger: 'hover',
|
||||
gridPopoverTrigger: 'click',
|
||||
messageNavigation: 'none',
|
||||
webdavHost: '',
|
||||
webdavUser: '',
|
||||
@@ -295,6 +297,9 @@ const settingsSlice = createSlice({
|
||||
setMathEngine: (state, action: PayloadAction<'MathJax' | 'KaTeX'>) => {
|
||||
state.mathEngine = action.payload
|
||||
},
|
||||
setFoldDisplayMode: (state, action: PayloadAction<'expanded' | 'compact'>) => {
|
||||
state.foldDisplayMode = action.payload
|
||||
},
|
||||
setGridColumns: (state, action: PayloadAction<number>) => {
|
||||
state.gridColumns = action.payload
|
||||
},
|
||||
@@ -446,6 +451,7 @@ export const {
|
||||
setCodeCollapsible,
|
||||
setCodeWrappable,
|
||||
setMathEngine,
|
||||
setFoldDisplayMode,
|
||||
setGridColumns,
|
||||
setGridPopoverTrigger,
|
||||
setMessageStyle,
|
||||
|
||||
@@ -306,7 +306,7 @@ export async function captureDiv(divRef: React.RefObject<HTMLDivElement>) {
|
||||
return Promise.resolve(undefined)
|
||||
}
|
||||
|
||||
export const captureScrollableDiv = async (divRef: React.RefObject<HTMLDivElement>) => {
|
||||
export const captureScrollableDiv = async (divRef: React.RefObject<HTMLDivElement | null>) => {
|
||||
if (divRef.current) {
|
||||
try {
|
||||
const div = divRef.current
|
||||
@@ -392,7 +392,7 @@ export const captureScrollableDiv = async (divRef: React.RefObject<HTMLDivElemen
|
||||
return Promise.resolve(undefined)
|
||||
}
|
||||
|
||||
export const captureScrollableDivAsDataURL = async (divRef: React.RefObject<HTMLDivElement>) => {
|
||||
export const captureScrollableDivAsDataURL = async (divRef: React.RefObject<HTMLDivElement | null>) => {
|
||||
return captureScrollableDiv(divRef).then((canvas) => {
|
||||
if (canvas) {
|
||||
return canvas.toDataURL('image/png')
|
||||
@@ -401,7 +401,10 @@ export const captureScrollableDivAsDataURL = async (divRef: React.RefObject<HTML
|
||||
})
|
||||
}
|
||||
|
||||
export const captureScrollableDivAsBlob = async (divRef: React.RefObject<HTMLDivElement>, func: BlobCallback) => {
|
||||
export const captureScrollableDivAsBlob = async (
|
||||
divRef: React.RefObject<HTMLDivElement | null>,
|
||||
func: BlobCallback
|
||||
) => {
|
||||
await captureScrollableDiv(divRef).then((canvas) => {
|
||||
canvas?.toBlob(func, 'image/png')
|
||||
})
|
||||
|
||||
@@ -9,7 +9,7 @@ import { SyntaxHighlighterProvider } from '../../context/SyntaxHighlighterProvid
|
||||
import { ThemeProvider } from '../../context/ThemeProvider'
|
||||
import HomeWindow from './home/HomeWindow'
|
||||
|
||||
function MiniWindow(): JSX.Element {
|
||||
function MiniWindow(): React.ReactElement {
|
||||
return (
|
||||
<Provider store={store}>
|
||||
<ThemeProvider>
|
||||
|
||||
@@ -165,6 +165,17 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@ant-design/v5-patch-for-react-19@npm:^1.0.3":
|
||||
version: 1.0.3
|
||||
resolution: "@ant-design/v5-patch-for-react-19@npm:1.0.3"
|
||||
peerDependencies:
|
||||
antd: ">=5.22.6"
|
||||
react: ">=19.0.0"
|
||||
react-dom: ">=19.0.0"
|
||||
checksum: 10c0/e3848c929b01a0a29a41e2886f489932e54d9665dd990c60c4b505e21740da2ef0db0d08f4dc7591651fa1f21b15227e7bb40f40280742225b4da74fd18cc899
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@anthropic-ai/sdk@npm:^0.38.0":
|
||||
version: 0.38.0
|
||||
resolution: "@anthropic-ai/sdk@npm:0.38.0"
|
||||
@@ -451,6 +462,176 @@ __metadata:
|
||||
languageName: unknown
|
||||
linkType: soft
|
||||
|
||||
"@cherrystudio/embedjs-interfaces@npm:0.1.29":
|
||||
version: 0.1.29
|
||||
resolution: "@cherrystudio/embedjs-interfaces@npm:0.1.29"
|
||||
dependencies:
|
||||
"@langchain/core": "npm:^0.3.26"
|
||||
debug: "npm:^4.4.0"
|
||||
md5: "npm:^2.3.0"
|
||||
uuid: "npm:^11.0.3"
|
||||
checksum: 10c0/df7ac19aecae137e5af427bb1605232993ef1510e3d41875cb8dd604e7a692778758e5f640a6ab839aaa4193c21012a50b7dfb0aa42c434e668f99faa0fd04d7
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@cherrystudio/embedjs-libsql@npm:^0.1.28":
|
||||
version: 0.1.29
|
||||
resolution: "@cherrystudio/embedjs-libsql@npm:0.1.29"
|
||||
dependencies:
|
||||
"@cherrystudio/embedjs-interfaces": "npm:0.1.29"
|
||||
"@cherrystudio/embedjs-utils": "npm:0.1.29"
|
||||
"@libsql/client": "npm:^0.14.0"
|
||||
debug: "npm:^4.4.0"
|
||||
checksum: 10c0/655da13d5e192bb0d46e36cbe1ee444b290f6d98d39ad4ac72004fa0aa1a2f5c6dc7a41dd2a9631cc80014501e3423fbd3a822f9fcb331617ab0a43db9692410
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@cherrystudio/embedjs-loader-csv@npm:^0.1.28":
|
||||
version: 0.1.29
|
||||
resolution: "@cherrystudio/embedjs-loader-csv@npm:0.1.29"
|
||||
dependencies:
|
||||
"@cherrystudio/embedjs-interfaces": "npm:0.1.29"
|
||||
"@cherrystudio/embedjs-utils": "npm:0.1.29"
|
||||
csv-parse: "npm:^5.6.0"
|
||||
debug: "npm:^4.4.0"
|
||||
md5: "npm:^2.3.0"
|
||||
checksum: 10c0/7c54791fe836839bf3b6a882a9e4c5656b4f30e54aa4e8967b380bc858fd76e03b2ca39b050bc5c06ffbc9e0c722d91d5dd0acf9edf576ff279805d718dfd437
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@cherrystudio/embedjs-loader-image@npm:^0.1.28":
|
||||
version: 0.1.29
|
||||
resolution: "@cherrystudio/embedjs-loader-image@npm:0.1.29"
|
||||
dependencies:
|
||||
"@cherrystudio/embedjs-interfaces": "npm:0.1.29"
|
||||
"@cherrystudio/embedjs-utils": "npm:0.1.29"
|
||||
"@langchain/core": "npm:^0.3.26"
|
||||
debug: "npm:^4.4.0"
|
||||
exifremove: "npm:^1.0.1"
|
||||
md5: "npm:^2.3.0"
|
||||
mime: "npm:^4.0.6"
|
||||
stream-mime-type: "npm:^2.0.0"
|
||||
checksum: 10c0/cbc43bf0be38ccd231a35ee06f160fee4628267a912f222c2c326e6d383a0477e1faad1910c9cd485ef8857b63d4404a9797c7e6a9661773345a4cca1ce956cf
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@cherrystudio/embedjs-loader-markdown@npm:^0.1.28":
|
||||
version: 0.1.29
|
||||
resolution: "@cherrystudio/embedjs-loader-markdown@npm:0.1.29"
|
||||
dependencies:
|
||||
"@cherrystudio/embedjs-interfaces": "npm:0.1.29"
|
||||
"@cherrystudio/embedjs-loader-web": "npm:0.1.29"
|
||||
debug: "npm:^4.4.0"
|
||||
md5: "npm:^2.3.0"
|
||||
micromark: "npm:^4.0.1"
|
||||
micromark-extension-gfm: "npm:^3.0.0"
|
||||
micromark-extension-mdx-jsx: "npm:^3.0.1"
|
||||
checksum: 10c0/068393c00321a03a7b7881bb9b4b3b115440a91496b4fef43ad9b7f352c763aa59a6a33f69c9db39f2ed4c0a727f7e1dcd28448f7a446a5ec6a62edbd035f5a8
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@cherrystudio/embedjs-loader-msoffice@npm:^0.1.28":
|
||||
version: 0.1.29
|
||||
resolution: "@cherrystudio/embedjs-loader-msoffice@npm:0.1.29"
|
||||
dependencies:
|
||||
"@cherrystudio/embedjs-interfaces": "npm:0.1.29"
|
||||
"@cherrystudio/embedjs-utils": "npm:0.1.29"
|
||||
"@langchain/textsplitters": "npm:^0.1.0"
|
||||
md5: "npm:^2.3.0"
|
||||
office-text-extractor: "npm:^3.0.3"
|
||||
checksum: 10c0/be97eb2278d29f06b569b0aa2fd2b3640caf43207268f5c5cbe16fb77776fe026e4e0d5a9c6360f61c4af439561022f6f4becbe97c2b903d1d446021ab3bf38f
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@cherrystudio/embedjs-loader-pdf@npm:^0.1.28":
|
||||
version: 0.1.29
|
||||
resolution: "@cherrystudio/embedjs-loader-pdf@npm:0.1.29"
|
||||
dependencies:
|
||||
"@cherrystudio/embedjs-interfaces": "npm:0.1.29"
|
||||
"@cherrystudio/embedjs-utils": "npm:0.1.29"
|
||||
"@langchain/textsplitters": "npm:^0.1.0"
|
||||
md5: "npm:^2.3.0"
|
||||
office-text-extractor: "npm:^3.0.3"
|
||||
checksum: 10c0/cd45963f9405cd1b817f9539ad876dd32e214d21b651459822fc9f829105dc4934daf1aded9cc7084efd9dc914901b4b72fc52a7c5aa9fb550454b0e465844cf
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@cherrystudio/embedjs-loader-sitemap@npm:^0.1.28":
|
||||
version: 0.1.29
|
||||
resolution: "@cherrystudio/embedjs-loader-sitemap@npm:0.1.29"
|
||||
dependencies:
|
||||
"@cherrystudio/embedjs-interfaces": "npm:0.1.29"
|
||||
"@cherrystudio/embedjs-loader-web": "npm:0.1.29"
|
||||
debug: "npm:^4.4.0"
|
||||
md5: "npm:^2.3.0"
|
||||
sitemapper: "npm:^3.2.20"
|
||||
checksum: 10c0/2cb5fba68f3e89026b08274f3d286b46c44192f3e8b499d72984e63f36d174bdc7da6c8122c922b8fd5660fa0bc1fbbdbaecc37dae134467d2a501fd1642f0d2
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@cherrystudio/embedjs-loader-web@npm:0.1.29, @cherrystudio/embedjs-loader-web@npm:^0.1.28":
|
||||
version: 0.1.29
|
||||
resolution: "@cherrystudio/embedjs-loader-web@npm:0.1.29"
|
||||
dependencies:
|
||||
"@cherrystudio/embedjs-interfaces": "npm:0.1.29"
|
||||
"@cherrystudio/embedjs-utils": "npm:0.1.29"
|
||||
"@langchain/textsplitters": "npm:^0.1.0"
|
||||
debug: "npm:^4.4.0"
|
||||
html-to-text: "npm:^9.0.5"
|
||||
md5: "npm:^2.3.0"
|
||||
checksum: 10c0/a15529e45e309993644db7ee8546f970c0d94fd54baf5044d650a0af66cddb9729af5f3a3fb115c13cd7b7b2ab38bb3809cc088d4c6346e9ca33e478845820f3
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@cherrystudio/embedjs-loader-xml@npm:^0.1.28":
|
||||
version: 0.1.29
|
||||
resolution: "@cherrystudio/embedjs-loader-xml@npm:0.1.29"
|
||||
dependencies:
|
||||
"@cherrystudio/embedjs-interfaces": "npm:0.1.29"
|
||||
debug: "npm:^4.4.0"
|
||||
fast-xml-parser: "npm:^4.5.1"
|
||||
md5: "npm:^2.3.0"
|
||||
checksum: 10c0/cf24dc1b48d55197f3773a9f7490c521461c6cade86869a333bac6c05dae10529ecdbaa03dbfce0994e07215fe343c9801b81356a6141965aa10d50fe2e6c858
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@cherrystudio/embedjs-openai@npm:^0.1.28":
|
||||
version: 0.1.29
|
||||
resolution: "@cherrystudio/embedjs-openai@npm:0.1.29"
|
||||
dependencies:
|
||||
"@cherrystudio/embedjs-interfaces": "npm:0.1.29"
|
||||
"@langchain/core": "npm:^0.3.26"
|
||||
"@langchain/openai": "npm:^0.3.16"
|
||||
debug: "npm:^4.4.0"
|
||||
checksum: 10c0/10451eb9e0c8f613ea3829b478120890ee44e2a9c7707a48797c21cbd4f4479ad56f86bd38099762900ddf17d42758dba938325eaaa9fae66f71e033c6b64dd5
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@cherrystudio/embedjs-utils@npm:0.1.29":
|
||||
version: 0.1.29
|
||||
resolution: "@cherrystudio/embedjs-utils@npm:0.1.29"
|
||||
dependencies:
|
||||
"@cherrystudio/embedjs-interfaces": "npm:0.1.29"
|
||||
checksum: 10c0/1b8d8e38207e7588ee134c316bc566dfb68d56023887be61793480cdeac0fc5a2dcc3c72f7727daae801abcaf16e8518ab9dcb7b0b0f7d3a16473a8830ba9dff
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@cherrystudio/embedjs@npm:^0.1.28":
|
||||
version: 0.1.29
|
||||
resolution: "@cherrystudio/embedjs@npm:0.1.29"
|
||||
dependencies:
|
||||
"@cherrystudio/embedjs-interfaces": "npm:0.1.29"
|
||||
"@cherrystudio/embedjs-utils": "npm:0.1.29"
|
||||
"@langchain/textsplitters": "npm:^0.1.0"
|
||||
debug: "npm:^4.4.0"
|
||||
langchain: "npm:^0.3.8"
|
||||
md5: "npm:^2.3.0"
|
||||
mime: "npm:^4.0.6"
|
||||
stream-mime-type: "npm:^2.0.0"
|
||||
checksum: 10c0/01487ab886e7c5c260fc65dee0d67407988e58fa82a1f0fdc4a332548a570cc63f5d39cc87878a7e3272be547a306fee5ec6caa805614eb4e139ce1259b7f6c9
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@cherrystudio/mac-system-ocr@npm:^0.1.0":
|
||||
version: 0.1.0
|
||||
resolution: "@cherrystudio/mac-system-ocr@npm:0.1.0"
|
||||
@@ -2178,207 +2359,6 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@llm-tools/embedjs-interfaces@npm:0.1.28":
|
||||
version: 0.1.28
|
||||
resolution: "@llm-tools/embedjs-interfaces@npm:0.1.28"
|
||||
dependencies:
|
||||
"@langchain/core": "npm:^0.3.26"
|
||||
debug: "npm:^4.4.0"
|
||||
md5: "npm:^2.3.0"
|
||||
uuid: "npm:^11.0.3"
|
||||
checksum: 10c0/51c89f2254da60aa01d911a22e8fe852564609525b95090f71385e653e42ef87b99af8d6450debfd0d5a4baa43ebeef8136109fefb09f19551a969e397d43dc1
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@llm-tools/embedjs-libsql@npm:^0.1.28":
|
||||
version: 0.1.28
|
||||
resolution: "@llm-tools/embedjs-libsql@npm:0.1.28"
|
||||
dependencies:
|
||||
"@libsql/client": "npm:^0.14.0"
|
||||
"@llm-tools/embedjs-interfaces": "npm:0.1.28"
|
||||
"@llm-tools/embedjs-utils": "npm:0.1.28"
|
||||
debug: "npm:^4.4.0"
|
||||
checksum: 10c0/ec2c50d89a9d601618d153839fc1545bef38a8a7475f2b6ed21a5d876d7964b958950872df64719a3a851a6d48a3a613233c854a091726ebdf2d992c1fdadf7f
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@llm-tools/embedjs-loader-csv@npm:^0.1.28":
|
||||
version: 0.1.28
|
||||
resolution: "@llm-tools/embedjs-loader-csv@npm:0.1.28"
|
||||
dependencies:
|
||||
"@llm-tools/embedjs-interfaces": "npm:0.1.28"
|
||||
"@llm-tools/embedjs-utils": "npm:0.1.28"
|
||||
csv-parse: "npm:^5.6.0"
|
||||
debug: "npm:^4.4.0"
|
||||
md5: "npm:^2.3.0"
|
||||
checksum: 10c0/dfa0f6825e0d3da9b703381d7e1c9765aea6b99cea2663fc0134e77b2b8bf331f8d8718f812e4efc31416e21450d67b2bf7fe3138a48146b871ab646aa3fd87e
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@llm-tools/embedjs-loader-image@npm:^0.1.28":
|
||||
version: 0.1.28
|
||||
resolution: "@llm-tools/embedjs-loader-image@npm:0.1.28"
|
||||
dependencies:
|
||||
"@langchain/core": "npm:^0.3.26"
|
||||
"@llm-tools/embedjs-interfaces": "npm:0.1.28"
|
||||
"@llm-tools/embedjs-utils": "npm:0.1.28"
|
||||
debug: "npm:^4.4.0"
|
||||
exifremove: "npm:^1.0.1"
|
||||
md5: "npm:^2.3.0"
|
||||
mime: "npm:^4.0.6"
|
||||
stream-mime-type: "npm:^2.0.0"
|
||||
checksum: 10c0/e9414dde0d10afe1541bfe464b80f5cb61ec523f28dce62ab931a3f4ffde93c5589fde8e7a7f5751e7dc20d68fe2d28883925ba65e2542ee9d43002591568af1
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@llm-tools/embedjs-loader-markdown@npm:0.1.28":
|
||||
version: 0.1.28
|
||||
resolution: "@llm-tools/embedjs-loader-markdown@npm:0.1.28"
|
||||
dependencies:
|
||||
"@llm-tools/embedjs-interfaces": "npm:0.1.28"
|
||||
"@llm-tools/embedjs-loader-web": "npm:0.1.28"
|
||||
debug: "npm:^4.4.0"
|
||||
md5: "npm:^2.3.0"
|
||||
micromark: "npm:^4.0.1"
|
||||
micromark-extension-gfm: "npm:^3.0.0"
|
||||
micromark-extension-mdx-jsx: "npm:^3.0.1"
|
||||
checksum: 10c0/deb86848c57cdaf1aa89cd3382505aa4cc53c170d68105a97da1f6ebaff508ed6db1f164004ae1e0426266c29e15435a5bc092eb37ca4fb81ee574940daf1c0e
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@llm-tools/embedjs-loader-markdown@patch:@llm-tools/embedjs-loader-markdown@npm%3A0.1.28#~/.yarn/patches/@llm-tools-embedjs-loader-markdown-npm-0.1.28-81647ffac6.patch":
|
||||
version: 0.1.28
|
||||
resolution: "@llm-tools/embedjs-loader-markdown@patch:@llm-tools/embedjs-loader-markdown@npm%3A0.1.28#~/.yarn/patches/@llm-tools-embedjs-loader-markdown-npm-0.1.28-81647ffac6.patch::version=0.1.28&hash=9c7dea"
|
||||
dependencies:
|
||||
"@llm-tools/embedjs-interfaces": "npm:0.1.28"
|
||||
"@llm-tools/embedjs-loader-web": "npm:0.1.28"
|
||||
debug: "npm:^4.4.0"
|
||||
md5: "npm:^2.3.0"
|
||||
micromark: "npm:^4.0.1"
|
||||
micromark-extension-gfm: "npm:^3.0.0"
|
||||
micromark-extension-mdx-jsx: "npm:^3.0.1"
|
||||
checksum: 10c0/4be7354294c9cc1ee5b93e0bf49a218894e5a0ad63f344300a9277751fb7517d7ff9ab51594eb63f548d303cec0c747507a5df29bd92deb506bf9829f1675f67
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@llm-tools/embedjs-loader-msoffice@npm:^0.1.28":
|
||||
version: 0.1.28
|
||||
resolution: "@llm-tools/embedjs-loader-msoffice@npm:0.1.28"
|
||||
dependencies:
|
||||
"@langchain/textsplitters": "npm:^0.1.0"
|
||||
"@llm-tools/embedjs-interfaces": "npm:0.1.28"
|
||||
"@llm-tools/embedjs-utils": "npm:0.1.28"
|
||||
md5: "npm:^2.3.0"
|
||||
office-text-extractor: "npm:^3.0.3"
|
||||
checksum: 10c0/dbc511938c16ebfcfe9cfedfe68b64b15e2290474092c3600cf290ccb3da5a116a7bd2d469a7f26ee24882cc6835260ad3129ddd54c0f50cc96ef1fa0b142abe
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@llm-tools/embedjs-loader-pdf@npm:^0.1.28":
|
||||
version: 0.1.28
|
||||
resolution: "@llm-tools/embedjs-loader-pdf@npm:0.1.28"
|
||||
dependencies:
|
||||
"@langchain/textsplitters": "npm:^0.1.0"
|
||||
"@llm-tools/embedjs-interfaces": "npm:0.1.28"
|
||||
"@llm-tools/embedjs-utils": "npm:0.1.28"
|
||||
md5: "npm:^2.3.0"
|
||||
office-text-extractor: "npm:^3.0.3"
|
||||
checksum: 10c0/3ac930561c137b2cc91dc22782c83857e60441a15710d3913351c69f4960dd50ad31a79a1c5f48c2784daf400fd86a03483b80ae3c375e085b1d42a759c9efbf
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@llm-tools/embedjs-loader-sitemap@npm:^0.1.28":
|
||||
version: 0.1.28
|
||||
resolution: "@llm-tools/embedjs-loader-sitemap@npm:0.1.28"
|
||||
dependencies:
|
||||
"@llm-tools/embedjs-interfaces": "npm:0.1.28"
|
||||
"@llm-tools/embedjs-loader-web": "npm:0.1.28"
|
||||
debug: "npm:^4.4.0"
|
||||
md5: "npm:^2.3.0"
|
||||
sitemapper: "npm:^3.2.20"
|
||||
checksum: 10c0/007f45d02e1200b7cca0bd2f21514910e4b0243126b553404f55c80196b82e673ce09ef1c77f515ab6a6a9397f06ee58799ac8c5f885635ffa759fcd14076fc2
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@llm-tools/embedjs-loader-web@npm:0.1.28, @llm-tools/embedjs-loader-web@npm:^0.1.28":
|
||||
version: 0.1.28
|
||||
resolution: "@llm-tools/embedjs-loader-web@npm:0.1.28"
|
||||
dependencies:
|
||||
"@langchain/textsplitters": "npm:^0.1.0"
|
||||
"@llm-tools/embedjs-interfaces": "npm:0.1.28"
|
||||
"@llm-tools/embedjs-utils": "npm:0.1.28"
|
||||
debug: "npm:^4.4.0"
|
||||
html-to-text: "npm:^9.0.5"
|
||||
md5: "npm:^2.3.0"
|
||||
checksum: 10c0/2abf61ebfa8e2f145730cc2676cf49f5f84b32b5f1c90b5dc58c820b13ab02c10f31bca9891fdb675a7f66a421bb407a0a192d069ea48184eb2b4b4b995382bd
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@llm-tools/embedjs-loader-xml@npm:^0.1.28":
|
||||
version: 0.1.28
|
||||
resolution: "@llm-tools/embedjs-loader-xml@npm:0.1.28"
|
||||
dependencies:
|
||||
"@llm-tools/embedjs-interfaces": "npm:0.1.28"
|
||||
debug: "npm:^4.4.0"
|
||||
fast-xml-parser: "npm:^4.5.1"
|
||||
md5: "npm:^2.3.0"
|
||||
checksum: 10c0/20595caa970a1f715f462a66f949e5f9d931431171cd6a55b70f6aeb9166a84233b397d688594de3764974d9d94c066d104f0e3b0c2b79967404cf452b1f7a93
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@llm-tools/embedjs-openai@npm:^0.1.28":
|
||||
version: 0.1.28
|
||||
resolution: "@llm-tools/embedjs-openai@npm:0.1.28"
|
||||
dependencies:
|
||||
"@langchain/core": "npm:^0.3.26"
|
||||
"@langchain/openai": "npm:^0.3.16"
|
||||
"@llm-tools/embedjs-interfaces": "npm:0.1.28"
|
||||
debug: "npm:^4.4.0"
|
||||
checksum: 10c0/cc8a703acf447a568f30b218ccb1935529a956177a8adac08f7a67fc4f6257f2a61ed21218341835250c9610566e3219bc8cf866a04423f3099631a85f29c32c
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@llm-tools/embedjs-utils@npm:0.1.28":
|
||||
version: 0.1.28
|
||||
resolution: "@llm-tools/embedjs-utils@npm:0.1.28"
|
||||
dependencies:
|
||||
"@llm-tools/embedjs-interfaces": "npm:0.1.28"
|
||||
checksum: 10c0/7d97b36be831d894102fed34a7e7078eade509b4fbd78d991160f60b2d2d8f3136e6ad93edcf64a3d2b7be346c83cdae9b0ecb63d35aa02eb38dfb4f9cff6117
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@llm-tools/embedjs@npm:0.1.28":
|
||||
version: 0.1.28
|
||||
resolution: "@llm-tools/embedjs@npm:0.1.28"
|
||||
dependencies:
|
||||
"@langchain/textsplitters": "npm:^0.1.0"
|
||||
"@llm-tools/embedjs-interfaces": "npm:0.1.28"
|
||||
"@llm-tools/embedjs-utils": "npm:0.1.28"
|
||||
debug: "npm:^4.4.0"
|
||||
langchain: "npm:^0.3.8"
|
||||
md5: "npm:^2.3.0"
|
||||
mime: "npm:^4.0.6"
|
||||
stream-mime-type: "npm:^2.0.0"
|
||||
checksum: 10c0/0ade20a97b987c5b24175e1e46c7f0917e91b0acde712e9a759fb9fe7f48b04a79fca28c2e4cc8702a25e6cd7fba8a9351bf1f7e5bbf1373f0f60de047703d7a
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@llm-tools/embedjs@patch:@llm-tools/embedjs@npm%3A0.1.28#~/.yarn/patches/@llm-tools-embedjs-npm-0.1.28-8e4393fa2d.patch":
|
||||
version: 0.1.28
|
||||
resolution: "@llm-tools/embedjs@patch:@llm-tools/embedjs@npm%3A0.1.28#~/.yarn/patches/@llm-tools-embedjs-npm-0.1.28-8e4393fa2d.patch::version=0.1.28&hash=51ffc6"
|
||||
dependencies:
|
||||
"@langchain/textsplitters": "npm:^0.1.0"
|
||||
"@llm-tools/embedjs-interfaces": "npm:0.1.28"
|
||||
"@llm-tools/embedjs-utils": "npm:0.1.28"
|
||||
debug: "npm:^4.4.0"
|
||||
langchain: "npm:^0.3.8"
|
||||
md5: "npm:^2.3.0"
|
||||
mime: "npm:^4.0.6"
|
||||
stream-mime-type: "npm:^2.0.0"
|
||||
checksum: 10c0/2af2bcd2f6476eaf02ed9ff5e189ecb03d663146cd5229c3c32b45fef8a37fd84a48193f8d067eaf9339e89a5035502c4ff48d2370dfd655294daa8b4e365841
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@malept/cross-spawn-promise@npm:^1.1.0":
|
||||
version: 1.1.1
|
||||
resolution: "@malept/cross-spawn-promise@npm:1.1.1"
|
||||
@@ -3534,19 +3514,12 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@types/prop-types@npm:*":
|
||||
version: 15.7.14
|
||||
resolution: "@types/prop-types@npm:15.7.14"
|
||||
checksum: 10c0/1ec775160bfab90b67a782d735952158c7e702ca4502968aa82565bd8e452c2de8601c8dfe349733073c31179116cf7340710160d3836aa8a1ef76d1532893b1
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@types/react-dom@npm:^18.2.18":
|
||||
version: 18.3.5
|
||||
resolution: "@types/react-dom@npm:18.3.5"
|
||||
"@types/react-dom@npm:^19.0.4":
|
||||
version: 19.0.4
|
||||
resolution: "@types/react-dom@npm:19.0.4"
|
||||
peerDependencies:
|
||||
"@types/react": ^18.0.0
|
||||
checksum: 10c0/b163d35a6b32a79f5782574a7aeb12a31a647e248792bf437e6d596e2676961c394c5e3c6e91d1ce44ae90441dbaf93158efb4f051c0d61e2612f1cb04ce4faa
|
||||
"@types/react": ^19.0.0
|
||||
checksum: 10c0/4e71853919b94df9e746a4bd73f8180e9ae13016333ce9c543dcba9f4f4c8fe6e28b038ca6ee61c24e291af8e03ca3bc5ded17c46dee938fcb32d71186fda7a3
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@@ -3559,7 +3532,7 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@types/react@npm:*":
|
||||
"@types/react@npm:*, @types/react@npm:^19.0.12":
|
||||
version: 19.0.12
|
||||
resolution: "@types/react@npm:19.0.12"
|
||||
dependencies:
|
||||
@@ -3568,16 +3541,6 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@types/react@npm:^18.2.48":
|
||||
version: 18.3.19
|
||||
resolution: "@types/react@npm:18.3.19"
|
||||
dependencies:
|
||||
"@types/prop-types": "npm:*"
|
||||
csstype: "npm:^3.0.2"
|
||||
checksum: 10c0/236bfe0c4748ada1a640f13573eca3e0fc7c9d847b442947adb352b0718d6d285357fd84c33336c8ffb8cbfabc0d58a43a647c7fd79857fecd61fb58ab6f7918
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@types/responselike@npm:^1.0.0":
|
||||
version: 1.0.3
|
||||
resolution: "@types/responselike@npm:1.0.3"
|
||||
@@ -3845,7 +3808,19 @@ __metadata:
|
||||
"@agentic/exa": "npm:^7.3.3"
|
||||
"@agentic/searxng": "npm:^7.3.3"
|
||||
"@agentic/tavily": "npm:^7.3.3"
|
||||
"@ant-design/v5-patch-for-react-19": "npm:^1.0.3"
|
||||
"@anthropic-ai/sdk": "npm:^0.38.0"
|
||||
"@cherrystudio/embedjs": "npm:^0.1.28"
|
||||
"@cherrystudio/embedjs-libsql": "npm:^0.1.28"
|
||||
"@cherrystudio/embedjs-loader-csv": "npm:^0.1.28"
|
||||
"@cherrystudio/embedjs-loader-image": "npm:^0.1.28"
|
||||
"@cherrystudio/embedjs-loader-markdown": "npm:^0.1.28"
|
||||
"@cherrystudio/embedjs-loader-msoffice": "npm:^0.1.28"
|
||||
"@cherrystudio/embedjs-loader-pdf": "npm:^0.1.28"
|
||||
"@cherrystudio/embedjs-loader-sitemap": "npm:^0.1.28"
|
||||
"@cherrystudio/embedjs-loader-web": "npm:^0.1.28"
|
||||
"@cherrystudio/embedjs-loader-xml": "npm:^0.1.28"
|
||||
"@cherrystudio/embedjs-openai": "npm:^0.1.28"
|
||||
"@cherrystudio/mac-system-ocr": "npm:^0.1.0"
|
||||
"@electron-toolkit/eslint-config-prettier": "npm:^3.0.0"
|
||||
"@electron-toolkit/eslint-config-ts": "npm:^3.0.0"
|
||||
@@ -3861,17 +3836,6 @@ __metadata:
|
||||
"@hello-pangea/dnd": "npm:^16.6.0"
|
||||
"@kangfenmao/keyv-storage": "npm:^0.1.0"
|
||||
"@langchain/community": "npm:^0.3.36"
|
||||
"@llm-tools/embedjs": "patch:@llm-tools/embedjs@npm%3A0.1.28#~/.yarn/patches/@llm-tools-embedjs-npm-0.1.28-8e4393fa2d.patch"
|
||||
"@llm-tools/embedjs-libsql": "npm:^0.1.28"
|
||||
"@llm-tools/embedjs-loader-csv": "npm:^0.1.28"
|
||||
"@llm-tools/embedjs-loader-image": "npm:^0.1.28"
|
||||
"@llm-tools/embedjs-loader-markdown": "patch:@llm-tools/embedjs-loader-markdown@npm%3A0.1.28#~/.yarn/patches/@llm-tools-embedjs-loader-markdown-npm-0.1.28-81647ffac6.patch"
|
||||
"@llm-tools/embedjs-loader-msoffice": "npm:^0.1.28"
|
||||
"@llm-tools/embedjs-loader-pdf": "npm:^0.1.28"
|
||||
"@llm-tools/embedjs-loader-sitemap": "npm:^0.1.28"
|
||||
"@llm-tools/embedjs-loader-web": "npm:^0.1.28"
|
||||
"@llm-tools/embedjs-loader-xml": "npm:^0.1.28"
|
||||
"@llm-tools/embedjs-openai": "npm:^0.1.28"
|
||||
"@mistralai/mistralai": "npm:^1.5.2"
|
||||
"@modelcontextprotocol/sdk": "patch:@modelcontextprotocol/sdk@npm%3A1.6.1#~/.yarn/patches/@modelcontextprotocol-sdk-npm-1.6.1-b46313efe7.patch"
|
||||
"@notionhq/client": "npm:^2.2.15"
|
||||
@@ -3886,8 +3850,8 @@ __metadata:
|
||||
"@types/node": "npm:^18.19.9"
|
||||
"@types/pako": "npm:^1.0.2"
|
||||
"@types/pdf-parse": "npm:^1.1.4"
|
||||
"@types/react": "npm:^18.2.48"
|
||||
"@types/react-dom": "npm:^18.2.18"
|
||||
"@types/react": "npm:^19.0.12"
|
||||
"@types/react-dom": "npm:^19.0.4"
|
||||
"@types/react-infinite-scroll-component": "npm:^5.0.0"
|
||||
"@types/tinycolor2": "npm:^1"
|
||||
"@vitejs/plugin-react": "npm:^4.2.1"
|
||||
@@ -3937,8 +3901,9 @@ __metadata:
|
||||
pdf-to-img: "npm:^4.4.0"
|
||||
prettier: "npm:^3.5.3"
|
||||
proxy-agent: "npm:^6.5.0"
|
||||
react: "npm:^18.2.0"
|
||||
react-dom: "npm:^18.2.0"
|
||||
rc-virtual-list: "npm:^3.18.5"
|
||||
react: "npm:^19.0.0"
|
||||
react-dom: "npm:^19.0.0"
|
||||
react-hotkeys-hook: "npm:^4.6.1"
|
||||
react-i18next: "npm:^14.1.2"
|
||||
react-infinite-scroll-component: "npm:^6.1.0"
|
||||
@@ -3968,9 +3933,6 @@ __metadata:
|
||||
vite: "npm:^5.0.12"
|
||||
webdav: "npm:^5.8.0"
|
||||
zipread: "npm:^1.3.3"
|
||||
peerDependencies:
|
||||
react: ^17.0.0 || ^18.0.0
|
||||
react-dom: ^17.0.0 || ^18.0.0
|
||||
languageName: unknown
|
||||
linkType: soft
|
||||
|
||||
@@ -9333,7 +9295,7 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"js-tokens@npm:^3.0.0 || ^4.0.0, js-tokens@npm:^4.0.0":
|
||||
"js-tokens@npm:^4.0.0":
|
||||
version: 4.0.0
|
||||
resolution: "js-tokens@npm:4.0.0"
|
||||
checksum: 10c0/e248708d377aa058eacf2037b07ded847790e6de892bbad3dac0abba2e759cb9f121b00099a65195616badcb6eca8d14d975cb3e89eb1cfda644756402c8aeed
|
||||
@@ -9941,17 +9903,6 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"loose-envify@npm:^1.1.0":
|
||||
version: 1.4.0
|
||||
resolution: "loose-envify@npm:1.4.0"
|
||||
dependencies:
|
||||
js-tokens: "npm:^3.0.0 || ^4.0.0"
|
||||
bin:
|
||||
loose-envify: cli.js
|
||||
checksum: 10c0/655d110220983c1a4b9c0c679a2e8016d4b67f6e9c7b5435ff5979ecdb20d0813f4dec0a08674fcbdd4846a3f07edbb50a36811fd37930b94aaa0d9daceb017e
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"lop@npm:^0.4.1":
|
||||
version: 0.4.2
|
||||
resolution: "lop@npm:0.4.2"
|
||||
@@ -13493,7 +13444,7 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"rc-virtual-list@npm:^3.14.2, rc-virtual-list@npm:^3.5.1, rc-virtual-list@npm:^3.5.2":
|
||||
"rc-virtual-list@npm:^3.14.2, rc-virtual-list@npm:^3.18.5, rc-virtual-list@npm:^3.5.1, rc-virtual-list@npm:^3.5.2":
|
||||
version: 3.18.5
|
||||
resolution: "rc-virtual-list@npm:3.18.5"
|
||||
dependencies:
|
||||
@@ -13522,15 +13473,14 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"react-dom@npm:^18.2.0":
|
||||
version: 18.3.1
|
||||
resolution: "react-dom@npm:18.3.1"
|
||||
"react-dom@npm:^19.0.0":
|
||||
version: 19.0.0
|
||||
resolution: "react-dom@npm:19.0.0"
|
||||
dependencies:
|
||||
loose-envify: "npm:^1.1.0"
|
||||
scheduler: "npm:^0.23.2"
|
||||
scheduler: "npm:^0.25.0"
|
||||
peerDependencies:
|
||||
react: ^18.3.1
|
||||
checksum: 10c0/a752496c1941f958f2e8ac56239172296fcddce1365ce45222d04a1947e0cc5547df3e8447f855a81d6d39f008d7c32eab43db3712077f09e3f67c4874973e85
|
||||
react: ^19.0.0
|
||||
checksum: 10c0/a36ce7ab507b237ae2759c984cdaad4af4096d8199fb65b3815c16825e5cfeb7293da790a3fc2184b52bfba7ba3ff31c058c01947aff6fd1a3701632aabaa6a9
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@@ -13701,12 +13651,10 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"react@npm:^18.2.0":
|
||||
version: 18.3.1
|
||||
resolution: "react@npm:18.3.1"
|
||||
dependencies:
|
||||
loose-envify: "npm:^1.1.0"
|
||||
checksum: 10c0/283e8c5efcf37802c9d1ce767f302dd569dd97a70d9bb8c7be79a789b9902451e0d16334b05d73299b20f048cbc3c7d288bbbde10b701fa194e2089c237dbea3
|
||||
"react@npm:^19.0.0":
|
||||
version: 19.0.0
|
||||
resolution: "react@npm:19.0.0"
|
||||
checksum: 10c0/9cad8f103e8e3a16d15cb18a0d8115d8bd9f9e1ce3420310aea381eb42aa0a4f812cf047bb5441349257a05fba8a291515691e3cb51267279b2d2c3253f38471
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@@ -14404,12 +14352,10 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"scheduler@npm:^0.23.2":
|
||||
version: 0.23.2
|
||||
resolution: "scheduler@npm:0.23.2"
|
||||
dependencies:
|
||||
loose-envify: "npm:^1.1.0"
|
||||
checksum: 10c0/26383305e249651d4c58e6705d5f8425f153211aef95f15161c151f7b8de885f24751b377e4a0b3dd42cce09aad3f87a61dab7636859c0d89b7daf1a1e2a5c78
|
||||
"scheduler@npm:^0.25.0":
|
||||
version: 0.25.0
|
||||
resolution: "scheduler@npm:0.25.0"
|
||||
checksum: 10c0/a4bb1da406b613ce72c1299db43759526058fdcc413999c3c3e0db8956df7633acf395cb20eb2303b6a65d658d66b6585d344460abaee8080b4aa931f10eaafe
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
|
||||
Reference in New Issue
Block a user