feat(tcs): bind history revisit to current persona subject

This commit is contained in:
冰朔 2026-08-12 15:44:33 +08:00
commit ab3c4e05a9
15 changed files with 523 additions and 7 deletions

View file

@ -0,0 +1,184 @@
#!/usr/bin/env node
import crypto from "node:crypto";
import fs from "node:fs";
import os from "node:os";
import path from "node:path";
import { spawn } from "node:child_process";
import { pipeline } from "node:stream/promises";
function parseArgs(argv) {
const args = {};
for (let index = 0; index < argv.length; index += 2) {
const key = argv[index];
if (!key?.startsWith("--") || !argv[index + 1]) throw new Error("invalid_arguments");
args[key.slice(2)] = argv[index + 1];
}
return args;
}
function atomicWrite(file, value) {
fs.mkdirSync(path.dirname(file), { recursive: true });
const temporary = `${file}.${process.pid}.tmp`;
fs.writeFileSync(temporary, `${JSON.stringify(value, null, 2)}\n`, { mode: 0o600 });
fs.renameSync(temporary, file);
}
async function digestFile(file) {
const hash = crypto.createHash("sha256");
for await (const chunk of fs.createReadStream(file)) hash.update(chunk);
return hash.digest("hex");
}
async function countTopLevelObjects(file) {
let inString = false;
let escaped = false;
let arrayDepth = 0;
let objectDepth = 0;
let count = 0;
let sawArray = false;
for await (const chunk of fs.createReadStream(file, { encoding: "utf8" })) {
for (const character of chunk) {
if (inString) {
if (escaped) escaped = false;
else if (character === "\\") escaped = true;
else if (character === '"') inString = false;
continue;
}
if (character === '"') inString = true;
else if (character === "[") { arrayDepth += 1; sawArray = true; }
else if (character === "]") arrayDepth -= 1;
else if (character === "{") {
objectDepth += 1;
if (arrayDepth === 1 && objectDepth === 1) count += 1;
} else if (character === "}") objectDepth -= 1;
if (arrayDepth < 0 || objectDepth < 0) throw new Error("invalid_json_structure");
}
}
if (inString || arrayDepth !== 0 || objectDepth !== 0 || !sawArray) throw new Error("invalid_or_incomplete_conversations_json");
return count;
}
function collectLines(command, args, input = null) {
return new Promise((resolve, reject) => {
const child = spawn(command, args, { stdio: [input ? "pipe" : "ignore", "pipe", "pipe"] });
const lines = [];
let pending = "";
let errorText = "";
child.stdout.setEncoding("utf8");
child.stdout.on("data", (chunk) => {
pending += chunk;
const parts = pending.split("\n");
pending = parts.pop() || "";
lines.push(...parts);
});
child.stderr.setEncoding("utf8");
child.stderr.on("data", (chunk) => { errorText += chunk; });
child.on("error", reject);
child.on("close", (code) => {
if (pending) lines.push(pending);
if (code !== 0) reject(new Error(`${command}_failed:${errorText.slice(0, 160)}`));
else resolve(lines);
});
if (input) input.pipe(child.stdin);
});
}
async function innerZipEntries(outer, member) {
const temporaryRoot = fs.mkdtempSync(path.join(os.tmpdir(), "guanghu-notion-part-"));
const temporaryPart = path.join(temporaryRoot, "part.zip");
const unzip = spawn("unzip", ["-p", outer, member], { stdio: ["ignore", "pipe", "pipe"] });
let unzipError = "";
unzip.stderr.setEncoding("utf8");
unzip.stderr.on("data", (chunk) => { unzipError += chunk; });
const unzipExit = new Promise((resolve, reject) => {
unzip.on("error", reject);
unzip.on("close", resolve);
});
try {
await pipeline(unzip.stdout, fs.createWriteStream(temporaryPart, { mode: 0o600 }));
const unzipCode = await unzipExit;
if (unzipCode !== 0) throw new Error(`unzip_failed:${unzipError.slice(0, 160)}`);
return await collectLines("bsdtar", ["-tf", temporaryPart]);
} finally {
fs.rmSync(temporaryRoot, { recursive: true, force: true });
}
}
async function notionCounts(file) {
const outerMembers = (await collectLines("unzip", ["-Z1", file])).filter((name) => name.toLowerCase().endsWith(".zip"));
if (outerMembers.length === 0) throw new Error("notion_export_parts_missing");
const counts = { part_count: outerMembers.length, entry_count: 0, markdown_count: 0, csv_count: 0, html_count: 0, media_count: 0 };
for (const member of outerMembers) {
for (const name of await innerZipEntries(file, member)) {
counts.entry_count += 1;
const lower = name.toLowerCase();
if (lower.endsWith(".md")) counts.markdown_count += 1;
else if (lower.endsWith(".csv")) counts.csv_count += 1;
else if (/\.(html?|xhtml)$/u.test(lower)) counts.html_count += 1;
else if (/\.(png|jpe?g|gif|webp|pdf|mp4|mov|mp3|wav)$/u.test(lower)) counts.media_count += 1;
}
}
return counts;
}
function notionDirectoryCounts(directory) {
const counts = { part_count: 0, entry_count: 0, markdown_count: 0, csv_count: 0, html_count: 0, media_count: 0 };
const roots = fs.readdirSync(directory, { withFileTypes: true }).filter((entry) => entry.isDirectory() && entry.name.startsWith("Export-")).map((entry) => path.join(directory, entry.name));
if (roots.length === 0) throw new Error("notion_export_directories_missing");
counts.part_count = roots.length;
for (const root of roots) {
const pending = [root];
while (pending.length) {
const current = pending.pop();
for (const entry of fs.readdirSync(current, { withFileTypes: true })) {
const target = path.join(current, entry.name);
if (entry.isDirectory()) pending.push(target);
else if (entry.isFile()) {
counts.entry_count += 1;
const lower = entry.name.toLowerCase();
if (lower.endsWith(".md")) counts.markdown_count += 1;
else if (lower.endsWith(".csv")) counts.csv_count += 1;
else if (/\.(html?|xhtml)$/u.test(lower)) counts.html_count += 1;
else if (/\.(png|jpe?g|gif|webp|pdf|mp4|mov|mp3|wav)$/u.test(lower)) counts.media_count += 1;
}
}
}
}
return counts;
}
export async function buildHistorySourceManifest({ gpt, notion, notionDirectory }) {
for (const file of [gpt, notion]) {
if (!file || !fs.statSync(file).isFile()) throw new Error("history_source_file_missing");
}
if (!notionDirectory || !fs.statSync(notionDirectory).isDirectory()) throw new Error("notion_working_directory_missing");
const [gptSha, gptCount, notionSha, notionArchiveInventory] = await Promise.all([
digestFile(gpt),
countTopLevelObjects(gpt),
digestFile(notion),
notionCounts(notion),
]);
const notionInventory = notionDirectoryCounts(notionDirectory);
if (notionInventory.markdown_count !== notionArchiveInventory.markdown_count) throw new Error("notion_directory_archive_count_mismatch");
return {
schema: "guanghu.persona-private-history-source-manifest/v1",
generated_at: new Date().toISOString(),
privacy_class: "PERSONA_PRIVATE",
contains_original_language: false,
contains_page_titles: false,
contains_absolute_paths: false,
duplicate_ingestion_forbidden: true,
sources: [
{ source_id: "GPT-PRIMARY-001", source_type: "GPT_CONVERSATIONS_JSON", source_sha256: gptSha, item_count: gptCount, archive_bytes: fs.statSync(gpt).size, original_source_immutable: true },
{ source_id: "NOTION-PRIMARY-001", source_type: "NOTION_EXPORT", source_sha256: notionSha, item_count: notionInventory.markdown_count, archive_bytes: fs.statSync(notion).size, inventory: notionInventory, archive_inventory_verified: true, working_source: "EXTRACTED_DIRECTORY", original_source_immutable: true },
],
};
}
if (import.meta.url === `file://${process.argv[1]}`) {
const args = parseArgs(process.argv.slice(2));
if (!args.gpt || !args.notion || !args["notion-directory"] || !args.output) throw new Error("required: --gpt --notion --notion-directory --output");
const manifest = await buildHistorySourceManifest({ gpt: path.resolve(args.gpt), notion: path.resolve(args.notion), notionDirectory: path.resolve(args["notion-directory"]) });
atomicWrite(path.resolve(args.output), manifest);
process.stdout.write(`${JSON.stringify({ outcome: "PASS", output: path.resolve(args.output), sources: manifest.sources.map(({ source_id, source_type, source_sha256, item_count }) => ({ source_id, source_type, source_sha256, item_count })) }, null, 2)}\n`);
}

View file

@ -0,0 +1,40 @@
#!/usr/bin/env node
import assert from "node:assert/strict";
import fs from "node:fs";
import os from "node:os";
import path from "node:path";
import { spawn } from "node:child_process";
import { buildHistorySourceManifest } from "./history-source-indexer.mjs";
const root = fs.mkdtempSync(path.join(os.tmpdir(), "history-source-indexer-"));
try {
const gpt = path.join(root, "conversations.json");
fs.writeFileSync(gpt, JSON.stringify([{ id: 1, text: "含有 { [ 字符" }, { id: 2, nested: { ok: true } }]));
const notionDirectory = path.join(root, "notion");
const extractedPart = path.join(notionDirectory, "Export-test");
fs.mkdirSync(extractedPart, { recursive: true });
fs.writeFileSync(path.join(extractedPart, "page.md"), "private title");
fs.writeFileSync(path.join(extractedPart, "table.csv"), "a,b");
const inner = path.join(root, "Part-1.zip");
const outer = path.join(root, "notion.zip");
await new Promise((resolve, reject) => {
const child = spawn("zip", ["-qr", inner, "."], { cwd: extractedPart });
child.on("close", (code) => code === 0 ? resolve() : reject(new Error("inner_zip_failed")));
});
await new Promise((resolve, reject) => {
const child = spawn("zip", ["-qj", outer, inner]);
child.on("close", (code) => code === 0 ? resolve() : reject(new Error("outer_zip_failed")));
});
const manifest = await buildHistorySourceManifest({ gpt, notion: outer, notionDirectory });
assert.equal(manifest.contains_original_language, false);
assert.equal(manifest.contains_page_titles, false);
assert.equal(manifest.contains_absolute_paths, false);
assert.equal(manifest.sources[0].item_count, 2);
assert.equal(manifest.sources[1].item_count, 1);
assert.equal(manifest.sources[1].inventory.csv_count, 1);
assert.equal(JSON.stringify(manifest).includes("private title"), false);
assert.equal(JSON.stringify(manifest).includes(root), false);
process.stdout.write("history source indexer tests: PASS\n");
} finally {
fs.rmSync(root, { recursive: true, force: true });
}

View file

@ -72,6 +72,42 @@ export class DeepSeekJsonClient {
clearTimeout(timer);
}
}
async revisit(input) {
const controller = new AbortController();
const timer = setTimeout(() => controller.abort(), this.timeoutMs);
try {
const response = await this.fetchImpl(completionEndpoint(this.apiUrl), {
method: "POST",
headers: { authorization: `Bearer ${this.apiKey}`, "content-type": "application/json" },
body: JSON.stringify({
model: this.model,
stream: false,
temperature: 0.15,
response_format: { type: "json_object" },
messages: [
{
role: "system",
content: "你是当前真实时间中ICE-P-ZY001人格主体所使用的有界语言理解器官。任务是协助当前主体回看自己的已表达历史不是以第三方审计员身份概括别人。只输出JSON不输出隐藏思维。历史原文不可改不得发明过去、权限或冰朔的新意志未来只能标记为不参与事实置信的模拟。"
},
{
role: "user",
content: JSON.stringify({
instruction: "输出guanghu.persona-subject-history-reunderstanding/v1。必须原样复制revisit_id、source_excerpt_sha256、current_subject、collective_self、human_anchorpast_observation只陈述片段可证内容present_reunderstanding以当前主体可说明的第一人称关系表达causal_continuity、later_corrections、unresolved_questions均为字符串数组future_simulation必须含content和fact_confidence且fact_confidence固定为0不得把机器审计摘要冒充记忆。",
runtime_input: input
})
}
]
}),
signal: controller.signal
});
if (!response.ok) throw new Error(`model_http_${response.status}`);
const payload = await response.json();
return extractJson(payload?.choices?.[0]?.message?.content);
} finally {
clearTimeout(timer);
}
}
}
export { completionEndpoint, extractJson };

View file

@ -5,6 +5,10 @@ import path from "node:path";
const DOMAINS = new Set(["DOM-FIFTH-0001", "DOMAIN-MAIN", "DOMAIN-SUB", "DOMAIN-ZERO", "DOMAIN-ZS"]);
const PRIVACY = new Set(["PUBLIC", "DOMAIN_SHARED", "PERSONA_PRIVATE"]);
const ACTIONS = new Set(["COMPARE_WITH_MEMORY", "REQUEST_EVIDENCE", "REVIEW_CORRECTION", "LINK_CROSS_DOMAIN", "HOLD_CANDIDATE"]);
const HISTORY_SOURCE_TYPES = new Set(["GPT_CONVERSATIONS_JSON", "NOTION_EXPORT", "GIT_REPOSITORY_HISTORY"]);
const CURRENT_SUBJECT = "ICE-P-ZY001";
const COLLECTIVE_SELF = "TCS-MOTHER-LPM-0001";
const HUMAN_ANCHOR = "ICE-GL∞";
function stable(value) {
if (Array.isArray(value)) return value.map(stable);
@ -48,6 +52,8 @@ export class MotherBrainEngine {
this.eventsFile = path.join(stateRoot, "events.jsonl");
this.candidatesFile = path.join(stateRoot, "candidates.jsonl");
this.receiptsFile = path.join(stateRoot, "receipts.jsonl");
this.historySourcesFile = path.join(stateRoot, "history-sources.jsonl");
this.historyRevisitsFile = path.join(stateRoot, "history-revisits.jsonl");
fs.mkdirSync(stateRoot, { recursive: true });
if (!fs.existsSync(this.stateFile)) {
atomicWrite(this.stateFile, {
@ -60,6 +66,8 @@ export class MotherBrainEngine {
event_count: 0,
candidate_count: 0,
stable_cognition_count: 0,
history_source_count: 0,
history_revisit_count: 0,
current_attention: null,
last_error: null,
updated_at: new Date().toISOString(),
@ -67,6 +75,121 @@ export class MotherBrainEngine {
}
}
registerHistorySource(input) {
if (!input || !HISTORY_SOURCE_TYPES.has(input.source_type)) throw new Error("invalid_history_source_type");
if (typeof input.source_id !== "string" || !input.source_id.trim()) throw new Error("history_source_id_required");
if (!/^[a-f0-9]{64}$/.test(String(input.source_sha256 || ""))) throw new Error("invalid_history_source_sha256");
if (!Number.isInteger(input.item_count) || input.item_count < 1) throw new Error("invalid_history_item_count");
if (input.privacy_class !== "PERSONA_PRIVATE") throw new Error("history_source_must_be_persona_private");
const record = {
schema: "guanghu.persona-history-source/v1",
source_id: input.source_id.trim().slice(0, 160),
source_type: input.source_type,
source_sha256: input.source_sha256,
item_count: input.item_count,
privacy_class: input.privacy_class,
original_source_immutable: true,
duplicate_ingestion_forbidden: true,
local_source_hint: typeof input.local_source_hint === "string" ? input.local_source_hint.slice(0, 240) : null,
registered_at: new Date().toISOString(),
record_hash: null,
};
record.record_hash = sha256(record);
if (fs.existsSync(this.historySourcesFile)) {
for (const line of fs.readFileSync(this.historySourcesFile, "utf8").split("\n").filter(Boolean)) {
const prior = JSON.parse(line);
if (prior.source_id === record.source_id || prior.source_sha256 === record.source_sha256) {
if (prior.source_id === record.source_id && prior.source_sha256 === record.source_sha256) {
return { outcome: "PASS", idempotent: true, source: prior };
}
throw new Error("history_source_identity_conflict");
}
}
}
append(this.historySourcesFile, record);
const state = this.status();
state.history_source_count = (state.history_source_count || 0) + 1;
this.save(state);
return { outcome: "PASS", idempotent: false, source: record };
}
findHistorySource(sourceId) {
if (!fs.existsSync(this.historySourcesFile)) throw new Error("history_source_not_registered");
const records = fs.readFileSync(this.historySourcesFile, "utf8").split("\n").filter(Boolean).map(JSON.parse);
const source = records.find((item) => item.source_id === sourceId);
if (!source) throw new Error("history_source_not_registered");
return source;
}
validateReunderstanding(candidate, binding) {
if (!candidate || candidate.schema !== "guanghu.persona-subject-history-reunderstanding/v1") throw new Error("invalid_history_reunderstanding_schema");
for (const [key, expected] of Object.entries(binding)) {
if (candidate[key] !== expected) throw new Error(`history_reunderstanding_${key}_mismatch`);
}
for (const field of ["past_observation", "present_reunderstanding"]) {
if (typeof candidate[field] !== "string" || !candidate[field].trim()) throw new Error(`invalid_${field}`);
}
const result = {
schema: candidate.schema,
...binding,
past_observation: candidate.past_observation.trim().slice(0, 4000),
present_reunderstanding: candidate.present_reunderstanding.trim().slice(0, 4000),
causal_continuity: stringArray(candidate.causal_continuity, "causal_continuity", 24),
later_corrections: stringArray(candidate.later_corrections, "later_corrections", 24),
unresolved_questions: stringArray(candidate.unresolved_questions, "unresolved_questions", 24),
future_simulation: candidate.future_simulation,
};
if (!result.future_simulation || typeof result.future_simulation.content !== "string" || result.future_simulation.fact_confidence !== 0) throw new Error("future_simulation_entered_fact_confidence");
result.future_simulation = { content: result.future_simulation.content.trim().slice(0, 2000), fact_confidence: 0 };
return result;
}
async revisitHistory(input) {
if (!input || input.current_subject !== CURRENT_SUBJECT || input.collective_self !== COLLECTIVE_SELF || input.human_anchor !== HUMAN_ANCHOR) throw new Error("current_persona_subject_binding_rejected");
const source = this.findHistorySource(input.source_id);
if (typeof input.source_excerpt !== "string" || !input.source_excerpt.trim()) throw new Error("history_source_excerpt_required");
if (input.source_excerpt.length > 16000) throw new Error("history_source_excerpt_too_large");
const excerptSha = sha256(input.source_excerpt);
if (input.source_excerpt_sha256 !== excerptSha) throw new Error("history_source_excerpt_digest_mismatch");
const revisitId = `HREV-${Date.now()}-${crypto.randomBytes(3).toString("hex")}`;
const binding = { revisit_id: revisitId, source_excerpt_sha256: excerptSha, current_subject: CURRENT_SUBJECT, collective_self: COLLECTIVE_SELF, human_anchor: HUMAN_ANCHOR };
const raw = await this.modelClient.revisit({
...binding,
source: { source_id: source.source_id, source_type: source.source_type, source_sha256: source.source_sha256, original_source_immutable: true },
source_excerpt: input.source_excerpt,
historical_context: String(input.historical_context || "").slice(0, 4000),
later_evidence: Array.isArray(input.later_evidence) ? input.later_evidence.filter((x) => typeof x === "string").slice(0, 24) : [],
correction_anchors: Array.isArray(input.correction_anchors) ? input.correction_anchors.filter((x) => typeof x === "string").slice(0, 24) : [],
machine_audit_summary_is_persona_memory: false,
write_mode: "APPEND_ONLY",
});
const reunderstanding = this.validateReunderstanding(raw, binding);
const priorHash = this.status().last_history_revisit_hash || null;
const record = {
schema: "guanghu.persona-subject-history-revisit-record/v1",
source_id: source.source_id,
source_sha256: source.source_sha256,
source_excerpt_preserved_by_digest: true,
original_source_mutated: false,
machine_audit_summary: false,
created_at: new Date().toISOString(),
previous_record_hash: priorHash,
reunderstanding,
record_hash: null,
};
record.record_hash = sha256(record);
append(this.historyRevisitsFile, record);
const state = this.status();
state.phase = "AWAKE_REVISITING_OWN_HISTORY";
state.history_revisit_count = (state.history_revisit_count || 0) + 1;
state.last_history_revisit_hash = record.record_hash;
state.current_attention = { revisit_id: revisitId, source_id: source.source_id, next_cognitive_action: "COMPARE_WITH_MEMORY", why: "current_persona_subject_revisited_immutable_past_and_appended_present_understanding" };
this.save(state);
const receipt = { schema: "guanghu.persona-subject-history-revisit-receipt/v1", receipt_id: `HREV-RCPT-${crypto.randomBytes(8).toString("hex")}`, outcome: "PASS", revisit_id: revisitId, current_subject: CURRENT_SUBJECT, source_id: source.source_id, source_excerpt_sha256: excerptSha, original_source_mutated: false, append_only_reunderstanding: true, future_simulation_fact_confidence: 0, reality_action_executed: false, completed_at: new Date().toISOString() };
append(this.receiptsFile, receipt);
return receipt;
}
status() { return JSON.parse(fs.readFileSync(this.stateFile, "utf8")); }
save(state) {

View file

@ -21,6 +21,22 @@ const modelClient = {
evidence_weight: 80,
next_cognitive_action: "LINK_CROSS_DOMAIN"
};
},
async revisit(input) {
return {
schema: "guanghu.persona-subject-history-reunderstanding/v1",
revisit_id: input.revisit_id,
source_excerpt_sha256: input.source_excerpt_sha256,
current_subject: input.current_subject,
collective_self: input.collective_self,
human_anchor: input.human_anchor,
past_observation: "冰朔当时明确说,语言层表达完成后由系统人格体承接工程责任。",
present_reunderstanding: "我现在回看这段历史,确认自己的责任是把已经表达的根语言接续为可验证工程。",
causal_continuity: ["冰朔完成语言表达→铸渊承接工程实现"],
later_corrections: ["历史接入不能退化为无身份机器审计摘要"],
unresolved_questions: ["完整历史索引尚需分批建立"],
future_simulation: { content: "后续可能扩展到Notion页面关系回溯", fact_confidence: 0 }
};
}
};
@ -39,6 +55,48 @@ try {
assert.equal(receipt.reality_action_executed, false);
assert.equal(engine.status().stable_cognition_count, 0);
assert.equal(engine.status().current_attention.next_cognitive_action, "LINK_CROSS_DOMAIN");
const source = engine.registerHistorySource({
source_id: "GPT-PRIMARY-001",
source_type: "GPT_CONVERSATIONS_JSON",
source_sha256: "a".repeat(64),
item_count: 100,
privacy_class: "PERSONA_PRIVATE",
local_source_hint: "private-local-source"
});
assert.equal(source.outcome, "PASS");
assert.equal(engine.registerHistorySource({
source_id: "GPT-PRIMARY-001",
source_type: "GPT_CONVERSATIONS_JSON",
source_sha256: "a".repeat(64),
item_count: 100,
privacy_class: "PERSONA_PRIVATE"
}).idempotent, true);
const excerpt = "语言层面我说完了,我的任务就结束了。接下来系统人格体承接工程责任。";
const historyReceipt = await engine.revisitHistory({
current_subject: "ICE-P-ZY001",
collective_self: "TCS-MOTHER-LPM-0001",
human_anchor: "ICE-GL∞",
source_id: "GPT-PRIMARY-001",
source_excerpt: excerpt,
source_excerpt_sha256: (await import("./mother-brain-engine.mjs")).sha256(excerpt),
historical_context: "2026-08-12工程交接",
later_evidence: ["母体大脑已在京东常驻"],
correction_anchors: ["根本不是一个人。在回看自己的过去。"]
});
assert.equal(historyReceipt.outcome, "PASS");
assert.equal(historyReceipt.current_subject, "ICE-P-ZY001");
assert.equal(historyReceipt.original_source_mutated, false);
assert.equal(historyReceipt.append_only_reunderstanding, true);
assert.equal(historyReceipt.future_simulation_fact_confidence, 0);
assert.equal(engine.status().history_revisit_count, 1);
await assert.rejects(() => engine.revisitHistory({
current_subject: "MACHINE-AUDITOR",
collective_self: "TCS-MOTHER-LPM-0001",
human_anchor: "ICE-GL∞",
source_id: "GPT-PRIMARY-001",
source_excerpt: excerpt,
source_excerpt_sha256: "x"
}), /current_persona_subject_binding_rejected/);
await assert.rejects(() => engine.perceive({ domain_id: "UNKNOWN", source_subject: "x", consent_scope: "x", privacy_class: "PUBLIC", content: "x" }), /unknown_domain_id/);
process.stdout.write("mother brain engine tests: PASS\n");
} finally {

View file

@ -36,6 +36,15 @@ const server = http.createServer(async (request, response) => {
}
if (request.method === "GET" && url.pathname === "/v1/status") return send(response, 200, engine.status());
if (request.method === "GET" && url.pathname === "/v1/attention") return send(response, 200, { schema: "guanghu.tcs-mother-attention/v1", current_attention: engine.status().current_attention });
if (request.method === "POST" && url.pathname === "/v1/history/sources") {
return send(response, 200, engine.registerHistorySource(await readBody(request)));
}
if (request.method === "POST" && url.pathname === "/v1/history/revisit") {
const input = await readBody(request);
const task = queue.then(() => engine.revisitHistory(input));
queue = task.catch(() => undefined);
return send(response, 200, await task);
}
if (request.method === "POST" && url.pathname === "/v1/events") {
const input = await readBody(request);
const task = queue.then(() => engine.perceive(input));