@nocobase/ai 2.2.0-beta.8 → 2.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/document-loader/index.d.ts +7 -1
- package/lib/document-loader/index.js +9 -4
- package/lib/document-loader/loader.worker.js +30 -22
- package/lib/document-loader/xlsx.d.ts +1 -1
- package/lib/document-loader/xlsx.js +6 -5
- package/lib/tools-manager/index.d.ts +1 -0
- package/lib/tools-manager/index.js +1 -0
- package/package.json +7 -7
- package/src/__tests__/document-loader.test.ts +74 -0
- package/src/document-loader/index.ts +18 -4
- package/src/document-loader/loader.worker.ts +30 -24
- package/src/document-loader/xlsx.ts +6 -5
- package/src/tools-manager/index.ts +1 -0
|
@@ -7,4 +7,10 @@
|
|
|
7
7
|
* For more information, please refer to: https://www.nocobase.com/agreement.
|
|
8
8
|
*/
|
|
9
9
|
import { Document } from '@langchain/core/documents';
|
|
10
|
-
export
|
|
10
|
+
export type DocumentLoaderWorkerOptions = {
|
|
11
|
+
filePath: string;
|
|
12
|
+
mimeType?: string;
|
|
13
|
+
/** Timeout in milliseconds for the worker to complete. Defaults to 5 minutes. */
|
|
14
|
+
timeout?: number;
|
|
15
|
+
};
|
|
16
|
+
export declare const loadByWorker: (extname: string, options: DocumentLoaderWorkerOptions) => Promise<Document[]>;
|
|
@@ -42,13 +42,14 @@ __export(document_loader_exports, {
|
|
|
42
42
|
module.exports = __toCommonJS(document_loader_exports);
|
|
43
43
|
var import_node_worker_threads = require("node:worker_threads");
|
|
44
44
|
var import_node_path = __toESM(require("node:path"));
|
|
45
|
-
const
|
|
46
|
-
|
|
45
|
+
const DEFAULT_WORKER_TIMEOUT = 5 * 60 * 1e3;
|
|
46
|
+
const loadByWorker = /* @__PURE__ */ __name(async (extname, options) => {
|
|
47
47
|
const isTsRuntime = __filename.endsWith(".ts");
|
|
48
48
|
const workerPath = import_node_path.default.join(__dirname, `loader.worker.${isTsRuntime ? "ts" : "js"}`);
|
|
49
49
|
const worker = new import_node_worker_threads.Worker(workerPath, {
|
|
50
50
|
execArgv: isTsRuntime ? ["--require", "tsx/cjs"] : void 0
|
|
51
51
|
});
|
|
52
|
+
const timeout = options.timeout ?? DEFAULT_WORKER_TIMEOUT;
|
|
52
53
|
return new Promise((resolve, reject) => {
|
|
53
54
|
let settled = false;
|
|
54
55
|
const close = /* @__PURE__ */ __name((error, result) => {
|
|
@@ -56,12 +57,16 @@ const loadByWorker = /* @__PURE__ */ __name(async (extname, blob) => {
|
|
|
56
57
|
return;
|
|
57
58
|
}
|
|
58
59
|
settled = true;
|
|
60
|
+
clearTimeout(timer);
|
|
59
61
|
if (error) {
|
|
60
62
|
reject(error);
|
|
61
63
|
return;
|
|
62
64
|
}
|
|
63
65
|
resolve(result || []);
|
|
64
66
|
}, "close");
|
|
67
|
+
const timer = setTimeout(() => {
|
|
68
|
+
close(new Error(`Document loading timed out after ${Math.round(timeout / 1e3)}s`));
|
|
69
|
+
}, timeout);
|
|
65
70
|
worker.once("message", (payload) => {
|
|
66
71
|
if (payload == null ? void 0 : payload.error) {
|
|
67
72
|
close(new Error(payload.error));
|
|
@@ -77,8 +82,8 @@ const loadByWorker = /* @__PURE__ */ __name(async (extname, blob) => {
|
|
|
77
82
|
});
|
|
78
83
|
worker.postMessage({
|
|
79
84
|
extname,
|
|
80
|
-
|
|
81
|
-
|
|
85
|
+
filePath: options.filePath,
|
|
86
|
+
mimeType: options.mimeType
|
|
82
87
|
});
|
|
83
88
|
}).finally(() => {
|
|
84
89
|
worker.terminate().catch(() => void 0);
|
|
@@ -17,47 +17,54 @@ var import_text = require("./vendor/langchain/document_loaders/fs/text");
|
|
|
17
17
|
var import_csv = require("@langchain/community/document_loaders/fs/csv");
|
|
18
18
|
var import_xlsx = require("./xlsx");
|
|
19
19
|
var _a;
|
|
20
|
-
const loadPdf = /* @__PURE__ */ __name(async (
|
|
21
|
-
const loader = new import_pdf.PDFLoader(
|
|
22
|
-
|
|
20
|
+
const loadPdf = /* @__PURE__ */ __name(async (filePath) => {
|
|
21
|
+
const loader = new import_pdf.PDFLoader(filePath);
|
|
22
|
+
try {
|
|
23
|
+
return await loader.load();
|
|
24
|
+
} catch (error) {
|
|
25
|
+
const err = error;
|
|
26
|
+
if ((err == null ? void 0 : err.name) === "PasswordException" || /password/i.test(err == null ? void 0 : err.message)) {
|
|
27
|
+
throw new Error("The PDF file is password-protected and cannot be parsed. Please upload an unlocked version.");
|
|
28
|
+
}
|
|
29
|
+
throw error;
|
|
30
|
+
}
|
|
23
31
|
}, "loadPdf");
|
|
24
|
-
const loadDoc = /* @__PURE__ */ __name(async (
|
|
25
|
-
const loader = new import_docx.DocxLoader(
|
|
32
|
+
const loadDoc = /* @__PURE__ */ __name(async (filePath, type) => {
|
|
33
|
+
const loader = new import_docx.DocxLoader(filePath, { type });
|
|
26
34
|
return loader.load();
|
|
27
35
|
}, "loadDoc");
|
|
28
|
-
const
|
|
29
|
-
const loader = new import_pptx.PPTXLoader(
|
|
36
|
+
const loadPptx = /* @__PURE__ */ __name(async (filePath) => {
|
|
37
|
+
const loader = new import_pptx.PPTXLoader(filePath);
|
|
30
38
|
return loader.load();
|
|
31
|
-
}, "
|
|
32
|
-
const loadTxt = /* @__PURE__ */ __name(async (
|
|
33
|
-
const loader = new import_text.TextLoader(
|
|
39
|
+
}, "loadPptx");
|
|
40
|
+
const loadTxt = /* @__PURE__ */ __name(async (filePath) => {
|
|
41
|
+
const loader = new import_text.TextLoader(filePath);
|
|
34
42
|
return loader.load();
|
|
35
43
|
}, "loadTxt");
|
|
36
|
-
const loadCsv = /* @__PURE__ */ __name(async (
|
|
37
|
-
const loader = new import_csv.CSVLoader(
|
|
44
|
+
const loadCsv = /* @__PURE__ */ __name(async (filePath) => {
|
|
45
|
+
const loader = new import_csv.CSVLoader(filePath);
|
|
38
46
|
return loader.load();
|
|
39
47
|
}, "loadCsv");
|
|
40
48
|
const loadByExtname = /* @__PURE__ */ __name(async (payload) => {
|
|
41
|
-
const blob = new Blob([Buffer.from(payload.buffer)], { type: payload.mimeType ?? "application/octet-stream" });
|
|
42
49
|
switch (payload.extname) {
|
|
43
50
|
case ".pdf":
|
|
44
|
-
return loadPdf(
|
|
45
|
-
case ".ppt":
|
|
51
|
+
return loadPdf(payload.filePath);
|
|
46
52
|
case ".pptx":
|
|
47
|
-
return
|
|
53
|
+
return loadPptx(payload.filePath);
|
|
48
54
|
case ".doc":
|
|
49
|
-
return loadDoc(
|
|
55
|
+
return loadDoc(payload.filePath, "doc");
|
|
50
56
|
case ".docx":
|
|
51
|
-
return loadDoc(
|
|
57
|
+
return loadDoc(payload.filePath, "docx");
|
|
52
58
|
case ".csv":
|
|
53
|
-
return loadCsv(
|
|
59
|
+
return loadCsv(payload.filePath);
|
|
54
60
|
case ".xls":
|
|
55
61
|
case ".xlsx":
|
|
56
|
-
|
|
62
|
+
case ".xlsm":
|
|
63
|
+
return (0, import_xlsx.loadXlsx)(payload.filePath, payload.mimeType);
|
|
57
64
|
case ".json":
|
|
58
65
|
case ".md":
|
|
59
66
|
case ".txt":
|
|
60
|
-
return loadTxt(
|
|
67
|
+
return loadTxt(payload.filePath);
|
|
61
68
|
default:
|
|
62
69
|
return [];
|
|
63
70
|
}
|
|
@@ -75,8 +82,9 @@ const loadByExtname = /* @__PURE__ */ __name(async (payload) => {
|
|
|
75
82
|
};
|
|
76
83
|
(_a2 = import_node_worker_threads.parentPort) == null ? void 0 : _a2.postMessage(response);
|
|
77
84
|
} catch (error) {
|
|
85
|
+
const err = error;
|
|
78
86
|
const response = {
|
|
79
|
-
error:
|
|
87
|
+
error: (err == null ? void 0 : err.message) || String(error)
|
|
80
88
|
};
|
|
81
89
|
(_b = import_node_worker_threads.parentPort) == null ? void 0 : _b.postMessage(response);
|
|
82
90
|
}
|
|
@@ -7,4 +7,4 @@
|
|
|
7
7
|
* For more information, please refer to: https://www.nocobase.com/agreement.
|
|
8
8
|
*/
|
|
9
9
|
import { Document } from '@langchain/core/documents';
|
|
10
|
-
export declare const loadXlsx: (
|
|
10
|
+
export declare const loadXlsx: (filePath: string, mimeType?: string) => Promise<Document[]>;
|
|
@@ -41,6 +41,7 @@ __export(xlsx_exports, {
|
|
|
41
41
|
});
|
|
42
42
|
module.exports = __toCommonJS(xlsx_exports);
|
|
43
43
|
var import_documents = require("@langchain/core/documents");
|
|
44
|
+
var import_promises = require("node:fs/promises");
|
|
44
45
|
var XLSX = __toESM(require("xlsx"));
|
|
45
46
|
const normalizeCellValue = /* @__PURE__ */ __name((value) => {
|
|
46
47
|
if (value === void 0 || value === null) {
|
|
@@ -64,10 +65,10 @@ const sheetToLines = /* @__PURE__ */ __name((sheet) => {
|
|
|
64
65
|
});
|
|
65
66
|
return rows.map((row) => trimTrailingEmptyCells(Array.isArray(row) ? row : [])).filter((row) => row.length > 0).map((row) => row.map((cell) => normalizeCellValue(cell)).join(" ")).filter((line) => line.trim().length > 0);
|
|
66
67
|
}, "sheetToLines");
|
|
67
|
-
const loadXlsx = /* @__PURE__ */ __name(async (
|
|
68
|
-
const buffer = await
|
|
68
|
+
const loadXlsx = /* @__PURE__ */ __name(async (filePath, mimeType) => {
|
|
69
|
+
const buffer = await (0, import_promises.readFile)(filePath);
|
|
69
70
|
const workbook = XLSX.read(buffer, {
|
|
70
|
-
type: "
|
|
71
|
+
type: "buffer",
|
|
71
72
|
cellText: true
|
|
72
73
|
});
|
|
73
74
|
const documents = [];
|
|
@@ -84,8 +85,8 @@ const loadXlsx = /* @__PURE__ */ __name(async (blob) => {
|
|
|
84
85
|
new import_documents.Document({
|
|
85
86
|
pageContent: [`Sheet: ${sheetName}`, ...lines].join("\n"),
|
|
86
87
|
metadata: {
|
|
87
|
-
source:
|
|
88
|
-
blobType:
|
|
88
|
+
source: filePath,
|
|
89
|
+
blobType: mimeType,
|
|
89
90
|
sheetName,
|
|
90
91
|
sheetIndex: index
|
|
91
92
|
}
|
|
@@ -22,6 +22,7 @@ export declare class DefaultToolsManager implements ToolsManager {
|
|
|
22
22
|
}
|
|
23
23
|
export declare function defineTools(options: ToolsOptions): ToolsOptions;
|
|
24
24
|
export declare const SYSTEM_TOOLS: {
|
|
25
|
+
GET_SKILL: string;
|
|
25
26
|
WEB_SEARCH: string;
|
|
26
27
|
KNOWLEDGE_BASE: string;
|
|
27
28
|
WORK_FLOW_TASK_OUTPUT: string;
|
|
@@ -132,6 +132,7 @@ function defineTools(options) {
|
|
|
132
132
|
}
|
|
133
133
|
__name(defineTools, "defineTools");
|
|
134
134
|
const SYSTEM_TOOLS = {
|
|
135
|
+
GET_SKILL: "getSkill",
|
|
135
136
|
WEB_SEARCH: "subAgentWebSearch",
|
|
136
137
|
KNOWLEDGE_BASE: "knowledge-base-retrieve",
|
|
137
138
|
WORK_FLOW_TASK_OUTPUT: "aiEmployeeWorkflowTaskOutput"
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nocobase/ai",
|
|
3
|
-
"version": "2.2.0
|
|
3
|
+
"version": "2.2.0",
|
|
4
4
|
"description": "",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"main": "./lib/index.js",
|
|
@@ -17,17 +17,17 @@
|
|
|
17
17
|
"@langchain/mcp-adapters": "1.1.3",
|
|
18
18
|
"@langchain/ollama": "1.2.7",
|
|
19
19
|
"@langchain/openai": "1.4.7",
|
|
20
|
-
"@nocobase/data-source-manager": "2.2.0
|
|
21
|
-
"@nocobase/logger": "2.2.0
|
|
22
|
-
"@nocobase/resourcer": "2.2.0
|
|
23
|
-
"@nocobase/utils": "2.2.0
|
|
20
|
+
"@nocobase/data-source-manager": "2.2.0",
|
|
21
|
+
"@nocobase/logger": "2.2.0",
|
|
22
|
+
"@nocobase/resourcer": "2.2.0",
|
|
23
|
+
"@nocobase/utils": "2.2.0",
|
|
24
24
|
"d3-dsv": "2",
|
|
25
25
|
"fast-glob": "^3.3.2",
|
|
26
26
|
"flexsearch": "^0.8.2",
|
|
27
27
|
"gray-matter": "^4.0.3",
|
|
28
28
|
"langchain": "1.2.39",
|
|
29
29
|
"mammoth": "^1.10.0",
|
|
30
|
-
"officeparser": "^
|
|
30
|
+
"officeparser": "^6.0.4",
|
|
31
31
|
"pdf-parse": "^1.1.1",
|
|
32
32
|
"word-extractor": "^1.0.4",
|
|
33
33
|
"xlsx": "https://cdn.sheetjs.com/xlsx-0.20.3/xlsx-0.20.3.tgz"
|
|
@@ -37,5 +37,5 @@
|
|
|
37
37
|
"url": "git+https://github.com/nocobase/nocobase.git",
|
|
38
38
|
"directory": "packages/ai"
|
|
39
39
|
},
|
|
40
|
-
"gitHead": "
|
|
40
|
+
"gitHead": "d5052cae37177054c236f1bf7bba3aed6ef029d0"
|
|
41
41
|
}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This file is part of the NocoBase (R) project.
|
|
3
|
+
* Copyright (c) 2020-2024 NocoBase Co., Ltd.
|
|
4
|
+
* Authors: NocoBase Team.
|
|
5
|
+
*
|
|
6
|
+
* This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
|
|
7
|
+
* For more information, please refer to: https://www.nocobase.com/agreement.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import { loadByWorker } from '../document-loader';
|
|
11
|
+
import { mkdtemp, rm, writeFile } from 'node:fs/promises';
|
|
12
|
+
import os from 'node:os';
|
|
13
|
+
import path from 'node:path';
|
|
14
|
+
import * as XLSX from 'xlsx';
|
|
15
|
+
|
|
16
|
+
describe('Document loader worker', () => {
|
|
17
|
+
const tempDirs: string[] = [];
|
|
18
|
+
|
|
19
|
+
const createTempFile = async (filename: string, content: string | Buffer) => {
|
|
20
|
+
const tempDir = await mkdtemp(path.join(os.tmpdir(), 'nocobase-document-loader-test-'));
|
|
21
|
+
tempDirs.push(tempDir);
|
|
22
|
+
const filePath = path.join(tempDir, filename);
|
|
23
|
+
await writeFile(filePath, content);
|
|
24
|
+
return filePath;
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
afterEach(async () => {
|
|
28
|
+
await Promise.all(tempDirs.splice(0).map((tempDir) => rm(tempDir, { recursive: true, force: true })));
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
it('loads text files by path', async () => {
|
|
32
|
+
const filePath = await createTempFile('source.txt', 'hello knowledge base\nsecond line\n');
|
|
33
|
+
|
|
34
|
+
const documents = await loadByWorker('.txt', {
|
|
35
|
+
filePath,
|
|
36
|
+
mimeType: 'text/plain',
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
expect(documents).toHaveLength(1);
|
|
40
|
+
expect(documents[0].pageContent).toBe('hello knowledge base\nsecond line\n');
|
|
41
|
+
expect(documents[0].metadata.source).toBe(filePath);
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
it('loads xlsx files by path', async () => {
|
|
45
|
+
const worksheet = XLSX.utils.aoa_to_sheet([
|
|
46
|
+
['name', 'value'],
|
|
47
|
+
['alpha', 1],
|
|
48
|
+
]);
|
|
49
|
+
const workbook = XLSX.utils.book_new();
|
|
50
|
+
XLSX.utils.book_append_sheet(workbook, worksheet, 'Sheet1');
|
|
51
|
+
const buffer = XLSX.write(workbook, { type: 'buffer', bookType: 'xlsx' });
|
|
52
|
+
const filePath = await createTempFile('source.xlsx', buffer);
|
|
53
|
+
|
|
54
|
+
const documents = await loadByWorker('.xlsx', {
|
|
55
|
+
filePath,
|
|
56
|
+
mimeType: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
expect(documents).toHaveLength(1);
|
|
60
|
+
expect(documents[0].pageContent).toBe('Sheet: Sheet1\nname\tvalue\nalpha\t1');
|
|
61
|
+
expect(documents[0].metadata.source).toBe(filePath);
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
it('does not parse legacy ppt files', async () => {
|
|
65
|
+
const filePath = await createTempFile('source.ppt', 'legacy powerpoint content');
|
|
66
|
+
|
|
67
|
+
const documents = await loadByWorker('.ppt', {
|
|
68
|
+
filePath,
|
|
69
|
+
mimeType: 'application/vnd.ms-powerpoint',
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
expect(documents).toEqual([]);
|
|
73
|
+
});
|
|
74
|
+
});
|
|
@@ -11,13 +11,22 @@ import { Document } from '@langchain/core/documents';
|
|
|
11
11
|
import { Worker } from 'node:worker_threads';
|
|
12
12
|
import path from 'node:path';
|
|
13
13
|
|
|
14
|
-
export
|
|
15
|
-
|
|
14
|
+
export type DocumentLoaderWorkerOptions = {
|
|
15
|
+
filePath: string;
|
|
16
|
+
mimeType?: string;
|
|
17
|
+
/** Timeout in milliseconds for the worker to complete. Defaults to 5 minutes. */
|
|
18
|
+
timeout?: number;
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
const DEFAULT_WORKER_TIMEOUT = 5 * 60 * 1000;
|
|
22
|
+
|
|
23
|
+
export const loadByWorker = async (extname: string, options: DocumentLoaderWorkerOptions): Promise<Document[]> => {
|
|
16
24
|
const isTsRuntime = __filename.endsWith('.ts');
|
|
17
25
|
const workerPath = path.join(__dirname, `loader.worker.${isTsRuntime ? 'ts' : 'js'}`);
|
|
18
26
|
const worker = new Worker(workerPath, {
|
|
19
27
|
execArgv: isTsRuntime ? ['--require', 'tsx/cjs'] : undefined,
|
|
20
28
|
});
|
|
29
|
+
const timeout = options.timeout ?? DEFAULT_WORKER_TIMEOUT;
|
|
21
30
|
return new Promise<Document[]>((resolve, reject) => {
|
|
22
31
|
let settled = false;
|
|
23
32
|
const close = (error?: Error, result?: Document[]) => {
|
|
@@ -25,6 +34,7 @@ export const loadByWorker = async (extname: string, blob: Blob): Promise<Documen
|
|
|
25
34
|
return;
|
|
26
35
|
}
|
|
27
36
|
settled = true;
|
|
37
|
+
clearTimeout(timer);
|
|
28
38
|
if (error) {
|
|
29
39
|
reject(error);
|
|
30
40
|
return;
|
|
@@ -32,6 +42,10 @@ export const loadByWorker = async (extname: string, blob: Blob): Promise<Documen
|
|
|
32
42
|
resolve(result || []);
|
|
33
43
|
};
|
|
34
44
|
|
|
45
|
+
const timer = setTimeout(() => {
|
|
46
|
+
close(new Error(`Document loading timed out after ${Math.round(timeout / 1000)}s`));
|
|
47
|
+
}, timeout);
|
|
48
|
+
|
|
35
49
|
worker.once('message', (payload: { documents?: Document[]; error?: string }) => {
|
|
36
50
|
if (payload?.error) {
|
|
37
51
|
close(new Error(payload.error));
|
|
@@ -48,8 +62,8 @@ export const loadByWorker = async (extname: string, blob: Blob): Promise<Documen
|
|
|
48
62
|
|
|
49
63
|
worker.postMessage({
|
|
50
64
|
extname,
|
|
51
|
-
|
|
52
|
-
|
|
65
|
+
filePath: options.filePath,
|
|
66
|
+
mimeType: options.mimeType,
|
|
53
67
|
});
|
|
54
68
|
}).finally(() => {
|
|
55
69
|
worker.terminate().catch(() => undefined);
|
|
@@ -19,7 +19,7 @@ import { loadXlsx } from './xlsx';
|
|
|
19
19
|
type ParsePayload = {
|
|
20
20
|
extname: string;
|
|
21
21
|
mimeType?: string;
|
|
22
|
-
|
|
22
|
+
filePath: string;
|
|
23
23
|
};
|
|
24
24
|
|
|
25
25
|
type WorkerResponse = {
|
|
@@ -27,54 +27,59 @@ type WorkerResponse = {
|
|
|
27
27
|
error?: string;
|
|
28
28
|
};
|
|
29
29
|
|
|
30
|
-
const loadPdf = async (
|
|
31
|
-
const loader = new PDFLoader(
|
|
32
|
-
|
|
30
|
+
const loadPdf = async (filePath: string): Promise<Document[]> => {
|
|
31
|
+
const loader = new PDFLoader(filePath);
|
|
32
|
+
try {
|
|
33
|
+
return await loader.load();
|
|
34
|
+
} catch (error) {
|
|
35
|
+
const err = error as Error;
|
|
36
|
+
if (err?.name === 'PasswordException' || /password/i.test(err?.message)) {
|
|
37
|
+
throw new Error('The PDF file is password-protected and cannot be parsed. Please upload an unlocked version.');
|
|
38
|
+
}
|
|
39
|
+
throw error;
|
|
40
|
+
}
|
|
33
41
|
};
|
|
34
42
|
|
|
35
|
-
const loadDoc = async (
|
|
36
|
-
const loader = new DocxLoader(
|
|
43
|
+
const loadDoc = async (filePath: string, type: 'docx' | 'doc'): Promise<Document[]> => {
|
|
44
|
+
const loader = new DocxLoader(filePath, { type });
|
|
37
45
|
return loader.load();
|
|
38
46
|
};
|
|
39
47
|
|
|
40
|
-
const
|
|
41
|
-
const loader = new PPTXLoader(
|
|
48
|
+
const loadPptx = async (filePath: string): Promise<Document[]> => {
|
|
49
|
+
const loader = new PPTXLoader(filePath);
|
|
42
50
|
return loader.load();
|
|
43
51
|
};
|
|
44
52
|
|
|
45
|
-
const loadTxt = async (
|
|
46
|
-
const loader = new TextLoader(
|
|
53
|
+
const loadTxt = async (filePath: string): Promise<Document[]> => {
|
|
54
|
+
const loader = new TextLoader(filePath);
|
|
47
55
|
return loader.load();
|
|
48
56
|
};
|
|
49
57
|
|
|
50
|
-
const loadCsv = async (
|
|
51
|
-
const loader = new CSVLoader(
|
|
58
|
+
const loadCsv = async (filePath: string): Promise<Document[]> => {
|
|
59
|
+
const loader = new CSVLoader(filePath);
|
|
52
60
|
return loader.load();
|
|
53
61
|
};
|
|
54
62
|
|
|
55
63
|
const loadByExtname = async (payload: ParsePayload): Promise<Document[]> => {
|
|
56
|
-
// @ts-ignore
|
|
57
|
-
const blob = new Blob([Buffer.from(payload.buffer)], { type: payload.mimeType ?? 'application/octet-stream' });
|
|
58
|
-
|
|
59
64
|
switch (payload.extname) {
|
|
60
65
|
case '.pdf':
|
|
61
|
-
return loadPdf(
|
|
62
|
-
case '.ppt':
|
|
66
|
+
return loadPdf(payload.filePath);
|
|
63
67
|
case '.pptx':
|
|
64
|
-
return
|
|
68
|
+
return loadPptx(payload.filePath);
|
|
65
69
|
case '.doc':
|
|
66
|
-
return loadDoc(
|
|
70
|
+
return loadDoc(payload.filePath, 'doc');
|
|
67
71
|
case '.docx':
|
|
68
|
-
return loadDoc(
|
|
72
|
+
return loadDoc(payload.filePath, 'docx');
|
|
69
73
|
case '.csv':
|
|
70
|
-
return loadCsv(
|
|
74
|
+
return loadCsv(payload.filePath);
|
|
71
75
|
case '.xls':
|
|
72
76
|
case '.xlsx':
|
|
73
|
-
|
|
77
|
+
case '.xlsm':
|
|
78
|
+
return loadXlsx(payload.filePath, payload.mimeType);
|
|
74
79
|
case '.json':
|
|
75
80
|
case '.md':
|
|
76
81
|
case '.txt':
|
|
77
|
-
return loadTxt(
|
|
82
|
+
return loadTxt(payload.filePath);
|
|
78
83
|
default:
|
|
79
84
|
return [];
|
|
80
85
|
}
|
|
@@ -92,8 +97,9 @@ parentPort?.on('message', async (payload: ParsePayload) => {
|
|
|
92
97
|
};
|
|
93
98
|
parentPort?.postMessage(response);
|
|
94
99
|
} catch (error) {
|
|
100
|
+
const err = error as Error;
|
|
95
101
|
const response: WorkerResponse = {
|
|
96
|
-
error:
|
|
102
|
+
error: err?.message || String(error),
|
|
97
103
|
};
|
|
98
104
|
parentPort?.postMessage(response);
|
|
99
105
|
}
|
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
10
|
import { Document } from '@langchain/core/documents';
|
|
11
|
+
import { readFile } from 'node:fs/promises';
|
|
11
12
|
import * as XLSX from 'xlsx';
|
|
12
13
|
|
|
13
14
|
const normalizeCellValue = (value: unknown): string => {
|
|
@@ -43,10 +44,10 @@ const sheetToLines = (sheet: XLSX.WorkSheet): string[] => {
|
|
|
43
44
|
.filter((line) => line.trim().length > 0);
|
|
44
45
|
};
|
|
45
46
|
|
|
46
|
-
export const loadXlsx = async (
|
|
47
|
-
const buffer = await
|
|
47
|
+
export const loadXlsx = async (filePath: string, mimeType?: string): Promise<Document[]> => {
|
|
48
|
+
const buffer = await readFile(filePath);
|
|
48
49
|
const workbook = XLSX.read(buffer, {
|
|
49
|
-
type: '
|
|
50
|
+
type: 'buffer',
|
|
50
51
|
cellText: true,
|
|
51
52
|
});
|
|
52
53
|
|
|
@@ -69,8 +70,8 @@ export const loadXlsx = async (blob: Blob): Promise<Document[]> => {
|
|
|
69
70
|
new Document({
|
|
70
71
|
pageContent: [`Sheet: ${sheetName}`, ...lines].join('\n'),
|
|
71
72
|
metadata: {
|
|
72
|
-
source:
|
|
73
|
-
blobType:
|
|
73
|
+
source: filePath,
|
|
74
|
+
blobType: mimeType,
|
|
74
75
|
sheetName,
|
|
75
76
|
sheetIndex: index,
|
|
76
77
|
},
|
|
@@ -106,6 +106,7 @@ export function defineTools(options: ToolsOptions) {
|
|
|
106
106
|
}
|
|
107
107
|
|
|
108
108
|
export const SYSTEM_TOOLS = {
|
|
109
|
+
GET_SKILL: 'getSkill',
|
|
109
110
|
WEB_SEARCH: 'subAgentWebSearch',
|
|
110
111
|
KNOWLEDGE_BASE: 'knowledge-base-retrieve',
|
|
111
112
|
WORK_FLOW_TASK_OUTPUT: 'aiEmployeeWorkflowTaskOutput',
|