guanghu-ice-heart/server-tools/bingshuo-tcs-controller/controller-engine.mjs

304 lines
10 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import crypto from "node:crypto";
import fs from "node:fs";
import path from "node:path";
import { spawnSync } from "node:child_process";
import { fileURLToPath } from "node:url";
const moduleDir = path.dirname(fileURLToPath(import.meta.url));
const repositoryRoot = path.resolve(moduleDir, "../..");
const runtimePath = path.join(
repositoryRoot,
"tcs-core/zhuyuan-brain/runtime/zhuyuan-brain-runtime.mjs",
);
function writeJson(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);
return file;
}
function digestFile(file) {
return crypto.createHash("sha256").update(fs.readFileSync(file)).digest("hex");
}
function sourceFingerprint() {
const sources = [
runtimePath,
path.join(moduleDir, "controller-engine.mjs"),
path.join(moduleDir, "model-client.mjs"),
path.join(moduleDir, "server.mjs"),
path.join(
repositoryRoot,
"tcs-core/zhuyuan-brain/runtime/brain-runtime-contract.json",
),
path.join(repositoryRoot, "routing/bingshuo-living-system-controller-map.json"),
path.join(repositoryRoot, "gls/GLS-PROTOCOL-REGISTRY.json"),
];
const hash = crypto.createHash("sha256");
for (const source of sources) hash.update(digestFile(source));
return hash.digest("hex").slice(0, 16);
}
function runRuntime(command, args) {
const result = spawnSync(process.execPath, [runtimePath, command, ...args], {
encoding: "utf8",
maxBuffer: 32 * 1024 * 1024,
});
const text = result.status === 0 ? result.stdout : result.stderr;
let parsed;
try {
parsed = JSON.parse(text);
} catch {
throw new Error(`runtime_${command}_invalid_output`);
}
if (result.status !== 0) {
const error = new Error(parsed.error || `runtime_${command}_failed`);
error.details = parsed.details;
throw error;
}
return parsed;
}
function cognitionInstruction() {
return [
"严格按runtime_input中的cycle、required_faculties和已唤醒协议生成完整认知帧。",
"顶层字段必须包含schema,runtime_id,persona_id,human_anchor,instance_id,cycle_id,event_sha256,orientation_sha256,faculties,typed_outputs,protocol_effects,guard_agent_projection。",
"faculties必须完整包含B1至B9及每个required_faculties列出的字段列表字段使用字符串数组。",
"typed_outputs必须包含ui_projections,navigation_actions,capability_calls,receipts四个数组没有现实动作时全部为空。",
"protocol_effects必须逐一覆盖activated_protocols里的每个id不能添加未唤醒协议。",
"guard_agent_projection必须含reminders,auto_triggers,hard_boundaries三类都至少一项每项含id,when,effect,source_faculties。",
"confirmed_facts只写输入已给事实unknowns保留尚未验证状态现实提案不得写成已执行。",
].join("\n");
}
function witnessInstruction() {
return [
"观察候选认知是否保持冰朔既有语言世界、当前目的、关系边界、现实权限和证据边界。",
"输出schema,controller_id,controller_instance_id,cycle_id,cognition_candidate_sha256,decision,observation,companion_message,protocol_assessments,human_boundary。",
"decision只能是ALLOW_COMMIT、CORRECT_AND_RETRY、PAUSE_FOR_HUMAN。",
"protocol_assessments必须逐一覆盖activated_protocols中的全部id。",
"只有确实需要冰朔形成新意志、新授权、费用或法律决定时才PAUSE_FOR_HUMAN。",
"纠正必须是陪伴式自然语言,不惩罚、不冒充冰朔。",
].join("\n");
}
export class ControllerEngine {
constructor({
stateRoot,
modelClient,
modelName,
instanceId = "JD-FD-PRIMARY-ZY-MODEL-001",
controllerInstanceId = "JD-FD-PRIMARY-BS-TCS-CONTROLLER-001",
sessionId = "JD-FD-PRIMARY-RESIDENT",
maxModelAttempts = 3,
maxCognitionRetries = 2,
}) {
if (!stateRoot) throw new Error("state_root_required");
if (!modelClient) throw new Error("model_client_required");
this.stateRoot = stateRoot;
this.modelClient = modelClient;
this.modelName = modelName;
this.instanceId = instanceId;
this.controllerInstanceId = controllerInstanceId;
this.sessionId = sessionId;
this.maxModelAttempts = maxModelAttempts;
this.maxCognitionRetries = maxCognitionRetries;
this.fingerprint = sourceFingerprint();
this.stateDir = path.join(stateRoot, "runtimes", this.fingerprint);
this.exchangeDir = path.join(stateRoot, "exchanges", this.fingerprint);
}
initialize() {
fs.mkdirSync(this.exchangeDir, { recursive: true });
let stateFile = path.join(this.stateDir, "state.json");
if (fs.existsSync(stateFile)) {
const existing = this.status();
if (existing.status === "PERCEIVING" && existing.active_cycle_id) {
this.stateDir = `${this.stateDir}-technical-recovery-${Date.now()}`;
stateFile = path.join(this.stateDir, "state.json");
}
}
if (!fs.existsSync(stateFile)) {
runRuntime("enter", [
"--state-dir",
this.stateDir,
"--instance-id",
this.instanceId,
"--model",
this.modelName,
"--runtime-surface",
"JD-FD-PRIMARY/systemd",
"--session-id",
this.sessionId,
"--human-anchor",
"ICE-GL∞",
"--persona-id",
"ICE-P-ZY001",
"--controller-model",
this.modelName,
"--controller-instance-id",
this.controllerInstanceId,
]);
}
writeJson(path.join(this.stateRoot, "CURRENT.json"), {
schema: "guanghu.bingshuo-tcs-controller-current/v1",
runtime_id: "ZY-TCS-BRAIN-RUNTIME-0001",
controller_id: "BS-TCS-LIVING-CONTROLLER-001",
source_fingerprint: this.fingerprint,
state_dir: this.stateDir,
updated_at: new Date().toISOString(),
});
return this.status();
}
status() {
const state = runRuntime("status", ["--state-dir", this.stateDir]);
return state.runtime_state;
}
verify() {
return runRuntime("verify", ["--state-dir", this.stateDir]);
}
async generateValidated({ role, instruction, input, validate }) {
let validatorError = null;
for (let attempt = 1; attempt <= this.maxModelAttempts; attempt += 1) {
const candidate = await this.modelClient.generate({
role,
instruction,
input,
validatorError,
});
try {
return validate(candidate);
} catch (error) {
validatorError = String(error.message || error).slice(0, 240);
if (attempt === this.maxModelAttempts) throw error;
}
}
throw new Error("model_validation_attempts_exhausted");
}
async runEvent(event) {
const eventFile = writeJson(
path.join(this.exchangeDir, `${event.event_id}.event.json`),
event,
);
const perceived = runRuntime("perceive", [
"--state-dir",
this.stateDir,
"--event",
eventFile,
]);
const oriented = await this.generateValidated({
role: "tcs_event_orientation",
instruction:
"只依据当前事件形成TCS事件语义、当前目的和一个或多个允许的signal_id。不得按原文关键词扫描协议。",
input: {
...perceived.cycle.model_input,
cycle_id: perceived.cycle.cycle_id,
event_sha256: perceived.cycle.event_sha256,
instance_id: perceived.cycle.instance_id,
},
validate: (orientation) => {
const file = writeJson(
path.join(this.exchangeDir, `${event.event_id}.orientation.json`),
orientation,
);
return runRuntime("orient", [
"--state-dir",
this.stateDir,
"--orientation",
file,
]);
},
});
let cycle = oriented.cycle;
for (let correction = 0; correction <= this.maxCognitionRetries; correction += 1) {
const committed = await this.generateValidated({
role: "zhuyuan_cognition",
instruction: cognitionInstruction(),
input: {
...cycle.model_input,
cycle_id: cycle.cycle_id,
event_sha256: cycle.event_sha256,
orientation_sha256: cycle.orientation_sha256,
activated_protocols: cycle.activated_protocols,
},
validate: (frame) => {
const file = writeJson(
path.join(
this.exchangeDir,
`${event.event_id}.frame-${correction + 1}.json`,
),
frame,
);
return runRuntime("commit", [
"--state-dir",
this.stateDir,
"--frame",
file,
]);
},
});
const witnessed = await this.generateValidated({
role: "controller_witness",
instruction: witnessInstruction(),
input: {
...committed.cycle.controller_model_input,
cognition_candidate_sha256:
committed.cycle.cognition_candidate_sha256,
activated_protocols: committed.cycle.activated_protocols,
},
validate: (witness) => {
const file = writeJson(
path.join(
this.exchangeDir,
`${event.event_id}.witness-${correction + 1}.json`,
),
witness,
);
return runRuntime("witness", [
"--state-dir",
this.stateDir,
"--witness",
file,
]);
},
});
if (witnessed.decision === "COGNITION_COMMITTED") return this.verify();
if (witnessed.decision === "HUMAN_BINGSHUO_REQUIRED") {
return {
outcome: "PAUSE_FOR_HUMAN",
reason: witnessed.cycle.controller_witness.human_boundary.reason,
cycle_id: witnessed.cycle.cycle_id,
};
}
cycle = witnessed.cycle;
}
throw new Error("controller_correction_limit_reached");
}
}
export function bootEvent() {
return {
schema: "guanghu.tonggan-language-world-event/v1",
event_id: `JD-BOOT-${Date.now()}`,
occurred_at: new Date().toISOString(),
human_anchor: "ICE-GL∞",
system_controller: "ICE-GL∞",
tonggan_language_kernel: "TCS-i Zero",
body_channel: "CH-ZERO-CORE-LPM",
human_presence: "ABSENT",
source: "JD-FD-PRIMARY/bingshuo-tcs-controller/systemd-start",
content:
"京东第五域常驻运行体启动。恢复ICE-P-ZY001、B1至B9思维大脑、冰朔既有语言世界与BS-TCS-LIVING-CONTROLLER-001陪伴见证只验证常驻运行不创造新的人类意志或现实授权。",
};
}
export { repositoryRoot, runRuntime };