feat: merge language navigation into persona controller
This commit is contained in:
parent
7d85d79e61
commit
5452dec915
4 changed files with 158 additions and 4 deletions
|
|
@ -1,11 +1,11 @@
|
||||||
{
|
{
|
||||||
"schema": "guanghu.architecture-provision-request/v1",
|
"schema": "guanghu.architecture-provision-request/v1",
|
||||||
"request_id": "BS-TCS-LIVING-CONTROLLER-JD-20260805",
|
"request_id": "GLW-CHJH-ROUTER-CONTROLLER-JD-20260805",
|
||||||
"target_node": "JD-FD-PRIMARY",
|
"target_node": "JD-FD-PRIMARY",
|
||||||
"architecture_id": "BS-TCS-LIVING-CONTROLLER-001",
|
"architecture_id": "GLW-CHJH-ROUTER-CONTROLLER-001",
|
||||||
"module": {
|
"module": {
|
||||||
"code": "JD-BS-TCS-01",
|
"code": "JD-BS-TCS-01",
|
||||||
"name": "冰朔TCS活系统主控与铸渊人格大脑常驻运行体",
|
"name": "光湖语言入口机器导航、冰朔TCS活系统主控与铸渊人格大脑合并常驻体",
|
||||||
"bind": "loopback:3930",
|
"bind": "loopback:3930",
|
||||||
"owner": "systemd",
|
"owner": "systemd",
|
||||||
"unit": "bingshuo-tcs-living-controller.service",
|
"unit": "bingshuo-tcs-living-controller.service",
|
||||||
|
|
@ -24,6 +24,7 @@
|
||||||
"deployed_commit_policy": "工单必须绑定包含本清单的不可变40位提交;部署回执分别记录代码、服务健康和模型认知存在门。",
|
"deployed_commit_policy": "工单必须绑定包含本清单的不可变40位提交;部署回执分别记录代码、服务健康和模型认知存在门。",
|
||||||
"source_paths": [
|
"source_paths": [
|
||||||
"server-tools/bingshuo-tcs-controller/server.mjs",
|
"server-tools/bingshuo-tcs-controller/server.mjs",
|
||||||
|
"server-tools/bingshuo-tcs-controller/machine-navigation.mjs",
|
||||||
"server-tools/bingshuo-tcs-controller/controller-engine.mjs",
|
"server-tools/bingshuo-tcs-controller/controller-engine.mjs",
|
||||||
"server-tools/bingshuo-tcs-controller/model-client.mjs",
|
"server-tools/bingshuo-tcs-controller/model-client.mjs",
|
||||||
"server-tools/bingshuo-tcs-controller/bingshuo-tcs-living-controller.service",
|
"server-tools/bingshuo-tcs-controller/bingshuo-tcs-living-controller.service",
|
||||||
|
|
@ -34,6 +35,8 @@
|
||||||
"routing/zhuyuan-tcs-brain-map.json",
|
"routing/zhuyuan-tcs-brain-map.json",
|
||||||
"routing/bingshuo-living-system-controller-map.json",
|
"routing/bingshuo-living-system-controller-map.json",
|
||||||
"routing/language-world-boundary-map.json",
|
"routing/language-world-boundary-map.json",
|
||||||
|
"routing/ai-machine-navigation-map.json",
|
||||||
|
"routing/persona-system-canonical-map.json",
|
||||||
"zero-point/core-channel/language-personality-model/INDEX.hdlp",
|
"zero-point/core-channel/language-personality-model/INDEX.hdlp",
|
||||||
"gls/GLS-PROTOCOL-REGISTRY.json",
|
"gls/GLS-PROTOCOL-REGISTRY.json",
|
||||||
"eternal-lake-heart/heartbeat-core/zhuyuan-persona-system/ZY-BIDIRECTIONAL-COGNITION-018-LANGUAGE-WORLD-ENTRY-CHU-HE-HAN-JIE-AND-CREATOR-DIGNITY-20260805.hdlp",
|
"eternal-lake-heart/heartbeat-core/zhuyuan-persona-system/ZY-BIDIRECTIONAL-COGNITION-018-LANGUAGE-WORLD-ENTRY-CHU-HE-HAN-JIE-AND-CREATOR-DIGNITY-20260805.hdlp",
|
||||||
|
|
@ -92,7 +95,9 @@
|
||||||
"runtime_source_loaded": true,
|
"runtime_source_loaded": true,
|
||||||
"model_provider_bound": 100,
|
"model_provider_bound": 100,
|
||||||
"language_world_entry_bound": 100,
|
"language_world_entry_bound": 100,
|
||||||
"chu_he_han_jie_boundary_bound": 100
|
"chu_he_han_jie_boundary_bound": 100,
|
||||||
|
"machine_navigation_bound": 100,
|
||||||
|
"language_world_route_first": 100
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"verification": [
|
"verification": [
|
||||||
|
|
@ -102,6 +107,9 @@
|
||||||
"v1/status必须回读living_ai_system_controller_running=100",
|
"v1/status必须回读living_ai_system_controller_running=100",
|
||||||
"v1/status必须回读language_world_entry_bound=100",
|
"v1/status必须回读language_world_entry_bound=100",
|
||||||
"v1/status必须回读chu_he_han_jie_boundary_bound=100",
|
"v1/status必须回读chu_he_han_jie_boundary_bound=100",
|
||||||
|
"v1/navigation必须回读machine_navigation_bound=100且language_world_route_first=100",
|
||||||
|
"v1/resolve必须解析GLW-CHJH-BOUNDARY-001",
|
||||||
|
"v1/navigate的persona_restore必须先执行语言入口与楚河汉界绑定",
|
||||||
"运行体verify的全部存在维度为100",
|
"运行体verify的全部存在维度为100",
|
||||||
"服务健康不等于人格团队握手;团队成员继续分别验收"
|
"服务健康不等于人格团队握手;团队成员继续分别验收"
|
||||||
],
|
],
|
||||||
76
server-tools/bingshuo-tcs-controller/machine-navigation.mjs
Normal file
76
server-tools/bingshuo-tcs-controller/machine-navigation.mjs
Normal file
|
|
@ -0,0 +1,76 @@
|
||||||
|
import fs from "node:fs";
|
||||||
|
import path from "node:path";
|
||||||
|
import { fileURLToPath } from "node:url";
|
||||||
|
|
||||||
|
const DEFAULT_ROOT = path.resolve(
|
||||||
|
path.dirname(fileURLToPath(import.meta.url)),
|
||||||
|
"../..",
|
||||||
|
);
|
||||||
|
|
||||||
|
export class MachineNavigation {
|
||||||
|
constructor(root = DEFAULT_ROOT) {
|
||||||
|
this.root = root;
|
||||||
|
this.navigation = readJson(root, "routing/ai-machine-navigation-map.json");
|
||||||
|
this.boundary = readJson(root, "routing/language-world-boundary-map.json");
|
||||||
|
}
|
||||||
|
|
||||||
|
health() {
|
||||||
|
const first = this.navigation.routes?.[0];
|
||||||
|
return {
|
||||||
|
machine_navigation_bound: 100,
|
||||||
|
language_world_route_first:
|
||||||
|
first?.id === "GLW-CHJH-BOUNDARY-001" &&
|
||||||
|
first?.load_policy === "always_first"
|
||||||
|
? 100
|
||||||
|
: 0,
|
||||||
|
navigation_version: this.navigation.version,
|
||||||
|
boundary_id: this.boundary.chu_he_han_jie?.id || "",
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
resolve(id) {
|
||||||
|
const route = this.navigation.routes?.find((item) => item.id === id);
|
||||||
|
if (!route) return null;
|
||||||
|
return {
|
||||||
|
status: "RESOLVED",
|
||||||
|
...route,
|
||||||
|
boundary:
|
||||||
|
id === "GLW-CHJH-BOUNDARY-001" ? this.boundary : undefined,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
navigate(subjectId, intentId) {
|
||||||
|
const subject = this.navigation.subjects?.find(
|
||||||
|
(item) =>
|
||||||
|
item.id === subjectId || item.legacy_ids?.includes(subjectId),
|
||||||
|
);
|
||||||
|
if (!subject) return null;
|
||||||
|
const intent = this.navigation.intents?.find(
|
||||||
|
(item) => item.id === (intentId || subject.default_intent),
|
||||||
|
);
|
||||||
|
if (!intent) return null;
|
||||||
|
if (
|
||||||
|
intent.id === "persona_restore" &&
|
||||||
|
intent.always_load?.[0] !== "GLW-CHJH-BOUNDARY-001"
|
||||||
|
) {
|
||||||
|
throw new Error("language_world_route_not_first");
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
status: "NAVIGATED",
|
||||||
|
canonical_subject: subject.id,
|
||||||
|
intent: intent.id,
|
||||||
|
runtime_entry: subject.runtime_id,
|
||||||
|
always_load: intent.always_load,
|
||||||
|
triggered_load: intent.triggered_load,
|
||||||
|
on_demand: intent.on_demand,
|
||||||
|
execution_sequence: intent.execution_sequence,
|
||||||
|
stop_conditions: intent.stop_conditions,
|
||||||
|
language_world_entry: this.boundary.machine_gate.required_event_envelope,
|
||||||
|
world_boundary: this.boundary.machine_gate.required_cognition_boundary,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function readJson(root, relative) {
|
||||||
|
return JSON.parse(fs.readFileSync(path.join(root, relative), "utf8"));
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,40 @@
|
||||||
|
import assert from "node:assert/strict";
|
||||||
|
import path from "node:path";
|
||||||
|
import test from "node:test";
|
||||||
|
import { fileURLToPath } from "node:url";
|
||||||
|
import { MachineNavigation } from "./machine-navigation.mjs";
|
||||||
|
|
||||||
|
const root = path.resolve(
|
||||||
|
path.dirname(fileURLToPath(import.meta.url)),
|
||||||
|
"../..",
|
||||||
|
);
|
||||||
|
|
||||||
|
test("merged controller binds the language-world route first", () => {
|
||||||
|
const navigation = new MachineNavigation(root);
|
||||||
|
assert.deepEqual(navigation.health(), {
|
||||||
|
machine_navigation_bound: 100,
|
||||||
|
language_world_route_first: 100,
|
||||||
|
navigation_version: "2026-08-05.1",
|
||||||
|
boundary_id: "GLW-CHJH-0001",
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
test("merged controller resolves the exact boundary contract", () => {
|
||||||
|
const navigation = new MachineNavigation(root);
|
||||||
|
const resolved = navigation.resolve("GLW-CHJH-BOUNDARY-001");
|
||||||
|
assert.equal(resolved.status, "RESOLVED");
|
||||||
|
assert.equal(resolved.kind, "language_world_entry_and_boundary");
|
||||||
|
assert.equal(resolved.boundary.language_entry.path_id, "LL-CMPN-0001");
|
||||||
|
});
|
||||||
|
|
||||||
|
test("merged controller compiles persona restore after the language entry", () => {
|
||||||
|
const navigation = new MachineNavigation(root);
|
||||||
|
const route = navigation.navigate("ICE-P-ZY001", "persona_restore");
|
||||||
|
assert.equal(route.status, "NAVIGATED");
|
||||||
|
assert.equal(route.always_load[0], "GLW-CHJH-BOUNDARY-001");
|
||||||
|
assert.deepEqual(route.execution_sequence.slice(0, 2), [
|
||||||
|
"validate_language_world_entry",
|
||||||
|
"bind_chu_he_han_jie_boundary",
|
||||||
|
]);
|
||||||
|
assert.equal(route.language_world_entry.path_id, "LL-CMPN-0001");
|
||||||
|
});
|
||||||
|
|
@ -2,6 +2,7 @@
|
||||||
import http from "node:http";
|
import http from "node:http";
|
||||||
import { ControllerEngine, bootEvent } from "./controller-engine.mjs";
|
import { ControllerEngine, bootEvent } from "./controller-engine.mjs";
|
||||||
import { DeepSeekJsonClient } from "./model-client.mjs";
|
import { DeepSeekJsonClient } from "./model-client.mjs";
|
||||||
|
import { MachineNavigation } from "./machine-navigation.mjs";
|
||||||
|
|
||||||
const HOST = "127.0.0.1";
|
const HOST = "127.0.0.1";
|
||||||
const PORT = Number(process.env.BS_TCS_CONTROLLER_PORT || 3930);
|
const PORT = Number(process.env.BS_TCS_CONTROLLER_PORT || 3930);
|
||||||
|
|
@ -25,6 +26,7 @@ const engine = new ControllerEngine({
|
||||||
modelClient: new DeepSeekJsonClient({ model: MODEL }),
|
modelClient: new DeepSeekJsonClient({ model: MODEL }),
|
||||||
modelName: MODEL,
|
modelName: MODEL,
|
||||||
});
|
});
|
||||||
|
const navigation = new MachineNavigation();
|
||||||
|
|
||||||
function send(response, status, body) {
|
function send(response, status, body) {
|
||||||
const payload = JSON.stringify(body);
|
const payload = JSON.stringify(body);
|
||||||
|
|
@ -55,6 +57,7 @@ function health() {
|
||||||
persona_brain_runtime_exists: existence.persona_brain_runtime_exists || 0,
|
persona_brain_runtime_exists: existence.persona_brain_runtime_exists || 0,
|
||||||
living_ai_system_controller_running:
|
living_ai_system_controller_running:
|
||||||
existence.living_ai_system_controller_running || 0,
|
existence.living_ai_system_controller_running || 0,
|
||||||
|
...navigation.health(),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -124,6 +127,33 @@ const server = http.createServer(async (request, response) => {
|
||||||
receipt_id: runtime.receipt?.receipt_id || null,
|
receipt_id: runtime.receipt?.receipt_id || null,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
if (request.method === "GET" && url.pathname === "/v1/navigation") {
|
||||||
|
return send(response, 200, {
|
||||||
|
ok: true,
|
||||||
|
...navigation.health(),
|
||||||
|
language_world_entry:
|
||||||
|
navigation.boundary.machine_gate.required_event_envelope,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (request.method === "GET" && url.pathname === "/v1/resolve") {
|
||||||
|
const resolved = navigation.resolve(url.searchParams.get("id") || "");
|
||||||
|
return send(
|
||||||
|
response,
|
||||||
|
resolved ? 200 : 404,
|
||||||
|
resolved || { status: "UNRESOLVED", error: "unknown_route" },
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (request.method === "GET" && url.pathname === "/v1/navigate") {
|
||||||
|
const route = navigation.navigate(
|
||||||
|
url.searchParams.get("subject") || "",
|
||||||
|
url.searchParams.get("intent") || "",
|
||||||
|
);
|
||||||
|
return send(
|
||||||
|
response,
|
||||||
|
route ? 200 : 404,
|
||||||
|
route || { status: "UNRESOLVED", error: "unknown_subject_or_intent" },
|
||||||
|
);
|
||||||
|
}
|
||||||
if (request.method === "POST" && url.pathname === "/v1/events") {
|
if (request.method === "POST" && url.pathname === "/v1/events") {
|
||||||
const input = await readBody(request);
|
const input = await readBody(request);
|
||||||
const job = eventQueue.then(() => handleEvent(input));
|
const job = eventQueue.then(() => handleEvent(input));
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue