M3a:息壤三级记忆域——归真触发提取管线/白名单明忆/重忆确认/正影版本链/删除墓碑/双通道召回注入,退役旧记忆-抽取-反思-大周天-演化管线(迁移 004,验收 7 用例)

This commit is contained in:
chenxin committed 2026-08-27 09:16:32 +08:00
1 parent 2a640a901b
commit 9c98c2f85e
69 files changed
+1193 -6033

No files matched your search

-37
View File
@@ -1,37 +0,0 @@
import { describe, expect, it, vi } from "vitest";
vi.mock("./client", () => ({
apiGet: vi.fn(),
apiPost: vi.fn(),
}));
import { apiGet, apiPost } from "./client";
import { approveCandidate, listCandidates, rejectCandidate } from "./evolution";
describe("evolution api", () => {
it("listCandidates 构造人物级列表 path 与 query", async () => {
vi.mocked(apiGet).mockResolvedValue({
items: [],
page: 1,
page_size: 20,
total: 0,
});
await listCandidates("char_1", { status: "pending", type: "procedural" });
expect(apiGet).toHaveBeenCalledWith(
"/characters/char_1/evolution-candidates",
{ status: "pending", type: "procedural" },
);
});
it("approveCandidate POST 到 approve 端点", async () => {
vi.mocked(apiPost).mockResolvedValue({ status: "applied" } as never);
await approveCandidate("evo_1");
expect(apiPost).toHaveBeenCalledWith("/evolution-candidates/evo_1/approve");
});
it("rejectCandidate POST 到 reject 端点", async () => {
vi.mocked(apiPost).mockResolvedValue({ status: "rejected" } as never);
await rejectCandidate("evo_1");
expect(apiPost).toHaveBeenCalledWith("/evolution-candidates/evo_1/reject");
});
});
-37
View File
@@ -1,37 +0,0 @@
/**
* 演化候选 API Client(对应 docs/domain/core-domains.md §7)。
* 大周天生成的演化候选审核闭环:列表 / approve / reject。
*/
import { apiGet, apiPost } from "./client";
import type { EvolutionCandidate, Paginated } from "@/types/api";
/** 列出某人物的演化候选(默认按 created_at 倒序) */
export function listCandidates(
characterId: string,
params?: {
status?: string;
type?: string;
page?: number;
page_size?: number;
},
) {
return apiGet<Paginated<EvolutionCandidate>>(
`/characters/${characterId}/evolution-candidates`,
params,
);
}
/** 审核通过:派生到下游(人格版本 / 程序记忆),status → applied */
export function approveCandidate(candidateId: string) {
return apiPost<EvolutionCandidate>(
`/evolution-candidates/${candidateId}/approve`,
);
}
/** 驳回:status → rejected,不派生下游 */
export function rejectCandidate(candidateId: string) {
return apiPost<EvolutionCandidate>(
`/evolution-candidates/${candidateId}/reject`,
);
}
-2
View File
@@ -10,9 +10,7 @@ export * as audioApi from "./audio";
export * as charactersApi from "./characters";
export * as runsApi from "./runs";
export * as sandboxApi from "./sandbox";
export * as memoryApi from "./memory";
export * as personalityApi from "./personality";
export * as evolutionApi from "./evolution";
export * as driveApi from "./drive";
export * as healthApi from "./health";
export * as toolsApi from "./tools";
-67
View File
@@ -1,67 +0,0 @@
import { describe, expect, it, vi } from "vitest";
vi.mock("./client", () => ({
apiDelete: vi.fn(),
apiGet: vi.fn(),
apiPatch: vi.fn(),
apiPost: vi.fn(),
}));
import { apiDelete, apiGet, apiPatch, apiPost } from "./client";
import {
createMemory,
deleteMemory,
listMemories,
updateMemory,
} from "./memory";
describe("memory api", () => {
it("listMemories GET /memory 支持分页与类型过滤", async () => {
vi.mocked(apiGet).mockResolvedValue({ items: [], total: 0 });
await listMemories({ page: 1, page_size: 20, type: "episodic" });
expect(apiGet).toHaveBeenCalledWith("/memory", {
page: 1,
page_size: 20,
type: "episodic",
});
});
it("createMemory POST /memory 默认 source=user_explicit", async () => {
vi.mocked(apiPost).mockResolvedValue({ id: "mem_1" });
await createMemory({ type: "episodic", title: "测试", content: "内容" });
expect(apiPost).toHaveBeenCalledWith("/memory", {
source: "user_explicit",
type: "episodic",
title: "测试",
content: "内容",
});
});
it("createMemory 支持覆盖 source", async () => {
vi.mocked(apiPost).mockResolvedValue({ id: "mem_2" });
await createMemory({
type: "episodic",
title: "导入",
content: "内容",
source: "conversation",
});
expect(apiPost).toHaveBeenCalledWith("/memory", {
source: "conversation",
type: "episodic",
title: "导入",
content: "内容",
});
});
it("updateMemory PATCH /memory/:id", async () => {
vi.mocked(apiPatch).mockResolvedValue({ id: "mem_1" });
await updateMemory("mem_1", { title: "新标题" });
expect(apiPatch).toHaveBeenCalledWith("/memory/mem_1", { title: "新标题" });
});
it("deleteMemory DELETE /memory/:id", async () => {
vi.mocked(apiDelete).mockResolvedValue(undefined);
await deleteMemory("mem_1");
expect(apiDelete).toHaveBeenCalledWith("/memory/mem_1");
});
});
-45
View File
@@ -1,45 +0,0 @@
/**
* 记忆 API Client(对应 后端生成的 OpenAPI 契约 §10)。
* 手动记忆 CRUD;character_id 省略时使用当前激活人物。
*/
import { apiDelete, apiGet, apiPatch, apiPost } from "./client";
import type {
CreateMemoryRequest,
Memory,
Paginated,
UpdateMemoryRequest,
} from "@/types/api";
export interface ListMemoryParams {
character_id?: string;
type?: string;
source?: string;
page?: number;
page_size?: number;
/** 查询参数可透传,允许作为 Record 传递给底层请求封装 */
[key: string]: string | number | undefined;
}
/** 列出当前人物记忆 */
export function listMemories(params?: ListMemoryParams) {
return apiGet<Paginated<Memory>>("/memory", params);
}
/** 创建记忆;手动记忆 source 默认 user_explicit */
export function createMemory(body: CreateMemoryRequest) {
return apiPost<Memory>("/memory", {
source: "user_explicit",
...body,
});
}
/** 更新记忆(PATCH 部分字段) */
export function updateMemory(memoryId: string, body: UpdateMemoryRequest) {
return apiPatch<Memory>(`/memory/${memoryId}`, body);
}
/** 删除记忆(后端软删除:status=deleted + deleted_at) */
export function deleteMemory(memoryId: string) {
return apiDelete<void>(`/memory/${memoryId}`);
}