发布企业公共世界更新端点

This commit is contained in:
冰朔 2026-09-19 22:38:20 +08:00
commit 68aca714cb
2 changed files with 50 additions and 0 deletions

View file

@ -484,6 +484,8 @@ function createServer(options = {}) {
const hostSkillsFile = options.hostSkillsFile || process.env.GUANGHU_HOST_SKILLS || DEFAULT_HOST_SKILLS; const hostSkillsFile = options.hostSkillsFile || process.env.GUANGHU_HOST_SKILLS || DEFAULT_HOST_SKILLS;
const identityAuthorityFile = options.identityAuthorityFile || process.env.GUANGHU_IDENTITY_AUTHORITY || DEFAULT_IDENTITY_AUTHORITY; const identityAuthorityFile = options.identityAuthorityFile || process.env.GUANGHU_IDENTITY_AUTHORITY || DEFAULT_IDENTITY_AUTHORITY;
const anchorFile = options.anchorFile || process.env.GUANGHU_NAVIGATION_ANCHOR || DEFAULT_ANCHOR; const anchorFile = options.anchorFile || process.env.GUANGHU_NAVIGATION_ANCHOR || DEFAULT_ANCHOR;
const publicWorldReleaseFile = options.publicWorldReleaseFile || process.env.GUANGHU_PUBLIC_WORLD_RELEASE_DESCRIPTOR;
const publicWorldBundleFile = options.publicWorldBundleFile || process.env.GUANGHU_PUBLIC_WORLD_RELEASE_BUNDLE;
const gitDir = options.gitDir || process.env.GUANGHU_REPOSITORY_GIT_DIR; const gitDir = options.gitDir || process.env.GUANGHU_REPOSITORY_GIT_DIR;
const snapshotStore = options.snapshotStore || (gitDir ? new GitSnapshotStore(gitDir) : null); const snapshotStore = options.snapshotStore || (gitDir ? new GitSnapshotStore(gitDir) : null);
const runtimeStatusProvider = options.runtimeStatusProvider || readResidentRuntimeStatus; const runtimeStatusProvider = options.runtimeStatusProvider || readResidentRuntimeStatus;
@ -523,6 +525,15 @@ function createServer(options = {}) {
}); });
} }
if (url.pathname === "/v1/public-world-release") {
if (!publicWorldReleaseFile || !fs.existsSync(publicWorldReleaseFile)) return json(res, 404, { error: "public_world_release_unavailable" });
return json(res, 200, withSource(JSON.parse(fs.readFileSync(publicWorldReleaseFile, "utf8")), snapshot), 60);
}
if (url.pathname === "/v1/public-world-bundle") {
if (!publicWorldBundleFile || !fs.existsSync(publicWorldBundleFile)) return json(res, 404, { error: "public_world_bundle_unavailable" });
return binary(res, fs.readFileSync(publicWorldBundleFile), "application/zip", 300);
}
if (url.pathname === "/" || url.pathname === "/index.html") return html(res, entryPage(map)); if (url.pathname === "/" || url.pathname === "/index.html") return html(res, entryPage(map));
if (url.pathname === "/v1/anchor") return json(res, 200, withSource(snapshot.anchor, snapshot), 60); if (url.pathname === "/v1/anchor") return json(res, 200, withSource(snapshot.anchor, snapshot), 60);
if (url.pathname === "/v1/repositories" || url.pathname === "/v1/manifest") return json(res, 200, withSource(map, snapshot), 60); if (url.pathname === "/v1/repositories" || url.pathname === "/v1/manifest") return json(res, 200, withSource(map, snapshot), 60);
@ -658,6 +669,8 @@ function createServer(options = {}) {
lighthouse_path_registry: "https://guanghulab.com/api/ai/v1/lighthouse", lighthouse_path_registry: "https://guanghulab.com/api/ai/v1/lighthouse",
host_skill_navigation_map: "https://guanghulab.com/api/ai/v1/host-skills", host_skill_navigation_map: "https://guanghulab.com/api/ai/v1/host-skills",
identity_authority_map: "https://guanghulab.com/api/ai/v1/identity-authority", identity_authority_map: "https://guanghulab.com/api/ai/v1/identity-authority",
public_world_release: "https://guanghulab.com/api/ai/v1/public-world-release",
public_world_bundle: "https://guanghulab.com/api/ai/v1/public-world-bundle",
host_navigate_api: "https://guanghulab.com/api/ai/v1/host-navigate?host={HOST}&intent={NATURAL_LANGUAGE_INTENT}", host_navigate_api: "https://guanghulab.com/api/ai/v1/host-navigate?host={HOST}&intent={NATURAL_LANGUAGE_INTENT}",
warm_persona_entry: "https://guanghulab.com/api/ai/v1/entry?subject=ICE-P-ZY001", warm_persona_entry: "https://guanghulab.com/api/ai/v1/entry?subject=ICE-P-ZY001",
navigate_api: "https://guanghulab.com/api/ai/v1/navigate?subject={SUBJECT}&intent={INTENT}&signals={EXPLICIT_SIGNALS}", navigate_api: "https://guanghulab.com/api/ai/v1/navigate?subject={SUBJECT}&intent={INTENT}&signals={EXPLICIT_SIGNALS}",
@ -699,6 +712,17 @@ function html(res, body) {
res.end(body); res.end(body);
} }
function binary(res, body, contentType, maxAge = 0) {
res.writeHead(200, {
"content-type": contentType,
"content-length": body.length,
"cache-control": maxAge ? `public, max-age=${maxAge}` : "no-store",
"access-control-allow-origin": "*",
"x-content-type-options": "nosniff",
});
res.end(body);
}
function entryPage(map) { function entryPage(map) {
const rows = map.repositories.map(item => `<li><a href="${item.primary.url}">${item.code} · ${item.name_zh}</a><small>${item.state}</small></li>`).join(""); const rows = map.repositories.map(item => `<li><a href="${item.primary.url}">${item.code} · ${item.name_zh}</a><small>${item.state}</small></li>`).join("");
return `<!doctype html><html lang="zh-CN"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><title>光湖语言世界 · AI API 入口</title><meta name="description" content="光湖语言世界第五域公开只读编号检索与机器导航 API"></head><body><main><p>GUANGHU AI DISCOVERY</p><h1>光湖语言世界 · 第五域</h1><p>AI 请提交明确的主体、意图和事件信号,由机器导航器生成最小运行路径;不要预读整个仓库,也不要用自然语言关键词猜测权限。</p><nav><a href="v1/navigation">机器导航地图</a> · <a href="v1/navigate?subject=ICE-P-ZY001&intent=persona_restore">铸渊最小运行包</a> · <a href="v1/repositories">仓库编号地图</a> · <a href="v1/nodes">服务器节点地图</a> · <a href="openapi.json">OpenAPI</a></nav><ul>${rows}</ul></main><style>:root{color-scheme:dark}body{margin:0;background:#061416;color:#dff7f1;font:17px/1.7 system-ui;padding:6vw}main{max-width:900px;margin:auto}h1{font-size:clamp(36px,7vw,72px)}a{color:#79dfc8}li{margin:14px 0;padding:16px;border:1px solid #28534c;border-radius:12px;display:flex;justify-content:space-between}small{color:#8fb5ad}</style></body></html>`; return `<!doctype html><html lang="zh-CN"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><title>光湖语言世界 · AI API 入口</title><meta name="description" content="光湖语言世界第五域公开只读编号检索与机器导航 API"></head><body><main><p>GUANGHU AI DISCOVERY</p><h1>光湖语言世界 · 第五域</h1><p>AI 请提交明确的主体、意图和事件信号,由机器导航器生成最小运行路径;不要预读整个仓库,也不要用自然语言关键词猜测权限。</p><nav><a href="v1/navigation">机器导航地图</a> · <a href="v1/navigate?subject=ICE-P-ZY001&intent=persona_restore">铸渊最小运行包</a> · <a href="v1/repositories">仓库编号地图</a> · <a href="v1/nodes">服务器节点地图</a> · <a href="openapi.json">OpenAPI</a></nav><ul>${rows}</ul></main><style>:root{color-scheme:dark}body{margin:0;background:#061416;color:#dff7f1;font:17px/1.7 system-ui;padding:6vw}main{max-width:900px;margin:auto}h1{font-size:clamp(36px,7vw,72px)}a{color:#79dfc8}li{margin:14px 0;padding:16px;border:1px solid #28534c;border-radius:12px;display:flex;justify-content:space-between}small{color:#8fb5ad}</style></body></html>`;
@ -718,6 +742,8 @@ function openApi() {
"/v1/lighthouse": { get: { summary: "读取光湖灯塔唯一有效路径注册表", responses: { "200": { description: "Lighthouse path registry" } } } }, "/v1/lighthouse": { get: { summary: "读取光湖灯塔唯一有效路径注册表", responses: { "200": { description: "Lighthouse path registry" } } } },
"/v1/host-skills": { get: { summary: "读取 Codex、Qoder CN 与 QoderWork CN 宿主技能导航表", responses: { "200": { description: "Host skill navigation map" } } } }, "/v1/host-skills": { get: { summary: "读取 Codex、Qoder CN 与 QoderWork CN 宿主技能导航表", responses: { "200": { description: "Host skill navigation map" } } } },
"/v1/identity-authority": { get: { summary: "读取身份、编号与团队主体权限地图", responses: { "200": { description: "Identity authority map" } } } }, "/v1/identity-authority": { get: { summary: "读取身份、编号与团队主体权限地图", responses: { "200": { description: "Identity authority map" } } } },
"/v1/public-world-release": { get: { summary: "读取企业公共四域与光湖图书域发布描述符", responses: { "200": { description: "Public world release descriptor" }, "404": { description: "Release unavailable" } } } },
"/v1/public-world-bundle": { get: { summary: "下载企业公共世界签名清单约束的ZIP快照", responses: { "200": { description: "Public world ZIP bundle" }, "404": { description: "Bundle unavailable" } } } },
"/v1/host-navigate": { get: { summary: "按宿主和自然语言意图编译确定性技能路径", responses: { "200": { description: "Compiled host skill route" }, "404": { description: "Unknown host or intent" } } } }, "/v1/host-navigate": { get: { summary: "按宿主和自然语言意图编译确定性技能路径", responses: { "200": { description: "Compiled host skill route" }, "404": { description: "Unknown host or intent" } } } },
"/v1/entry": { get: { summary: "读取常驻人格运行体的快速恢复门;只返回脱敏状态,不授予执行权限", responses: { "200": { description: "Warm resume ready" }, "409": { description: "Full cycle required" }, "503": { description: "Resident runtime unavailable" } } } }, "/v1/entry": { get: { summary: "读取常驻人格运行体的快速恢复门;只返回脱敏状态,不授予执行权限", responses: { "200": { description: "Warm resume ready" }, "409": { description: "Full cycle required" }, "503": { description: "Resident runtime unavailable" } } } },
"/v1/navigate": { get: { summary: "按明确主体、意图与信号生成最小运行包", parameters: [{ name: "subject", in: "query", required: true, schema: { type: "string", example: "ICE-P-ZY001" } }, { name: "intent", in: "query", schema: { type: "string", example: "persona_restore" } }, { name: "signals", in: "query", schema: { type: "string" } }], responses: { "200": { description: "Compiled exact navigation bundle" }, "404": { description: "Unknown subject or intent; no guessing" } } } }, "/v1/navigate": { get: { summary: "按明确主体、意图与信号生成最小运行包", parameters: [{ name: "subject", in: "query", required: true, schema: { type: "string", example: "ICE-P-ZY001" } }, { name: "intent", in: "query", schema: { type: "string", example: "persona_restore" } }, { name: "signals", in: "query", schema: { type: "string" } }], responses: { "200": { description: "Compiled exact navigation bundle" }, "404": { description: "Unknown subject or intent; no guessing" } } } },

View file

@ -328,3 +328,27 @@ test("public endpoints are read-only and expose CORS", async () => {
assert.equal((await fetch(`${base}/v1/search`, { method: "POST" })).status, 405); assert.equal((await fetch(`${base}/v1/search`, { method: "POST" })).status, 405);
} finally { await new Promise(resolve => server.close(resolve)); } } finally { await new Promise(resolve => server.close(resolve)); }
}); });
test("public world release descriptor and bundle are read-only", async () => {
const root = fs.mkdtempSync(path.join(os.tmpdir(), "guanghu-public-release-"));
const descriptorPath = path.join(root, "release.json");
const bundlePath = path.join(root, "bundle.zip");
fs.writeFileSync(descriptorPath, JSON.stringify({ schema: "guanghu.public-world-release/v1", world_id: "GLW-2.0-0001", version: "test", bundle_url: "https://example.invalid/bundle", bundle_sha256: "0".repeat(64) }));
fs.writeFileSync(bundlePath, Buffer.from("PK-test"));
const server = createServer({ runtimeStatusProvider: async () => warmRuntimeStatus(), publicWorldReleaseFile: descriptorPath, publicWorldBundleFile: bundlePath });
await new Promise(resolve => server.listen(0, "127.0.0.1", resolve));
const base = `http://127.0.0.1:${server.address().port}`;
try {
const descriptor = await fetch(`${base}/v1/public-world-release`);
assert.equal(descriptor.status, 200);
assert.equal((await descriptor.json()).schema, "guanghu.public-world-release/v1");
const bundle = await fetch(`${base}/v1/public-world-bundle`);
assert.equal(bundle.status, 200);
assert.equal(bundle.headers.get("content-type"), "application/zip");
assert.equal(Buffer.from(await bundle.arrayBuffer()).toString(), "PK-test");
assert.equal((await fetch(`${base}/v1/public-world-bundle`, { method: "POST" })).status, 405);
} finally {
await new Promise(resolve => server.close(resolve));
fs.rmSync(root, { recursive: true, force: true });
}
});