@fgbg/mdocs 0.8.25 → 1.1.1
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/agent-skills/changelog/SKILL.md +50 -1
- package/agent-skills/index.json +8 -1
- package/agent-skills/usage-knowledge-graph/SKILL.md +126 -0
- package/agent-skills/usage-onboarding-ai/SKILL.md +36 -5
- package/dist/server/agent/Agent/run.js +60 -34
- package/dist/server/agent/Agent/run.js.map +1 -1
- package/dist/server/agent/Agent/tools-documents.js +1 -1
- package/dist/server/agent/Agent/tools-documents.js.map +1 -1
- package/dist/server/agent/Config/config.js +234 -64
- package/dist/server/agent/Config/config.js.map +1 -1
- package/dist/server/agent/Config/config.test.js +109 -0
- package/dist/server/agent/Config/config.test.js.map +1 -0
- package/dist/server/app.js +2 -0
- package/dist/server/app.js.map +1 -1
- package/dist/server/db/repositories/agent-model-config.repo.js +58 -27
- package/dist/server/db/repositories/agent-model-config.repo.js.map +1 -1
- package/dist/server/db/schema.js +96 -1
- package/dist/server/db/schema.js.map +1 -1
- package/dist/server/documents/build-graph.e2e.test.js +65 -0
- package/dist/server/documents/build-graph.e2e.test.js.map +1 -0
- package/dist/server/documents/document.service.js +34 -2
- package/dist/server/documents/document.service.js.map +1 -1
- package/dist/server/documents/graph/change-ratio.js +29 -0
- package/dist/server/documents/graph/change-ratio.js.map +1 -0
- package/dist/server/documents/graph/change-ratio.test.js +38 -0
- package/dist/server/documents/graph/change-ratio.test.js.map +1 -0
- package/dist/server/documents/graph/graph-agent.integration.test.js +95 -0
- package/dist/server/documents/graph/graph-agent.integration.test.js.map +1 -0
- package/dist/server/documents/graph/graph-agent.js +185 -0
- package/dist/server/documents/graph/graph-agent.js.map +1 -0
- package/dist/server/documents/graph/graph-file.js +58 -0
- package/dist/server/documents/graph/graph-file.js.map +1 -0
- package/dist/server/documents/graph/graph-file.test.js +28 -0
- package/dist/server/documents/graph/graph-file.test.js.map +1 -0
- package/dist/server/documents/graph/index.js +183 -0
- package/dist/server/documents/graph/index.js.map +1 -0
- package/dist/server/documents/graph/lifecycle.js +104 -0
- package/dist/server/documents/graph/lifecycle.js.map +1 -0
- package/dist/server/documents/graph/llm-chains.js +135 -0
- package/dist/server/documents/graph/llm-chains.js.map +1 -0
- package/dist/server/documents/graph/llm-utils.js +19 -0
- package/dist/server/documents/graph/llm-utils.js.map +1 -0
- package/dist/server/documents/graph/llm-utils.test.js +34 -0
- package/dist/server/documents/graph/llm-utils.test.js.map +1 -0
- package/dist/server/documents/graph/tools/concept-relations.tool.js +49 -0
- package/dist/server/documents/graph/tools/concept-relations.tool.js.map +1 -0
- package/dist/server/documents/graph/tools/extract-knowledge-points.tool.js +45 -0
- package/dist/server/documents/graph/tools/extract-knowledge-points.tool.js.map +1 -0
- package/dist/server/documents/graph/tools/generate-contains.tool.js +41 -0
- package/dist/server/documents/graph/tools/generate-contains.tool.js.map +1 -0
- package/dist/server/documents/graph/tools/induce-concepts.tool.js +43 -0
- package/dist/server/documents/graph/tools/induce-concepts.tool.js.map +1 -0
- package/dist/server/documents/graph/types.js +12 -0
- package/dist/server/documents/graph/types.js.map +1 -0
- package/dist/server/documents/graph/utils.js +41 -0
- package/dist/server/documents/graph/utils.js.map +1 -0
- package/dist/server/documents/graph/utils.test.js +87 -0
- package/dist/server/documents/graph/utils.test.js.map +1 -0
- package/dist/server/documents/graph-cache-io.js +254 -0
- package/dist/server/documents/graph-cache-io.js.map +1 -0
- package/dist/server/documents/graph-lifecycle.js +19 -0
- package/dist/server/documents/graph-lifecycle.js.map +1 -0
- package/dist/server/documents/graph-task.js +232 -0
- package/dist/server/documents/graph-task.js.map +1 -0
- package/dist/server/documents/graph.integration.test.js +213 -0
- package/dist/server/documents/graph.integration.test.js.map +1 -0
- package/dist/server/documents/graph.service.js +296 -0
- package/dist/server/documents/graph.service.js.map +1 -0
- package/dist/server/documents/markdown-to-lexical.js +111 -13
- package/dist/server/documents/markdown-to-lexical.js.map +1 -1
- package/dist/server/documents/markdown-to-lexical.test.js +37 -0
- package/dist/server/documents/markdown-to-lexical.test.js.map +1 -1
- package/dist/server/documents/tree.service.js +12 -6
- package/dist/server/documents/tree.service.js.map +1 -1
- package/dist/server/migrations/003-folder-desc-file-type.js +43 -0
- package/dist/server/migrations/003-folder-desc-file-type.js.map +1 -0
- package/dist/server/migrations/004-api-key-to-secrets.js +90 -0
- package/dist/server/migrations/004-api-key-to-secrets.js.map +1 -0
- package/dist/server/migrations/004-folder-desc-id.js +98 -0
- package/dist/server/migrations/004-folder-desc-id.js.map +1 -0
- package/dist/server/migrations/005-special-file-id-format.js +124 -0
- package/dist/server/migrations/005-special-file-id-format.js.map +1 -0
- package/dist/server/routes/agent.routes.js +69 -31
- package/dist/server/routes/agent.routes.js.map +1 -1
- package/dist/server/routes/assets.routes.js +73 -62
- package/dist/server/routes/assets.routes.js.map +1 -1
- package/dist/server/routes/assets.routes.upload.test.js +28 -0
- package/dist/server/routes/assets.routes.upload.test.js.map +1 -0
- package/dist/server/routes/documents.routes.js +1 -1
- package/dist/server/routes/documents.routes.js.map +1 -1
- package/dist/server/routes/folders.routes.js +2 -2
- package/dist/server/routes/folders.routes.js.map +1 -1
- package/dist/server/routes/graph.routes.js +112 -0
- package/dist/server/routes/graph.routes.js.map +1 -0
- package/dist/server/routes/tree.routes.js +1 -1
- package/dist/server/routes/tree.routes.js.map +1 -1
- package/dist/server/secrets/secrets-store.js +93 -0
- package/dist/server/secrets/secrets-store.js.map +1 -0
- package/dist/server/storage/paths.js +0 -1
- package/dist/server/storage/paths.js.map +1 -1
- package/dist/server/task-queue/TaskQueue.js +258 -0
- package/dist/server/task-queue/TaskQueue.js.map +1 -0
- package/dist/server/task-queue/TaskQueue.test.js +136 -0
- package/dist/server/task-queue/TaskQueue.test.js.map +1 -0
- package/dist/server/task-queue/index.js +18 -0
- package/dist/server/task-queue/index.js.map +1 -0
- package/dist/server/task-queue/log-store.js +84 -0
- package/dist/server/task-queue/log-store.js.map +1 -0
- package/dist/server/task-queue/types.js +5 -0
- package/dist/server/task-queue/types.js.map +1 -0
- package/dist/shared/docPath.js +3 -2
- package/dist/shared/docPath.js.map +1 -1
- package/dist/shared/file-types.js +35 -0
- package/dist/shared/file-types.js.map +1 -0
- package/dist/shared/graph-files.js +31 -0
- package/dist/shared/graph-files.js.map +1 -0
- package/dist/web/assets/AgentChatPanel-KiTv5uCF.js +6 -0
- package/dist/web/assets/AgentSkillFormCard-CP-HN--U.js +6 -0
- package/dist/web/assets/AiWriteWorkbench-0wEf6qur.js +7 -0
- package/dist/web/assets/{DiagramEditor-NtNY3sZL-DqPXDJHY.js → DiagramEditor-NtNY3sZL-XBBS6Mu4.js} +1 -1
- package/dist/web/assets/DocumentEditor-CeaspJgX.js +26 -0
- package/dist/web/assets/{MergeView-Y3zB8V5p.js → MergeView-y24LKycd.js} +1 -1
- package/dist/web/assets/PlaygroundPage-CYx8X23_.js +8 -0
- package/dist/web/assets/SettingsPage-Bor0wh4z.js +1 -0
- package/dist/web/assets/{Toolbar-B36NxaTc.js → Toolbar-uyj1sA_r.js} +16 -21
- package/dist/web/assets/{VisitorPickerModal-drnOuPLP.js → VisitorPickerModal-DljB4USS.js} +1 -1
- package/dist/web/assets/{copy-CX8GOyUb.js → copy-DZj0Bj86.js} +1 -1
- package/dist/web/assets/diagram-CT58wBdU.js +5772 -0
- package/dist/web/assets/{editor-ONzd_YnO.js → editor-CL03se2B.js} +1 -1
- package/dist/web/assets/index-C4ESYs7f.css +1 -0
- package/dist/web/assets/index-CqUWQ28V.js +248 -0
- package/dist/web/assets/{meta2d-D3b5RRN8.js → meta2d-1-g23JOU.js} +1 -1
- package/dist/web/assets/{meta2dEngine-BD2XbzaV-CCgjRlVJ.js → meta2dEngine-BD2XbzaV-D2yFsZ_P.js} +1 -1
- package/dist/web/assets/{motion-92iQWeIW.js → motion-DX3HNq_4.js} +2 -2
- package/dist/web/assets/{plus-BWV299MC.js → plus-Bcg3ots1.js} +1 -1
- package/dist/web/assets/react-kYvt_3tR.js +2122 -0
- package/dist/web/assets/react-vendor-BuABiQkA.js +242 -0
- package/dist/web/assets/ui-BQStT3dY.js +3116 -0
- package/dist/web/index.html +6 -5
- package/package.json +3 -2
- package/dist/web/assets/AgentChatPanel-BTCyf9Ww.js +0 -1
- package/dist/web/assets/AgentSkillFormCard-CAD6QqQ0.js +0 -6
- package/dist/web/assets/AiWriteWorkbench-PVv90TJS.js +0 -7
- package/dist/web/assets/DocumentEditor-zNIJgxe0.js +0 -21
- package/dist/web/assets/PlaygroundPage-DAaEm887.js +0 -8
- package/dist/web/assets/SettingsPage-DhdiNEhO.js +0 -1
- package/dist/web/assets/diagram-3lhA7FYR.js +0 -6257
- package/dist/web/assets/index-DgM2rYI-.js +0 -185
- package/dist/web/assets/index-S_lCknAk.css +0 -1
- package/dist/web/assets/react-BUhFwPCj.js +0 -2382
- package/dist/web/assets/react-vendor-BJFXgntS.js +0 -242
- package/dist/web/assets/ui-06fxEgif.js +0 -3126
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 图谱缓存生命周期:与 document.service 主链路解耦。
|
|
3
|
+
* 主链路只 schedule;隐藏文件 IO 全在本模块 + graph.service 导出函数。
|
|
4
|
+
*/
|
|
5
|
+
import { getDb } from "../../db/connection.js";
|
|
6
|
+
import { findDocumentById } from "../../db/repositories/document.repo.js";
|
|
7
|
+
import { findCommitById } from "../../db/repositories/commit.repo.js";
|
|
8
|
+
import { readCommitBlob, readDocument } from "../../storage/file-store.js";
|
|
9
|
+
import { extractPlainTextFromLexical } from "../lexical-text.js";
|
|
10
|
+
import { changeRatio, DEFAULT_GRAPH_DIRTY_RATIO, } from "./change-ratio.js";
|
|
11
|
+
import { deleteArticleGraphCache, readArticleGraphFile, readDirGraphFile, readDomainGraphFile, writeArticleGraphFile, writeDirGraphFile, writeDomainGraphFile, } from "../graph-cache-io.js";
|
|
12
|
+
export function scheduleGraphLifecycle(task) {
|
|
13
|
+
setImmediate(() => {
|
|
14
|
+
void task().catch((err) => {
|
|
15
|
+
console.warn("[graph-lifecycle]", err);
|
|
16
|
+
});
|
|
17
|
+
});
|
|
18
|
+
}
|
|
19
|
+
/** 从 folderId 自身起标 dirty,再沿 parent_id 向上;最后域图 */
|
|
20
|
+
export async function markAncestorsDirty(params) {
|
|
21
|
+
let p = params.folderId;
|
|
22
|
+
const db = getDb();
|
|
23
|
+
while (p != null) {
|
|
24
|
+
const file = readDirGraphFile(p);
|
|
25
|
+
if (file) {
|
|
26
|
+
file.meta.dirty = true;
|
|
27
|
+
writeDirGraphFile(p, file);
|
|
28
|
+
}
|
|
29
|
+
const row = findDocumentById(db, p);
|
|
30
|
+
p = row?.parent_id ?? null;
|
|
31
|
+
}
|
|
32
|
+
const domainFile = readDomainGraphFile(params.domainId);
|
|
33
|
+
if (domainFile) {
|
|
34
|
+
domainFile.meta.dirty = true;
|
|
35
|
+
writeDomainGraphFile(params.domainId, domainFile);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
export async function onArticleDeleted(params) {
|
|
39
|
+
await markAncestorsDirty({
|
|
40
|
+
domainId: params.domainId,
|
|
41
|
+
folderId: params.parentId,
|
|
42
|
+
});
|
|
43
|
+
deleteArticleGraphCache(params.documentId);
|
|
44
|
+
}
|
|
45
|
+
export async function onArticleMoved(params) {
|
|
46
|
+
await markAncestorsDirty({
|
|
47
|
+
domainId: params.domainId,
|
|
48
|
+
folderId: params.oldParentId,
|
|
49
|
+
});
|
|
50
|
+
await markAncestorsDirty({
|
|
51
|
+
domainId: params.domainId,
|
|
52
|
+
folderId: params.newParentId,
|
|
53
|
+
});
|
|
54
|
+
deleteArticleGraphCache(params.documentId);
|
|
55
|
+
}
|
|
56
|
+
export async function onArticlePublished(params) {
|
|
57
|
+
const cached = readArticleGraphFile(params.documentId);
|
|
58
|
+
if (!cached)
|
|
59
|
+
return;
|
|
60
|
+
const oldLexical = readLexicalAtCommit(params.documentId, cached.meta.commitId);
|
|
61
|
+
const newLexical = readCurrentLexical(params.documentId);
|
|
62
|
+
if (oldLexical == null || newLexical == null)
|
|
63
|
+
return;
|
|
64
|
+
const ratio = changeRatio(extractPlainTextFromLexical(oldLexical), extractPlainTextFromLexical(newLexical));
|
|
65
|
+
if (ratio < DEFAULT_GRAPH_DIRTY_RATIO)
|
|
66
|
+
return;
|
|
67
|
+
cached.meta.dirty = true;
|
|
68
|
+
writeArticleGraphFile(params.documentId, cached);
|
|
69
|
+
await markAncestorsDirty({
|
|
70
|
+
domainId: params.domainId,
|
|
71
|
+
folderId: params.parentId,
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
export async function onFolderDeleted(params) {
|
|
75
|
+
await markAncestorsDirty({
|
|
76
|
+
domainId: params.domainId,
|
|
77
|
+
folderId: params.parentId,
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
function readCurrentLexical(documentId) {
|
|
81
|
+
const db = getDb();
|
|
82
|
+
const doc = findDocumentById(db, documentId);
|
|
83
|
+
if (!doc)
|
|
84
|
+
return null;
|
|
85
|
+
try {
|
|
86
|
+
return readDocument(doc.domain_id, doc.relative_path).content;
|
|
87
|
+
}
|
|
88
|
+
catch {
|
|
89
|
+
return null;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
function readLexicalAtCommit(documentId, commitId) {
|
|
93
|
+
const db = getDb();
|
|
94
|
+
const commit = findCommitById(db, commitId);
|
|
95
|
+
if (!commit || commit.document_id !== documentId)
|
|
96
|
+
return null;
|
|
97
|
+
try {
|
|
98
|
+
return readCommitBlob(commit.blob_ref);
|
|
99
|
+
}
|
|
100
|
+
catch {
|
|
101
|
+
return null;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
//# sourceMappingURL=lifecycle.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lifecycle.js","sourceRoot":"","sources":["../../../../src/server/documents/graph/lifecycle.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,EAAE,KAAK,EAAE,MAAM,wBAAwB,CAAC;AAC/C,OAAO,EAAE,gBAAgB,EAAE,MAAM,wCAAwC,CAAC;AAC1E,OAAO,EAAE,cAAc,EAAE,MAAM,sCAAsC,CAAC;AACtE,OAAO,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAC3E,OAAO,EAAE,2BAA2B,EAAE,MAAM,oBAAoB,CAAC;AACjE,OAAO,EACL,WAAW,EACX,yBAAyB,GAC1B,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EACL,uBAAuB,EACvB,oBAAoB,EACpB,gBAAgB,EAChB,mBAAmB,EACnB,qBAAqB,EACrB,iBAAiB,EACjB,oBAAoB,GACrB,MAAM,sBAAsB,CAAC;AAE9B,MAAM,UAAU,sBAAsB,CAAC,IAAyB;IAC9D,YAAY,CAAC,GAAG,EAAE;QAChB,KAAK,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;YACxB,OAAO,CAAC,IAAI,CAAC,mBAAmB,EAAE,GAAG,CAAC,CAAC;QACzC,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC;AAED,iDAAiD;AACjD,MAAM,CAAC,KAAK,UAAU,kBAAkB,CAAC,MAGxC;IACC,IAAI,CAAC,GAAkB,MAAM,CAAC,QAAQ,CAAC;IACvC,MAAM,EAAE,GAAG,KAAK,EAAE,CAAC;IACnB,OAAO,CAAC,IAAI,IAAI,EAAE,CAAC;QACjB,MAAM,IAAI,GAAG,gBAAgB,CAAC,CAAC,CAAC,CAAC;QACjC,IAAI,IAAI,EAAE,CAAC;YACT,IAAI,CAAC,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC;YACvB,iBAAiB,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC;QAC7B,CAAC;QACD,MAAM,GAAG,GAAG,gBAAgB,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC;QACpC,CAAC,GAAG,GAAG,EAAE,SAAS,IAAI,IAAI,CAAC;IAC7B,CAAC;IACD,MAAM,UAAU,GAAG,mBAAmB,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;IACxD,IAAI,UAAU,EAAE,CAAC;QACf,UAAU,CAAC,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC;QAC7B,oBAAoB,CAAC,MAAM,CAAC,QAAQ,EAAE,UAAU,CAAC,CAAC;IACpD,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,gBAAgB,CAAC,MAItC;IACC,MAAM,kBAAkB,CAAC;QACvB,QAAQ,EAAE,MAAM,CAAC,QAAQ;QACzB,QAAQ,EAAE,MAAM,CAAC,QAAQ;KAC1B,CAAC,CAAC;IACH,uBAAuB,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;AAC7C,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,MAKpC;IACC,MAAM,kBAAkB,CAAC;QACvB,QAAQ,EAAE,MAAM,CAAC,QAAQ;QACzB,QAAQ,EAAE,MAAM,CAAC,WAAW;KAC7B,CAAC,CAAC;IACH,MAAM,kBAAkB,CAAC;QACvB,QAAQ,EAAE,MAAM,CAAC,QAAQ;QACzB,QAAQ,EAAE,MAAM,CAAC,WAAW;KAC7B,CAAC,CAAC;IACH,uBAAuB,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;AAC7C,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,kBAAkB,CAAC,MAIxC;IACC,MAAM,MAAM,GAAG,oBAAoB,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;IACvD,IAAI,CAAC,MAAM;QAAE,OAAO;IAEpB,MAAM,UAAU,GAAG,mBAAmB,CAAC,MAAM,CAAC,UAAU,EAAE,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IAChF,MAAM,UAAU,GAAG,kBAAkB,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;IACzD,IAAI,UAAU,IAAI,IAAI,IAAI,UAAU,IAAI,IAAI;QAAE,OAAO;IAErD,MAAM,KAAK,GAAG,WAAW,CACvB,2BAA2B,CAAC,UAAU,CAAC,EACvC,2BAA2B,CAAC,UAAU,CAAC,CACxC,CAAC;IACF,IAAI,KAAK,GAAG,yBAAyB;QAAE,OAAO;IAE9C,MAAM,CAAC,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC;IACzB,qBAAqB,CAAC,MAAM,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC;IACjD,MAAM,kBAAkB,CAAC;QACvB,QAAQ,EAAE,MAAM,CAAC,QAAQ;QACzB,QAAQ,EAAE,MAAM,CAAC,QAAQ;KAC1B,CAAC,CAAC;AACL,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,MAGrC;IACC,MAAM,kBAAkB,CAAC;QACvB,QAAQ,EAAE,MAAM,CAAC,QAAQ;QACzB,QAAQ,EAAE,MAAM,CAAC,QAAQ;KAC1B,CAAC,CAAC;AACL,CAAC;AAED,SAAS,kBAAkB,CAAC,UAAkB;IAC5C,MAAM,EAAE,GAAG,KAAK,EAAE,CAAC;IACnB,MAAM,GAAG,GAAG,gBAAgB,CAAC,EAAE,EAAE,UAAU,CAAC,CAAC;IAC7C,IAAI,CAAC,GAAG;QAAE,OAAO,IAAI,CAAC;IACtB,IAAI,CAAC;QACH,OAAO,YAAY,CAAC,GAAG,CAAC,SAAS,EAAE,GAAG,CAAC,aAAa,CAAC,CAAC,OAAO,CAAC;IAChE,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,SAAS,mBAAmB,CAAC,UAAkB,EAAE,QAAgB;IAC/D,MAAM,EAAE,GAAG,KAAK,EAAE,CAAC;IACnB,MAAM,MAAM,GAAG,cAAc,CAAC,EAAE,EAAE,QAAQ,CAAC,CAAC;IAC5C,IAAI,CAAC,MAAM,IAAI,MAAM,CAAC,WAAW,KAAK,UAAU;QAAE,OAAO,IAAI,CAAC;IAC9D,IAAI,CAAC;QACH,OAAO,cAAc,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;IACzC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 三条 AI 链路 —— 基于 Tool 方式输出结构化结果。
|
|
3
|
+
*
|
|
4
|
+
* 每条链路都有「正常 tool + 降级 tool」,AI 二选一调用。
|
|
5
|
+
* 外部接口统一返回正常数据(降级时返回空数组,外部不感知降级)。
|
|
6
|
+
*
|
|
7
|
+
* 1. extractDocNodes — 文章 → doc 节点
|
|
8
|
+
* 2. induceConceptNodes — doc 节点 → concept 节点
|
|
9
|
+
* 3. generateContains — 顶层节点 → contains 关系
|
|
10
|
+
*/
|
|
11
|
+
import { runToolExtractionWithFallback } from './graph-agent.js';
|
|
12
|
+
import { extractKnowledgePointsTool, noKnowledgePointsTool, } from './tools/extract-knowledge-points.tool.js';
|
|
13
|
+
import { induceConceptsTool, noConceptsTool, } from './tools/induce-concepts.tool.js';
|
|
14
|
+
import { generateContainsTool, noContainsRelationsTool, } from './tools/generate-contains.tool.js';
|
|
15
|
+
import { conceptRelationsTool, noConceptRelationsTool, } from './tools/concept-relations.tool.js';
|
|
16
|
+
// ========== 链路 1:从文章提取 doc 节点 ==========
|
|
17
|
+
const EXTRACT_DOC_NODES_SYSTEM = `你是一个知识提取专家。你的任务是从给定的 Markdown 文章中提取若干个独立的知识要点。
|
|
18
|
+
|
|
19
|
+
要求:
|
|
20
|
+
1. 每个知识要点是一个独立的知识点(概念、规则、方法等)
|
|
21
|
+
2. 提取 3-10 个要点,粒度适中,不要太细也不要太粗
|
|
22
|
+
3. 每个要点必须包含 label、description、confidence
|
|
23
|
+
4. 如果是概念定义,可以填写 definition 字段
|
|
24
|
+
5. 如果要点对应文章中的某个小标题,填写 heading 字段
|
|
25
|
+
6. 分析完成后,调用 submitKnowledgePoints 或 submitNoKnowledgePoints 之一提交结果`;
|
|
26
|
+
/**
|
|
27
|
+
* 从文章 Markdown 中提取 doc 节点。
|
|
28
|
+
* 内容太少或无法提取时返回空数组。
|
|
29
|
+
*/
|
|
30
|
+
export async function extractDocNodes(markdown, agentConfig) {
|
|
31
|
+
const result = await runToolExtractionWithFallback(agentConfig, extractKnowledgePointsTool, noKnowledgePointsTool, EXTRACT_DOC_NODES_SYSTEM, `请从以下文章中提取知识要点:
|
|
32
|
+
|
|
33
|
+
${markdown}`);
|
|
34
|
+
if (result.ok)
|
|
35
|
+
return result.data.nodes;
|
|
36
|
+
return [];
|
|
37
|
+
}
|
|
38
|
+
// ========== 链路 2:从 doc 节点归纳 concept 节点 ==========
|
|
39
|
+
const INDUCE_CONCEPT_SYSTEM = `你是一个知识归纳专家。你的任务是从一组知识节点中归纳出若干上层概念。
|
|
40
|
+
|
|
41
|
+
要求:
|
|
42
|
+
1. 每个上层概念是对多个相关知识节点的抽象概括
|
|
43
|
+
2. 概念数量约为输入节点数的 1/3 ~ 1/5,宁缺毋滥
|
|
44
|
+
3. 允许多父(一个知识节点可属于多个上层概念)
|
|
45
|
+
4. 合并不了的节点可以不归,不强求全覆盖
|
|
46
|
+
5. 每个概念至少能覆盖 2 个输入节点
|
|
47
|
+
6. 分析完成后,调用 submitInducedConcepts 或 submitNoConcepts 之一提交结果`;
|
|
48
|
+
/**
|
|
49
|
+
* 从 doc 节点中归纳出 concept 节点。
|
|
50
|
+
* 节点太少或无法归纳时返回空数组。
|
|
51
|
+
*/
|
|
52
|
+
export async function induceConceptNodes(docNodes, agentConfig) {
|
|
53
|
+
if (docNodes.length < 2)
|
|
54
|
+
return [];
|
|
55
|
+
const nodesList = docNodes
|
|
56
|
+
.map((n, i) => `${i + 1}. ${n.label}:${n.description}`)
|
|
57
|
+
.join('\n');
|
|
58
|
+
const result = await runToolExtractionWithFallback(agentConfig, induceConceptsTool, noConceptsTool, INDUCE_CONCEPT_SYSTEM, `请从以下知识节点中归纳上层概念:
|
|
59
|
+
|
|
60
|
+
${nodesList}`);
|
|
61
|
+
if (result.ok)
|
|
62
|
+
return result.data.concepts;
|
|
63
|
+
return [];
|
|
64
|
+
}
|
|
65
|
+
// ========== 链路 3:生成 contains 关系 ==========
|
|
66
|
+
const GENERATE_CONTAINS_SYSTEM = `你是一个知识图谱关系专家。你的任务是判断知识节点之间的包含关系。
|
|
67
|
+
|
|
68
|
+
包含关系定义:
|
|
69
|
+
- A contains B 表示 A 更抽象、更宽泛,B 更具体、是 A 的一部分或子概念
|
|
70
|
+
- concept 类型的节点可以包含 doc 节点,也可以包含更具体的 concept 节点
|
|
71
|
+
- 方向一定是:上层(抽象) → 下层(具体)
|
|
72
|
+
|
|
73
|
+
要求:
|
|
74
|
+
1. 只输出高置信度的包含关系,宁缺毋滥
|
|
75
|
+
2. fromId 是更抽象节点的 id,toId 是更具体节点的 id
|
|
76
|
+
3. **严格使用输入中给出的 id,不要自己编造**
|
|
77
|
+
4. 分析完成后,调用 submitContainsRelations 或 submitNoContainsRelations 之一提交结果`;
|
|
78
|
+
/**
|
|
79
|
+
* 为节点生成 contains 关系。
|
|
80
|
+
* 无法判断时返回空数组。
|
|
81
|
+
*/
|
|
82
|
+
export async function generateContains(nodes, agentConfig) {
|
|
83
|
+
if (nodes.length < 2)
|
|
84
|
+
return [];
|
|
85
|
+
const nodesList = nodes
|
|
86
|
+
.map((n) => `- id: ${n.id}\n type: ${n.type}\n label: ${n.label}\n description: ${n.description}`)
|
|
87
|
+
.join('\n\n');
|
|
88
|
+
const result = await runToolExtractionWithFallback(agentConfig, generateContainsTool, noContainsRelationsTool, GENERATE_CONTAINS_SYSTEM, `请判断以下节点之间的包含关系:
|
|
89
|
+
|
|
90
|
+
${nodesList}`);
|
|
91
|
+
if (result.ok) {
|
|
92
|
+
return result.data.relations.map((r) => ({
|
|
93
|
+
from: r.fromId,
|
|
94
|
+
to: r.toId,
|
|
95
|
+
type: 'contains',
|
|
96
|
+
confidence: r.confidence,
|
|
97
|
+
}));
|
|
98
|
+
}
|
|
99
|
+
return [];
|
|
100
|
+
}
|
|
101
|
+
// ========== 链路 4:生成 concept 之间的关系 ==========
|
|
102
|
+
const CONCEPT_RELATIONS_SYSTEM = `你是一个知识图谱关系专家。你的任务是分析一组概念,找出它们之间的关系。
|
|
103
|
+
|
|
104
|
+
关系类型定义:
|
|
105
|
+
- related_to:两个概念相关,但没有明确的包含/依赖关系
|
|
106
|
+
- part_of:A part_of B 表示 A 是 B 的一部分 / 子领域
|
|
107
|
+
- depends_on:A depends_on B 表示 A 依赖于 B(B 是 A 的前提或基础)
|
|
108
|
+
|
|
109
|
+
要求:
|
|
110
|
+
1. 只输出高置信度的关系,宁缺毋滥
|
|
111
|
+
2. fromId 和 toId 必须是输入中给出的概念 id,不要编造
|
|
112
|
+
3. 关系方向要准确:
|
|
113
|
+
- part_of:部分 → 整体(小的 → 大的)
|
|
114
|
+
- depends_on:依赖方 → 被依赖方
|
|
115
|
+
- related_to:方向不敏感,但也要有意义
|
|
116
|
+
4. 避免重复的关系(互为 related_to 算重复)
|
|
117
|
+
5. 分析完成后,调用 submitConceptRelations 或 submitNoConceptRelations 之一提交结果`;
|
|
118
|
+
/**
|
|
119
|
+
* 归纳 concept 节点之间的关系。
|
|
120
|
+
* 节点太少或无法判断时返回空数组。
|
|
121
|
+
*/
|
|
122
|
+
export async function induceConceptRelations(concepts, agentConfig) {
|
|
123
|
+
if (concepts.length < 2)
|
|
124
|
+
return [];
|
|
125
|
+
const conceptsList = concepts
|
|
126
|
+
.map((n, i) => `${i + 1}. id: ${n.id}\n label: ${n.label}\n description: ${n.description}`)
|
|
127
|
+
.join('\n\n');
|
|
128
|
+
const result = await runToolExtractionWithFallback(agentConfig, conceptRelationsTool, noConceptRelationsTool, CONCEPT_RELATIONS_SYSTEM, `请分析以下概念之间的关系:
|
|
129
|
+
|
|
130
|
+
${conceptsList}`);
|
|
131
|
+
if (result.ok)
|
|
132
|
+
return result.data.relations;
|
|
133
|
+
return [];
|
|
134
|
+
}
|
|
135
|
+
//# sourceMappingURL=llm-chains.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"llm-chains.js","sourceRoot":"","sources":["../../../../src/server/documents/graph/llm-chains.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 从 Agent 输出中提取最外层 JSON 对象。
|
|
3
|
+
* 支持 ```json 围栏、前后多余文字等情况。
|
|
4
|
+
*/
|
|
5
|
+
export function extractJson(text) {
|
|
6
|
+
// 先尝试找 fenced code block
|
|
7
|
+
const fenceMatch = text.match(/```(?:json)?\s*\n([\s\S]*?)\n\s*```/i);
|
|
8
|
+
if (fenceMatch && fenceMatch[1]) {
|
|
9
|
+
return fenceMatch[1].trim();
|
|
10
|
+
}
|
|
11
|
+
// 再尝试找最外层的 { ... }
|
|
12
|
+
const firstBrace = text.indexOf('{');
|
|
13
|
+
const lastBrace = text.lastIndexOf('}');
|
|
14
|
+
if (firstBrace !== -1 && lastBrace !== -1 && lastBrace > firstBrace) {
|
|
15
|
+
return text.slice(firstBrace, lastBrace + 1);
|
|
16
|
+
}
|
|
17
|
+
return null;
|
|
18
|
+
}
|
|
19
|
+
//# sourceMappingURL=llm-utils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"llm-utils.js","sourceRoot":"","sources":["../../../../src/server/documents/graph/llm-utils.ts"],"names":[],"mappings":"AAOA;;;GAGG;AACH,MAAM,UAAU,WAAW,CAAC,IAAY;IACtC,yBAAyB;IACzB,MAAM,UAAU,GAAG,IAAI,CAAC,KAAK,CAAC,sCAAsC,CAAC,CAAC;IACtE,IAAI,UAAU,IAAI,UAAU,CAAC,CAAC,CAAC,EAAE,CAAC;QAChC,OAAO,UAAU,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;IAC9B,CAAC;IACD,mBAAmB;IACnB,MAAM,UAAU,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;IACrC,MAAM,SAAS,GAAG,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;IACxC,IAAI,UAAU,KAAK,CAAC,CAAC,IAAI,SAAS,KAAK,CAAC,CAAC,IAAI,SAAS,GAAG,UAAU,EAAE,CAAC;QACpE,OAAO,IAAI,CAAC,KAAK,CAAC,UAAU,EAAE,SAAS,GAAG,CAAC,CAAC,CAAC;IAC/C,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* LLM 工具函数单元测试(JSON 提取部分)。
|
|
3
|
+
*/
|
|
4
|
+
import { describe, expect, test } from 'vitest';
|
|
5
|
+
import { extractJson } from './llm-utils.js';
|
|
6
|
+
describe('extractJson', () => {
|
|
7
|
+
test('纯 JSON 直接返回', () => {
|
|
8
|
+
const json = '{"a": 1}';
|
|
9
|
+
expect(extractJson(json)).toBe(json);
|
|
10
|
+
});
|
|
11
|
+
test('带 markdown code fence', () => {
|
|
12
|
+
const input = '```json\n{"a": 1}\n```';
|
|
13
|
+
expect(extractJson(input)).toBe('{"a": 1}');
|
|
14
|
+
});
|
|
15
|
+
test('带前后多余文字', () => {
|
|
16
|
+
const input = '好的,这是结果:\n{"a": 1}\n希望对你有帮助。';
|
|
17
|
+
expect(extractJson(input)).toBe('{"a": 1}');
|
|
18
|
+
});
|
|
19
|
+
test('带 fence 和多余文字', () => {
|
|
20
|
+
const input = '开始\n```\n{"a": 1}\n```\n结束';
|
|
21
|
+
expect(extractJson(input)).toBe('{"a": 1}');
|
|
22
|
+
});
|
|
23
|
+
test('嵌套对象正确取最外层', () => {
|
|
24
|
+
const input = '{"a": {"b": 1}}';
|
|
25
|
+
expect(extractJson(input)).toBe(input);
|
|
26
|
+
});
|
|
27
|
+
test('没有 JSON 返回 null', () => {
|
|
28
|
+
expect(extractJson('hello world')).toBeNull();
|
|
29
|
+
});
|
|
30
|
+
test('空字符串返回 null', () => {
|
|
31
|
+
expect(extractJson('')).toBeNull();
|
|
32
|
+
});
|
|
33
|
+
});
|
|
34
|
+
//# sourceMappingURL=llm-utils.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"llm-utils.test.js","sourceRoot":"","sources":["../../../../src/server/documents/graph/llm-utils.test.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC;AAChD,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAE7C,QAAQ,CAAC,aAAa,EAAE,GAAG,EAAE;IAC3B,IAAI,CAAC,aAAa,EAAE,GAAG,EAAE;QACvB,MAAM,IAAI,GAAG,UAAU,CAAC;QACxB,MAAM,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACvC,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,uBAAuB,EAAE,GAAG,EAAE;QACjC,MAAM,KAAK,GAAG,wBAAwB,CAAC;QACvC,MAAM,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;IAC9C,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,SAAS,EAAE,GAAG,EAAE;QACnB,MAAM,KAAK,GAAG,8BAA8B,CAAC;QAC7C,MAAM,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;IAC9C,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,eAAe,EAAE,GAAG,EAAE;QACzB,MAAM,KAAK,GAAG,4BAA4B,CAAC;QAC3C,MAAM,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;IAC9C,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,YAAY,EAAE,GAAG,EAAE;QACtB,MAAM,KAAK,GAAG,iBAAiB,CAAC;QAChC,MAAM,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACzC,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,iBAAiB,EAAE,GAAG,EAAE;QAC3B,MAAM,CAAC,WAAW,CAAC,aAAa,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC;IAChD,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,aAAa,EAAE,GAAG,EAAE;QACvB,MAAM,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC;IACrC,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tool:提交 concept 节点之间的关系。
|
|
3
|
+
*
|
|
4
|
+
* 用在 induceConceptRelations 链路:
|
|
5
|
+
* AI 分析完所有 concept 节点后调用这个 tool,提交概念之间的关系。
|
|
6
|
+
*/
|
|
7
|
+
import { Type } from '@earendil-works/pi-ai';
|
|
8
|
+
import { z } from 'zod';
|
|
9
|
+
// TypeBox schema(发给 API 用)
|
|
10
|
+
export const conceptRelationsParameters = Type.Object({
|
|
11
|
+
relations: Type.Array(Type.Object({
|
|
12
|
+
fromId: Type.String({ description: '起点概念的 id(必须与输入中的 id 完全一致)' }),
|
|
13
|
+
toId: Type.String({ description: '终点概念的 id(必须与输入中的 id 完全一致)' }),
|
|
14
|
+
type: Type.Union([
|
|
15
|
+
Type.Literal('related_to'),
|
|
16
|
+
Type.Literal('part_of'),
|
|
17
|
+
Type.Literal('depends_on'),
|
|
18
|
+
], { description: '关系类型:related_to(相关)、part_of(属于)、depends_on(依赖)' }),
|
|
19
|
+
description: Type.Optional(Type.String({ description: '关系的简要说明' })),
|
|
20
|
+
confidence: Type.Number({ description: '关系的置信度,0-1' }),
|
|
21
|
+
}), { description: '概念之间的关系列表' }),
|
|
22
|
+
});
|
|
23
|
+
// Zod schema(运行时校验 + 类型推断用)
|
|
24
|
+
export const conceptRelationsSchema = z.object({
|
|
25
|
+
relations: z.array(z.object({
|
|
26
|
+
fromId: z.string().min(1),
|
|
27
|
+
toId: z.string().min(1),
|
|
28
|
+
type: z.enum(['related_to', 'part_of', 'depends_on']),
|
|
29
|
+
description: z.string().optional(),
|
|
30
|
+
confidence: z.number().min(0).max(1),
|
|
31
|
+
})),
|
|
32
|
+
});
|
|
33
|
+
export const conceptRelationsTool = {
|
|
34
|
+
name: 'submitConceptRelations',
|
|
35
|
+
description: '提交概念节点之间的关系列表。分析完所有概念后调用此工具提交结果。',
|
|
36
|
+
parameters: conceptRelationsParameters,
|
|
37
|
+
schema: conceptRelationsSchema,
|
|
38
|
+
};
|
|
39
|
+
// ========== 降级 tool ==========
|
|
40
|
+
export const noConceptRelationsParameters = Type.Object({
|
|
41
|
+
reason: Type.String({ description: '无法生成概念关系的原因' }),
|
|
42
|
+
});
|
|
43
|
+
export const noConceptRelationsTool = {
|
|
44
|
+
name: 'submitNoConceptRelations',
|
|
45
|
+
description: '当概念太少或无法判断有效关系时,调用此工具说明原因。',
|
|
46
|
+
parameters: noConceptRelationsParameters,
|
|
47
|
+
schema: z.object({ reason: z.string() }),
|
|
48
|
+
};
|
|
49
|
+
//# sourceMappingURL=concept-relations.tool.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"concept-relations.tool.js","sourceRoot":"","sources":["../../../../../src/server/documents/graph/tools/concept-relations.tool.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,EAAE,IAAI,EAAe,MAAM,uBAAuB,CAAC;AAC1D,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,2BAA2B;AAC3B,MAAM,CAAC,MAAM,0BAA0B,GAAG,IAAI,CAAC,MAAM,CAAC;IACpD,SAAS,EAAE,IAAI,CAAC,KAAK,CACnB,IAAI,CAAC,MAAM,CAAC;QACV,MAAM,EAAE,IAAI,CAAC,MAAM,CAAC,EAAE,WAAW,EAAE,2BAA2B,EAAE,CAAC;QACjE,IAAI,EAAE,IAAI,CAAC,MAAM,CAAC,EAAE,WAAW,EAAE,2BAA2B,EAAE,CAAC;QAC/D,IAAI,EAAE,IAAI,CAAC,KAAK,CACd;YACE,IAAI,CAAC,OAAO,CAAC,YAAY,CAAC;YAC1B,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC;YACvB,IAAI,CAAC,OAAO,CAAC,YAAY,CAAC;SAC3B,EACD,EAAE,WAAW,EAAE,gDAAgD,EAAE,CAClE;QACD,WAAW,EAAE,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,WAAW,EAAE,SAAS,EAAE,CAAC,CAAC;QACnE,UAAU,EAAE,IAAI,CAAC,MAAM,CAAC,EAAE,WAAW,EAAE,YAAY,EAAE,CAAC;KACvD,CAAC,EACF,EAAE,WAAW,EAAE,WAAW,EAAE,CAC7B;CACF,CAAC,CAAC;AAEH,4BAA4B;AAC5B,MAAM,CAAC,MAAM,sBAAsB,GAAG,CAAC,CAAC,MAAM,CAAC;IAC7C,SAAS,EAAE,CAAC,CAAC,KAAK,CAChB,CAAC,CAAC,MAAM,CAAC;QACP,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;QACzB,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;QACvB,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,YAAY,EAAE,SAAS,EAAE,YAAY,CAAC,CAAC;QACrD,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;QAClC,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;KACrC,CAAC,CACH;CACF,CAAC,CAAC;AAIH,MAAM,CAAC,MAAM,oBAAoB,GAAgD;IAC/E,IAAI,EAAE,wBAAwB;IAC9B,WAAW,EACT,kCAAkC;IACpC,UAAU,EAAE,0BAA0B;IACtC,MAAM,EAAE,sBAAsB;CAC/B,CAAC;AAEF,gCAAgC;AAEhC,MAAM,CAAC,MAAM,4BAA4B,GAAG,IAAI,CAAC,MAAM,CAAC;IACtD,MAAM,EAAE,IAAI,CAAC,MAAM,CAAC,EAAE,WAAW,EAAE,aAAa,EAAE,CAAC;CACpD,CAAC,CAAC;AAIH,MAAM,CAAC,MAAM,sBAAsB,GAAkD;IACnF,IAAI,EAAE,0BAA0B;IAChC,WAAW,EAAE,4BAA4B;IACzC,UAAU,EAAE,4BAA4B;IACxC,MAAM,EAAE,CAAC,CAAC,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC;CACzC,CAAC"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tool:提交提取到的知识要点。
|
|
3
|
+
*
|
|
4
|
+
* 用在 extractDocNodes 链路:
|
|
5
|
+
* AI 读完文章后调用这个 tool,把提取到的知识要点作为参数提交。
|
|
6
|
+
*/
|
|
7
|
+
import { Type } from '@earendil-works/pi-ai';
|
|
8
|
+
import { z } from 'zod';
|
|
9
|
+
// TypeBox schema(发给 API 用)
|
|
10
|
+
export const extractKnowledgePointsParameters = Type.Object({
|
|
11
|
+
nodes: Type.Array(Type.Object({
|
|
12
|
+
label: Type.String({ description: '要点标题,简洁明了' }),
|
|
13
|
+
definition: Type.Optional(Type.String({ description: '如果是概念定义,填写准确定义' })),
|
|
14
|
+
description: Type.String({ description: '要点的完整描述' }),
|
|
15
|
+
confidence: Type.Number({ description: '提取的置信度,0-1' }),
|
|
16
|
+
heading: Type.Optional(Type.String({ description: '对应文章中的小标题,如果有的话' })),
|
|
17
|
+
}), { description: '知识要点列表' }),
|
|
18
|
+
});
|
|
19
|
+
// Zod schema(运行时校验 + 类型推断用)
|
|
20
|
+
export const extractKnowledgePointsSchema = z.object({
|
|
21
|
+
nodes: z.array(z.object({
|
|
22
|
+
label: z.string().min(1),
|
|
23
|
+
definition: z.string().optional(),
|
|
24
|
+
description: z.string().min(1),
|
|
25
|
+
confidence: z.number().min(0).max(1),
|
|
26
|
+
heading: z.string().optional(),
|
|
27
|
+
})),
|
|
28
|
+
});
|
|
29
|
+
export const extractKnowledgePointsTool = {
|
|
30
|
+
name: 'submitKnowledgePoints',
|
|
31
|
+
description: '提交从文章中提取的知识要点列表。分析完文章后调用此工具提交结果。',
|
|
32
|
+
parameters: extractKnowledgePointsParameters,
|
|
33
|
+
schema: extractKnowledgePointsSchema,
|
|
34
|
+
};
|
|
35
|
+
// ========== 降级 tool ==========
|
|
36
|
+
export const noKnowledgePointsParameters = Type.Object({
|
|
37
|
+
reason: Type.String({ description: '无法提取知识要点的原因' }),
|
|
38
|
+
});
|
|
39
|
+
export const noKnowledgePointsTool = {
|
|
40
|
+
name: 'submitNoKnowledgePoints',
|
|
41
|
+
description: '当文章内容太少或无法提取有效知识要点时,调用此工具说明原因。',
|
|
42
|
+
parameters: noKnowledgePointsParameters,
|
|
43
|
+
schema: z.object({ reason: z.string() }),
|
|
44
|
+
};
|
|
45
|
+
//# sourceMappingURL=extract-knowledge-points.tool.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"extract-knowledge-points.tool.js","sourceRoot":"","sources":["../../../../../src/server/documents/graph/tools/extract-knowledge-points.tool.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,EAAE,IAAI,EAAe,MAAM,uBAAuB,CAAC;AAC1D,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,2BAA2B;AAC3B,MAAM,CAAC,MAAM,gCAAgC,GAAG,IAAI,CAAC,MAAM,CAAC;IAC1D,KAAK,EAAE,IAAI,CAAC,KAAK,CACf,IAAI,CAAC,MAAM,CAAC;QACV,KAAK,EAAE,IAAI,CAAC,MAAM,CAAC,EAAE,WAAW,EAAE,WAAW,EAAE,CAAC;QAChD,UAAU,EAAE,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,WAAW,EAAE,gBAAgB,EAAE,CAAC,CAAC;QACzE,WAAW,EAAE,IAAI,CAAC,MAAM,CAAC,EAAE,WAAW,EAAE,SAAS,EAAE,CAAC;QACpD,UAAU,EAAE,IAAI,CAAC,MAAM,CAAC,EAAE,WAAW,EAAE,YAAY,EAAE,CAAC;QACtD,OAAO,EAAE,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,WAAW,EAAE,iBAAiB,EAAE,CAAC,CAAC;KACxE,CAAC,EACF,EAAE,WAAW,EAAE,QAAQ,EAAE,CAC1B;CACF,CAAC,CAAC;AAEH,4BAA4B;AAC5B,MAAM,CAAC,MAAM,4BAA4B,GAAG,CAAC,CAAC,MAAM,CAAC;IACnD,KAAK,EAAE,CAAC,CAAC,KAAK,CACZ,CAAC,CAAC,MAAM,CAAC;QACP,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;QACxB,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;QACjC,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;QAC9B,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;QACpC,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;KAC/B,CAAC,CACH;CACF,CAAC,CAAC;AAIH,MAAM,CAAC,MAAM,0BAA0B,GAAsD;IAC3F,IAAI,EAAE,uBAAuB;IAC7B,WAAW,EAAE,kCAAkC;IAC/C,UAAU,EAAE,gCAAgC;IAC5C,MAAM,EAAE,4BAA4B;CACrC,CAAC;AAEF,gCAAgC;AAEhC,MAAM,CAAC,MAAM,2BAA2B,GAAG,IAAI,CAAC,MAAM,CAAC;IACrD,MAAM,EAAE,IAAI,CAAC,MAAM,CAAC,EAAE,WAAW,EAAE,aAAa,EAAE,CAAC;CACpD,CAAC,CAAC;AAIH,MAAM,CAAC,MAAM,qBAAqB,GAAiD;IACjF,IAAI,EAAE,yBAAyB;IAC/B,WAAW,EAAE,gCAAgC;IAC7C,UAAU,EAAE,2BAA2B;IACvC,MAAM,EAAE,CAAC,CAAC,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC;CACzC,CAAC"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tool:提交生成的 contains 关系。
|
|
3
|
+
*
|
|
4
|
+
* 用在 generateContains 链路:
|
|
5
|
+
* AI 分析完所有节点后调用这个 tool,把判断出的 contains 关系作为参数提交。
|
|
6
|
+
*/
|
|
7
|
+
import { Type } from '@earendil-works/pi-ai';
|
|
8
|
+
import { z } from 'zod';
|
|
9
|
+
// TypeBox schema(发给 API 用)
|
|
10
|
+
export const generateContainsParameters = Type.Object({
|
|
11
|
+
relations: Type.Array(Type.Object({
|
|
12
|
+
fromId: Type.String({ description: '上层(更抽象)节点的 id' }),
|
|
13
|
+
toId: Type.String({ description: '下层(更具体)节点的 id' }),
|
|
14
|
+
confidence: Type.Number({ description: '关系的置信度,0-1' }),
|
|
15
|
+
}), { description: '包含关系列表' }),
|
|
16
|
+
});
|
|
17
|
+
// Zod schema(运行时校验 + 类型推断用)
|
|
18
|
+
export const generateContainsSchema = z.object({
|
|
19
|
+
relations: z.array(z.object({
|
|
20
|
+
fromId: z.string().min(1),
|
|
21
|
+
toId: z.string().min(1),
|
|
22
|
+
confidence: z.number().min(0).max(1),
|
|
23
|
+
})),
|
|
24
|
+
});
|
|
25
|
+
export const generateContainsTool = {
|
|
26
|
+
name: 'submitContainsRelations',
|
|
27
|
+
description: '提交节点之间的 contains 包含关系列表。分析完成后调用此工具提交结果。',
|
|
28
|
+
parameters: generateContainsParameters,
|
|
29
|
+
schema: generateContainsSchema,
|
|
30
|
+
};
|
|
31
|
+
// ========== 降级 tool ==========
|
|
32
|
+
export const noContainsRelationsParameters = Type.Object({
|
|
33
|
+
reason: Type.String({ description: '无法生成包含关系的原因' }),
|
|
34
|
+
});
|
|
35
|
+
export const noContainsRelationsTool = {
|
|
36
|
+
name: 'submitNoContainsRelations',
|
|
37
|
+
description: '当节点太少或无法判断有效包含关系时,调用此工具说明原因。',
|
|
38
|
+
parameters: noContainsRelationsParameters,
|
|
39
|
+
schema: z.object({ reason: z.string() }),
|
|
40
|
+
};
|
|
41
|
+
//# sourceMappingURL=generate-contains.tool.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"generate-contains.tool.js","sourceRoot":"","sources":["../../../../../src/server/documents/graph/tools/generate-contains.tool.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,EAAE,IAAI,EAAe,MAAM,uBAAuB,CAAC;AAC1D,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,2BAA2B;AAC3B,MAAM,CAAC,MAAM,0BAA0B,GAAG,IAAI,CAAC,MAAM,CAAC;IACpD,SAAS,EAAE,IAAI,CAAC,KAAK,CACnB,IAAI,CAAC,MAAM,CAAC;QACV,MAAM,EAAE,IAAI,CAAC,MAAM,CAAC,EAAE,WAAW,EAAE,eAAe,EAAE,CAAC;QACrD,IAAI,EAAE,IAAI,CAAC,MAAM,CAAC,EAAE,WAAW,EAAE,eAAe,EAAE,CAAC;QACnD,UAAU,EAAE,IAAI,CAAC,MAAM,CAAC,EAAE,WAAW,EAAE,YAAY,EAAE,CAAC;KACvD,CAAC,EACF,EAAE,WAAW,EAAE,QAAQ,EAAE,CAC1B;CACF,CAAC,CAAC;AAEH,4BAA4B;AAC5B,MAAM,CAAC,MAAM,sBAAsB,GAAG,CAAC,CAAC,MAAM,CAAC;IAC7C,SAAS,EAAE,CAAC,CAAC,KAAK,CAChB,CAAC,CAAC,MAAM,CAAC;QACP,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;QACzB,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;QACvB,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;KACrC,CAAC,CACH;CACF,CAAC,CAAC;AAIH,MAAM,CAAC,MAAM,oBAAoB,GAAgD;IAC/E,IAAI,EAAE,yBAAyB;IAC/B,WAAW,EAAE,yCAAyC;IACtD,UAAU,EAAE,0BAA0B;IACtC,MAAM,EAAE,sBAAsB;CAC/B,CAAC;AAEF,gCAAgC;AAEhC,MAAM,CAAC,MAAM,6BAA6B,GAAG,IAAI,CAAC,MAAM,CAAC;IACvD,MAAM,EAAE,IAAI,CAAC,MAAM,CAAC,EAAE,WAAW,EAAE,aAAa,EAAE,CAAC;CACpD,CAAC,CAAC;AAIH,MAAM,CAAC,MAAM,uBAAuB,GAAmD;IACrF,IAAI,EAAE,2BAA2B;IACjC,WAAW,EAAE,8BAA8B;IAC3C,UAAU,EAAE,6BAA6B;IACzC,MAAM,EAAE,CAAC,CAAC,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC;CACzC,CAAC"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tool:提交归纳出的上层概念。
|
|
3
|
+
*
|
|
4
|
+
* 用在 induceConceptNodes 链路:
|
|
5
|
+
* AI 读完所有 doc 节点后调用这个 tool,把归纳出的上层概念作为参数提交。
|
|
6
|
+
*/
|
|
7
|
+
import { Type } from '@earendil-works/pi-ai';
|
|
8
|
+
import { z } from 'zod';
|
|
9
|
+
// TypeBox schema(发给 API 用)
|
|
10
|
+
export const induceConceptsParameters = Type.Object({
|
|
11
|
+
concepts: Type.Array(Type.Object({
|
|
12
|
+
label: Type.String({ description: '概念名称' }),
|
|
13
|
+
definition: Type.Optional(Type.String({ description: '如果有准确定义,填写此字段' })),
|
|
14
|
+
description: Type.String({ description: '概念的完整描述' }),
|
|
15
|
+
confidence: Type.Number({ description: '归纳的置信度,0-1' }),
|
|
16
|
+
}), { description: '上层概念列表' }),
|
|
17
|
+
});
|
|
18
|
+
// Zod schema(运行时校验 + 类型推断用)
|
|
19
|
+
export const induceConceptsSchema = z.object({
|
|
20
|
+
concepts: z.array(z.object({
|
|
21
|
+
label: z.string().min(1),
|
|
22
|
+
definition: z.string().optional(),
|
|
23
|
+
description: z.string().min(1),
|
|
24
|
+
confidence: z.number().min(0).max(1),
|
|
25
|
+
})),
|
|
26
|
+
});
|
|
27
|
+
export const induceConceptsTool = {
|
|
28
|
+
name: 'submitInducedConcepts',
|
|
29
|
+
description: '提交从知识节点中归纳出的上层概念列表。分析完成后调用此工具提交结果。',
|
|
30
|
+
parameters: induceConceptsParameters,
|
|
31
|
+
schema: induceConceptsSchema,
|
|
32
|
+
};
|
|
33
|
+
// ========== 降级 tool ==========
|
|
34
|
+
export const noConceptsParameters = Type.Object({
|
|
35
|
+
reason: Type.String({ description: '无法归纳上层概念的原因' }),
|
|
36
|
+
});
|
|
37
|
+
export const noConceptsTool = {
|
|
38
|
+
name: 'submitNoConcepts',
|
|
39
|
+
description: '当节点太少或无法归纳出有效上层概念时,调用此工具说明原因。',
|
|
40
|
+
parameters: noConceptsParameters,
|
|
41
|
+
schema: z.object({ reason: z.string() }),
|
|
42
|
+
};
|
|
43
|
+
//# sourceMappingURL=induce-concepts.tool.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"induce-concepts.tool.js","sourceRoot":"","sources":["../../../../../src/server/documents/graph/tools/induce-concepts.tool.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,EAAE,IAAI,EAAe,MAAM,uBAAuB,CAAC;AAC1D,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,2BAA2B;AAC3B,MAAM,CAAC,MAAM,wBAAwB,GAAG,IAAI,CAAC,MAAM,CAAC;IAClD,QAAQ,EAAE,IAAI,CAAC,KAAK,CAClB,IAAI,CAAC,MAAM,CAAC;QACV,KAAK,EAAE,IAAI,CAAC,MAAM,CAAC,EAAE,WAAW,EAAE,MAAM,EAAE,CAAC;QAC3C,UAAU,EAAE,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,WAAW,EAAE,eAAe,EAAE,CAAC,CAAC;QACxE,WAAW,EAAE,IAAI,CAAC,MAAM,CAAC,EAAE,WAAW,EAAE,SAAS,EAAE,CAAC;QACpD,UAAU,EAAE,IAAI,CAAC,MAAM,CAAC,EAAE,WAAW,EAAE,YAAY,EAAE,CAAC;KACvD,CAAC,EACF,EAAE,WAAW,EAAE,QAAQ,EAAE,CAC1B;CACF,CAAC,CAAC;AAEH,4BAA4B;AAC5B,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAAC,CAAC,MAAM,CAAC;IAC3C,QAAQ,EAAE,CAAC,CAAC,KAAK,CACf,CAAC,CAAC,MAAM,CAAC;QACP,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;QACxB,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;QACjC,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;QAC9B,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;KACrC,CAAC,CACH;CACF,CAAC,CAAC;AAIH,MAAM,CAAC,MAAM,kBAAkB,GAA8C;IAC3E,IAAI,EAAE,uBAAuB;IAC7B,WAAW,EAAE,oCAAoC;IACjD,UAAU,EAAE,wBAAwB;IACpC,MAAM,EAAE,oBAAoB;CAC7B,CAAC;AAEF,gCAAgC;AAEhC,MAAM,CAAC,MAAM,oBAAoB,GAAG,IAAI,CAAC,MAAM,CAAC;IAC9C,MAAM,EAAE,IAAI,CAAC,MAAM,CAAC,EAAE,WAAW,EAAE,aAAa,EAAE,CAAC;CACpD,CAAC,CAAC;AAIH,MAAM,CAAC,MAAM,cAAc,GAA0C;IACnE,IAAI,EAAE,kBAAkB;IACxB,WAAW,EAAE,+BAA+B;IAC5C,UAAU,EAAE,oBAAoB;IAChC,MAAM,EAAE,CAAC,CAAC,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC;CACzC,CAAC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 知识图谱核心类型定义。
|
|
3
|
+
*
|
|
4
|
+
* 节点分两类(都是知识节点,只是来源不同):
|
|
5
|
+
* - doc: 从单篇文章直接提取的知识块,带 sources(记录来源文章)
|
|
6
|
+
* - concept: 从已有节点中归纳抽象出的概念,不带 sources
|
|
7
|
+
*
|
|
8
|
+
* 边:
|
|
9
|
+
* - contains:上层包含下层(抽象 → 具体),concept 可以包含 doc 或更具体的 concept
|
|
10
|
+
*/
|
|
11
|
+
export {};
|
|
12
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../../src/server/documents/graph/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 图谱工具函数:id 生成、slug 归一化等纯逻辑。
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* 将 label 归一化为 slug。
|
|
6
|
+
* - 去首尾空格
|
|
7
|
+
* - 转小写(只转英文字母)
|
|
8
|
+
* - 中文/英文/数字保留
|
|
9
|
+
* - 其他字符替换为 -,连续 - 合并
|
|
10
|
+
*/
|
|
11
|
+
export function slugify(label) {
|
|
12
|
+
return label
|
|
13
|
+
.trim()
|
|
14
|
+
.replace(/\s+/g, '-')
|
|
15
|
+
.replace(/[^a-zA-Z0-9\u4e00-\u9fa5-]/g, '-')
|
|
16
|
+
.replace(/-+/g, '-')
|
|
17
|
+
.replace(/^-+|-+$/g, '')
|
|
18
|
+
.toLowerCase();
|
|
19
|
+
}
|
|
20
|
+
/** 生成节点 id(末尾带 4 位随机数,保证唯一) */
|
|
21
|
+
export function makeNodeId(type, label) {
|
|
22
|
+
const rand = Math.floor(Math.random() * 10000).toString().padStart(4, '0');
|
|
23
|
+
return `${type}:${slugify(label)}-${rand}`;
|
|
24
|
+
}
|
|
25
|
+
/** 增量判断:当前 commit 与缓存的 commit 不同就需要重建 */
|
|
26
|
+
export function needRebuild(currentCommitId, cachedCommitId) {
|
|
27
|
+
if (!cachedCommitId)
|
|
28
|
+
return true;
|
|
29
|
+
return currentCommitId !== cachedCommitId;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* 找出所有「入度为 0」的节点(没有被任何边指向的节点)。
|
|
33
|
+
*
|
|
34
|
+
* 用于自底向上构建时:每层只把顶层节点(入度为 0)喂给 AI 归纳 concept / 生成 contains,
|
|
35
|
+
* 下层已经有父节点的节点不参与本层归纳,避免重复处理。
|
|
36
|
+
*/
|
|
37
|
+
export function findRootNodes(nodes, edges) {
|
|
38
|
+
const nonRootIds = new Set(edges.map((e) => e.to));
|
|
39
|
+
return nodes.filter((n) => !nonRootIds.has(n.id));
|
|
40
|
+
}
|
|
41
|
+
//# sourceMappingURL=utils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../../../../src/server/documents/graph/utils.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH;;;;;;GAMG;AACH,MAAM,UAAU,OAAO,CAAC,KAAa;IACnC,OAAO,KAAK;SACT,IAAI,EAAE;SACN,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC;SACpB,OAAO,CAAC,6BAA6B,EAAE,GAAG,CAAC;SAC3C,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC;SACnB,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC;SACvB,WAAW,EAAE,CAAC;AACnB,CAAC;AAED,+BAA+B;AAC/B,MAAM,UAAU,UAAU,CAAC,IAAuB,EAAE,KAAa;IAC/D,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,KAAK,CAAC,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;IAC3E,OAAO,GAAG,IAAI,IAAI,OAAO,CAAC,KAAK,CAAC,IAAI,IAAI,EAAE,CAAC;AAC7C,CAAC;AAED,yCAAyC;AACzC,MAAM,UAAU,WAAW,CAAC,eAAuB,EAAE,cAAuB;IAC1E,IAAI,CAAC,cAAc;QAAE,OAAO,IAAI,CAAC;IACjC,OAAO,eAAe,KAAK,cAAc,CAAC;AAC5C,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,aAAa,CAC3B,KAAU,EACV,KAA4B;IAE5B,MAAM,UAAU,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IACnD,OAAO,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;AACpD,CAAC"}
|