feat(y-log): 操作日志上报(前端直连 + 后端公开只读下发地址)
- 后端新增 y_log 公开只读配置:YLogConfig + AppConfig.y_log + GET /api/public/config/y-log,地址写在 config.yaml(mtime 热重载) - 前端核心 src/core/log/:writeYLog(双门控/异步即发即忘/永不抛错/ 去ip-host/对象序列化裁剪/optResult恒0)+ 配置加载 + token1 隔离存取 - 登录(token)持久化 token1 并报登录、登出先报后清;启动预热配置 - 各 API client 成功路径埋点:敏感词/菜单/按钮/技能地址/轻应用、 会商草稿+任务草稿+后台任务、智能体/定时任务/知识库、Word导出, 以及问答完成钩子(ChatPage/AgentChatPage onFinish) Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
1 parent
dd942cdd60
commit
d2be3b206d
26 files changed
+808
-40
No files matched your search
@@ -1,5 +1,6 @@
|
||||
import { apiFetch } from "@/core/api";
|
||||
import { getBackendBaseURL } from "@/core/config";
|
||||
import { OptType, writeYLog } from "@/core/log/y-log";
|
||||
|
||||
import type {
|
||||
BatchIngestPayload,
|
||||
@@ -41,9 +42,17 @@ export async function listKnowledgeNotes(params: KnowledgeListParams = {}) {
|
||||
if (params.folder !== undefined) qs.set("folder", params.folder);
|
||||
qs.set("limit", String(params.limit ?? 20));
|
||||
qs.set("offset", String(params.offset ?? 0));
|
||||
return parseResponse<KnowledgeListResponse>(
|
||||
const result = await parseResponse<KnowledgeListResponse>(
|
||||
await apiFetch(`${baseUrl()}/notes?${qs.toString()}`),
|
||||
);
|
||||
writeYLog({
|
||||
optType: OptType.search,
|
||||
optDetail: "B1-CM助手-知识库-检索",
|
||||
url: `${baseUrl()}/notes?${qs.toString()}`,
|
||||
reqParam: params,
|
||||
returnParam: result,
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
export async function getKnowledgeNote(noteId: string) {
|
||||
@@ -67,6 +76,13 @@ export async function createKnowledgeNote(data: {
|
||||
body: JSON.stringify(data),
|
||||
}),
|
||||
);
|
||||
writeYLog({
|
||||
optType: OptType.create,
|
||||
optDetail: "B1-CM助手-知识库-新建",
|
||||
url: `${baseUrl()}/notes`,
|
||||
reqParam: data,
|
||||
returnParam: res.note,
|
||||
});
|
||||
return res.note;
|
||||
}
|
||||
|
||||
@@ -81,22 +97,38 @@ export async function updateKnowledgeNote(
|
||||
folder: string | null;
|
||||
}>,
|
||||
) {
|
||||
return parseResponse<KnowledgeNote>(
|
||||
const result = await parseResponse<KnowledgeNote>(
|
||||
await apiFetch(`${baseUrl()}/notes/${encodeURIComponent(noteId)}`, {
|
||||
method: "PUT",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify(data),
|
||||
}),
|
||||
);
|
||||
writeYLog({
|
||||
optType: OptType.edit,
|
||||
optDetail: "B1-CM助手-知识库-修改",
|
||||
url: `${baseUrl()}/notes/${encodeURIComponent(noteId)}`,
|
||||
reqParam: { noteId, data },
|
||||
returnParam: result,
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
export async function deleteKnowledgeNote(noteId: string, hard = false) {
|
||||
return parseResponse<{ ok: boolean; note_id: string }>(
|
||||
const result = await parseResponse<{ ok: boolean; note_id: string }>(
|
||||
await apiFetch(
|
||||
`${baseUrl()}/notes/${encodeURIComponent(noteId)}${hard ? "?hard=true" : ""}`,
|
||||
{ method: "DELETE" },
|
||||
),
|
||||
);
|
||||
writeYLog({
|
||||
optType: OptType.delete,
|
||||
optDetail: "B1-CM助手-知识库-删除",
|
||||
url: `${baseUrl()}/notes/${encodeURIComponent(noteId)}${hard ? "?hard=true" : ""}`,
|
||||
reqParam: { noteId, hard },
|
||||
returnParam: result,
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
export async function searchKnowledge(query: string, limit = 8) {
|
||||
@@ -107,11 +139,18 @@ export async function searchKnowledge(query: string, limit = 8) {
|
||||
body: JSON.stringify({ query, mode: "keyword", limit }),
|
||||
}),
|
||||
);
|
||||
writeYLog({
|
||||
optType: OptType.search,
|
||||
optDetail: "B1-CM助手-知识库-检索",
|
||||
url: `${baseUrl()}/search`,
|
||||
reqParam: { query, mode: "keyword", limit },
|
||||
returnParam: res.items,
|
||||
});
|
||||
return res.items;
|
||||
}
|
||||
|
||||
export async function ingestThread(threadId: string, payload: IngestThreadPayload = {}) {
|
||||
return parseResponse<{
|
||||
const result = await parseResponse<{
|
||||
note?: KnowledgeNote;
|
||||
created?: boolean;
|
||||
queued?: boolean;
|
||||
@@ -122,16 +161,32 @@ export async function ingestThread(threadId: string, payload: IngestThreadPayloa
|
||||
body: JSON.stringify(payload),
|
||||
}),
|
||||
);
|
||||
writeYLog({
|
||||
optType: OptType.import,
|
||||
optDetail: "B1-CM助手-知识库-导入",
|
||||
url: `${baseUrl()}/ingest/thread/${encodeURIComponent(threadId)}`,
|
||||
reqParam: { threadId, payload },
|
||||
returnParam: result,
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
export async function ingestThreadsBatch(payload: BatchIngestPayload = {}) {
|
||||
return parseResponse<BatchIngestResult>(
|
||||
const result = await parseResponse<BatchIngestResult>(
|
||||
await apiFetch(`${baseUrl()}/ingest/threads/batch`, {
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify(payload),
|
||||
}),
|
||||
);
|
||||
writeYLog({
|
||||
optType: OptType.import,
|
||||
optDetail: "B1-CM助手-知识库-导入",
|
||||
url: `${baseUrl()}/ingest/threads/batch`,
|
||||
reqParam: payload,
|
||||
returnParam: result,
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
export interface IngestFileResult {
|
||||
@@ -162,9 +217,17 @@ export async function ingestKnowledgeFile(
|
||||
if (opts.template_id) form.append("template_id", opts.template_id);
|
||||
if (opts.folder) form.append("folder", opts.folder);
|
||||
// No Content-Type header — the browser sets the multipart boundary itself.
|
||||
return parseResponse<IngestFileResult>(
|
||||
const result = await parseResponse<IngestFileResult>(
|
||||
await apiFetch(`${baseUrl()}/ingest/file`, { method: "POST", body: form }),
|
||||
);
|
||||
writeYLog({
|
||||
optType: OptType.import,
|
||||
optDetail: "B1-CM助手-知识库-导入",
|
||||
url: `${baseUrl()}/ingest/file`,
|
||||
reqParam: { fileName: file.name, ...opts },
|
||||
returnParam: result,
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
/** Resolve `[[wikilink]]` targets to note ids / vault pages. */
|
||||
@@ -197,9 +260,16 @@ export async function fetchVaultPage(path: string) {
|
||||
}
|
||||
|
||||
export async function exportKnowledgeGraph() {
|
||||
return parseResponse<GraphExportResult>(
|
||||
const result = await parseResponse<GraphExportResult>(
|
||||
await apiFetch(`${baseUrl()}/export/graph`, { method: "POST" }),
|
||||
);
|
||||
writeYLog({
|
||||
optType: OptType.export,
|
||||
optDetail: "B1-CM助手-知识库-导出",
|
||||
url: `${baseUrl()}/export/graph`,
|
||||
returnParam: result,
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
/** Absolute URL of a served wiki-export file (for iframe / download). */
|
||||
|
||||
Reference in new issue
Block a user