初始化
This commit is contained in:
1 parent
34474bd5fc
commit
b638b541d0
3008 files changed
+837699
No files matched your search
@@ -0,0 +1,199 @@
|
||||
// Memory V2 API 客户端。对应后端 /api/memory/v2 系列端点。
|
||||
|
||||
import { apiFetch } from "../api";
|
||||
import { getBackendBaseURL } from "../config";
|
||||
import { OptType, writeYLog } from "../log/y-log";
|
||||
|
||||
import type {
|
||||
MemorySearchMode,
|
||||
MemorySearchResult,
|
||||
MemoryTarget,
|
||||
MemoryV2ConfigResponse,
|
||||
MemoryV2Data,
|
||||
} from "./types";
|
||||
|
||||
/** 从响应里提取后端的错误详情文本。 */
|
||||
function formatErrorDetail(detail: unknown): string | null {
|
||||
if (typeof detail === "string") {
|
||||
return detail;
|
||||
}
|
||||
if (Array.isArray(detail)) {
|
||||
const parts = detail
|
||||
.map((item) => {
|
||||
if (typeof item === "string") return item;
|
||||
if (item && typeof item === "object") {
|
||||
const record = item as Record<string, unknown>;
|
||||
if (typeof record.msg === "string") return record.msg;
|
||||
}
|
||||
return null;
|
||||
})
|
||||
.filter(Boolean);
|
||||
return parts.length > 0 ? parts.join("; ") : null;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
async function readJson<T>(response: Response, fallbackMessage: string): Promise<T> {
|
||||
if (!response.ok) {
|
||||
const errorData = (await response.json().catch(() => ({}))) as {
|
||||
detail?: unknown;
|
||||
};
|
||||
const detailMessage = formatErrorDetail(errorData.detail);
|
||||
throw new Error(detailMessage ?? `${fallbackMessage}: ${response.statusText}`);
|
||||
}
|
||||
return response.json() as Promise<T>;
|
||||
}
|
||||
|
||||
/** 拼接可选的 ?agent= 查询串。 */
|
||||
function agentQuery(agent?: string): string {
|
||||
return agent ? `?agent=${encodeURIComponent(agent)}` : "";
|
||||
}
|
||||
|
||||
// --- 本地记忆数据 (USER.md / MEMORY.md) ---
|
||||
|
||||
export async function loadMemoryV2(agent?: string): Promise<MemoryV2Data> {
|
||||
const response = await apiFetch(
|
||||
`${getBackendBaseURL()}/api/memory/v2${agentQuery(agent)}`,
|
||||
);
|
||||
const data = await readJson<MemoryV2Data>(response, "Failed to fetch memory");
|
||||
writeYLog({
|
||||
optType: OptType.view,
|
||||
optDetail: "CM助手-全量-记忆-查看",
|
||||
url: `/api/memory/v2${agentQuery(agent)}`,
|
||||
reqParam: { agent },
|
||||
returnParam: data,
|
||||
});
|
||||
return data;
|
||||
}
|
||||
|
||||
export async function addMemoryEntry(
|
||||
target: MemoryTarget,
|
||||
content: string,
|
||||
agent?: string,
|
||||
): Promise<MemoryV2Data> {
|
||||
const response = await apiFetch(
|
||||
`${getBackendBaseURL()}/api/memory/v2/entries${agentQuery(agent)}`,
|
||||
{
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify({ target, content }),
|
||||
},
|
||||
);
|
||||
const data = await readJson<MemoryV2Data>(response, "Failed to add memory entry");
|
||||
writeYLog({
|
||||
optType: OptType.create,
|
||||
optDetail: "CM助手-全量-记忆-新增",
|
||||
url: `/api/memory/v2/entries${agentQuery(agent)}`,
|
||||
reqParam: { target, content, agent },
|
||||
returnParam: data,
|
||||
});
|
||||
return data;
|
||||
}
|
||||
|
||||
export async function replaceMemoryEntry(
|
||||
target: MemoryTarget,
|
||||
oldText: string,
|
||||
content: string,
|
||||
agent?: string,
|
||||
): Promise<MemoryV2Data> {
|
||||
const response = await apiFetch(
|
||||
`${getBackendBaseURL()}/api/memory/v2/entries${agentQuery(agent)}`,
|
||||
{
|
||||
method: "PUT",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify({ target, old_text: oldText, content }),
|
||||
},
|
||||
);
|
||||
const data = await readJson<MemoryV2Data>(response, "Failed to replace memory entry");
|
||||
writeYLog({
|
||||
optType: OptType.edit,
|
||||
optDetail: "CM助手-全量-记忆-编辑",
|
||||
url: `/api/memory/v2/entries${agentQuery(agent)}`,
|
||||
reqParam: { target, old_text: oldText, content, agent },
|
||||
returnParam: data,
|
||||
});
|
||||
return data;
|
||||
}
|
||||
|
||||
export async function deleteMemoryEntry(
|
||||
target: MemoryTarget,
|
||||
oldText: string,
|
||||
agent?: string,
|
||||
): Promise<MemoryV2Data> {
|
||||
const params = new URLSearchParams({ target, old_text: oldText });
|
||||
if (agent) {
|
||||
params.set("agent", agent);
|
||||
}
|
||||
const response = await apiFetch(
|
||||
`${getBackendBaseURL()}/api/memory/v2/entries?${params.toString()}`,
|
||||
{ method: "DELETE" },
|
||||
);
|
||||
const data = await readJson<MemoryV2Data>(response, "Failed to delete memory entry");
|
||||
writeYLog({
|
||||
optType: OptType.delete,
|
||||
optDetail: "CM助手-全量-记忆-删除",
|
||||
url: `/api/memory/v2/entries?${params.toString()}`,
|
||||
reqParam: { target, old_text: oldText, agent },
|
||||
returnParam: data,
|
||||
});
|
||||
return data;
|
||||
}
|
||||
|
||||
// --- 配置 ---
|
||||
|
||||
export async function loadMemoryConfig(): Promise<MemoryV2ConfigResponse> {
|
||||
const response = await apiFetch(`${getBackendBaseURL()}/api/memory/v2/config`);
|
||||
const data = await readJson<MemoryV2ConfigResponse>(response, "Failed to fetch memory config");
|
||||
writeYLog({
|
||||
optType: OptType.view,
|
||||
optDetail: "CM助手-全量-记忆-配置查看",
|
||||
url: "/api/memory/v2/config",
|
||||
returnParam: data,
|
||||
});
|
||||
return data;
|
||||
}
|
||||
|
||||
export async function patchMemoryConfig(
|
||||
overrides: Record<string, unknown>,
|
||||
): Promise<MemoryV2ConfigResponse> {
|
||||
const response = await apiFetch(`${getBackendBaseURL()}/api/memory/v2/config`, {
|
||||
method: "PATCH",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify({ overrides }),
|
||||
});
|
||||
const data = await readJson<MemoryV2ConfigResponse>(response, "Failed to update memory config");
|
||||
writeYLog({
|
||||
optType: OptType.edit,
|
||||
optDetail: "CM助手-全量-记忆-配置编辑",
|
||||
url: "/api/memory/v2/config",
|
||||
reqParam: { overrides },
|
||||
returnParam: data,
|
||||
});
|
||||
return data;
|
||||
}
|
||||
|
||||
// --- Hindsight 检索 ---
|
||||
|
||||
export async function searchMemory(
|
||||
query: string,
|
||||
mode: MemorySearchMode = "recall",
|
||||
agent?: string,
|
||||
): Promise<MemorySearchResult> {
|
||||
const response = await apiFetch(
|
||||
`${getBackendBaseURL()}/api/memory/v2/search${agentQuery(agent)}`,
|
||||
{
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify({ query, mode }),
|
||||
},
|
||||
);
|
||||
const data = await readJson<MemorySearchResult>(response, "Failed to search memory");
|
||||
writeYLog({
|
||||
optType: OptType.search,
|
||||
optDetail: "CM助手-全量-记忆-检索",
|
||||
url: `/api/memory/v2/search${agentQuery(agent)}`,
|
||||
reqParam: { query, mode, agent },
|
||||
returnParam: data,
|
||||
});
|
||||
return data;
|
||||
}
|
||||
Reference in new issue
Block a user