refactor(kb): 文库列表/正文分离 + [[双链]]索引表(可扛大文件)
不再一次拉回整库正文、不再前端扫全文 —— 列表只读元数据,正文按需取,链接走索引。 - store: SaveDoc 维护 size+preview(前 500 字);ListVault 仅 Select 元数据(name/size/preview, 不含 content);GetDoc 取单篇全文;DocLink 表 + ReplaceDocLinks(入库/编辑时按 from 重建出链) + ListLinks。 - gateway: 入库/笔记保存时正则抽 [[链接]]→ReplaceDocLinks 维护索引; /kb/vault 改返元数据+预览;新增 /kb/doc(单篇全文) 与 /kb/links(全库双链)。 - 前端:listVault 返元数据,新增 getDoc/listLinks;VaultPanel 列表只展示名/字数, 选中后 getDoc 按需载正文(带加载态),反链/笔记关系图改用服务端 links 索引(不扫全文)。 验证:curl /kb/vault 仅 name/size/preview;/kb/doc 取单篇;/kb/links 返 3 条双链。 Preview:文库点「架构总览」按需载正文(平台分五层)、反向链接(1)=Dispatcher(来自索引)。tsc+vite+gateway build 通过。 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -123,7 +123,12 @@ export async function createKb(id: Identity, name: string, kind: string): Promis
|
||||
|
||||
export interface VaultDoc {
|
||||
name: string;
|
||||
content: string;
|
||||
size?: number;
|
||||
preview?: string;
|
||||
}
|
||||
export interface DocLink {
|
||||
from: string;
|
||||
to: string;
|
||||
}
|
||||
|
||||
// ---- 我的 Agent 编排(服务端保存,owner 隔离)----
|
||||
@@ -169,7 +174,7 @@ export async function listChatModels(): Promise<string[]> {
|
||||
}
|
||||
}
|
||||
|
||||
// listVault: GET /api/v1/kb/vault —— 某知识库的原始文档(Obsidian 式文库浏览)。
|
||||
// listVault: GET /api/v1/kb/vault —— 文库列表(仅元数据 + 预览,不拉全文)。
|
||||
export async function listVault(id: Identity, kb: string): Promise<VaultDoc[]> {
|
||||
const res = await fetch(`${GATEWAY}/api/v1/kb/vault?kb=${encodeURIComponent(kb)}`, { headers: idHeaders(id) });
|
||||
const data = (await res.json()) as { docs?: VaultDoc[]; error?: string };
|
||||
@@ -177,6 +182,22 @@ export async function listVault(id: Identity, kb: string): Promise<VaultDoc[]> {
|
||||
return data.docs ?? [];
|
||||
}
|
||||
|
||||
// getDoc: GET /api/v1/kb/doc —— 取单篇文档全文(按需加载,避免列表拉全量)。
|
||||
export async function getDoc(id: Identity, kb: string, name: string): Promise<string> {
|
||||
const res = await fetch(`${GATEWAY}/api/v1/kb/doc?kb=${encodeURIComponent(kb)}&name=${encodeURIComponent(name)}`, { headers: idHeaders(id) });
|
||||
const data = (await res.json()) as { content?: string; error?: string };
|
||||
if (!res.ok) throw new Error(data.error ?? `doc failed: ${res.status}`);
|
||||
return data.content ?? "";
|
||||
}
|
||||
|
||||
// listLinks: GET /api/v1/kb/links —— 某库全部 [[双链]](反链/笔记关系图,数据小)。
|
||||
export async function listLinks(id: Identity, kb: string): Promise<DocLink[]> {
|
||||
const res = await fetch(`${GATEWAY}/api/v1/kb/links?kb=${encodeURIComponent(kb)}`, { headers: idHeaders(id) });
|
||||
const data = (await res.json()) as { links?: DocLink[]; error?: string };
|
||||
if (!res.ok) throw new Error(data.error ?? `links failed: ${res.status}`);
|
||||
return data.links ?? [];
|
||||
}
|
||||
|
||||
// saveNote: POST /api/v1/kb/note —— 新建/编辑笔记(落库 + 按 doc 重入库替换旧块)。
|
||||
export async function saveNote(id: Identity, kb: string, name: string, content: string): Promise<void> {
|
||||
const res = await fetch(`${GATEWAY}/api/v1/kb/note`, {
|
||||
|
||||
Reference in New Issue
Block a user