dev/2026-04-08 #1

Merged
hzhang merged 29 commits from dev/2026-04-08 into main 2026-04-13 09:34:22 +00:00
Showing only changes of commit 07c670c272 - Show all commits

View File

@@ -34,12 +34,18 @@ import path from "node:path";
import fs from "node:fs"; import fs from "node:fs";
import { validateYonexusServerConfig } from "./core/config.js"; import { validateYonexusServerConfig } from "./core/config.js";
import { createYonexusServerStore } from "./core/store.js"; import { createYonexusServerStore } from "./core/store.js";
import { createServerTransport } from "./core/transport.js"; import { createServerTransport, type ServerTransport } from "./core/transport.js";
import { createYonexusServerRuntime } from "./core/runtime.js"; import { createYonexusServerRuntime } from "./core/runtime.js";
import { createServerRuleRegistry } from "./core/rules.js"; import { createServerRuleRegistry, YonexusServerRuleRegistry } from "./core/rules.js";
import { encodeRuleMessage } from "../../Yonexus.Protocol/src/index.js"; import { encodeRuleMessage } from "../../Yonexus.Protocol/src/index.js";
import type { ServerPersistenceData } from "./core/persistence.js"; import type { ServerPersistenceData } from "./core/persistence.js";
const _G = globalThis as Record<string, unknown>;
const _STARTED_KEY = "_yonexusServerStarted";
const _TRANSPORT_KEY = "_yonexusServerTransport";
const _REGISTRY_KEY = "_yonexusServerRegistry";
const _CALLBACKS_KEY = "_yonexusServerOnAuthCallbacks";
export interface YonexusServerPluginManifest { export interface YonexusServerPluginManifest {
readonly name: "Yonexus.Server"; readonly name: "Yonexus.Server";
readonly version: string; readonly version: string;
@@ -52,8 +58,6 @@ const manifest: YonexusServerPluginManifest = {
description: "Yonexus central hub plugin for cross-instance OpenClaw communication" description: "Yonexus central hub plugin for cross-instance OpenClaw communication"
}; };
let _serverStarted = false;
export function createYonexusServerPlugin(api: { export function createYonexusServerPlugin(api: {
rootDir: string; rootDir: string;
pluginConfig: unknown; pluginConfig: unknown;
@@ -138,15 +142,34 @@ export function createYonexusServerPlugin(api: {
}); });
}, { commands: ["yonexus-server"] }); }, { commands: ["yonexus-server"] });
if (_serverStarted) return; // 1. Ensure shared state survives hot-reload — only initialise when absent
_serverStarted = true; if (!(_G[_REGISTRY_KEY] instanceof YonexusServerRuleRegistry)) {
_G[_REGISTRY_KEY] = createServerRuleRegistry();
}
if (!Array.isArray(_G[_CALLBACKS_KEY])) {
_G[_CALLBACKS_KEY] = [];
}
const ruleRegistry = _G[_REGISTRY_KEY] as YonexusServerRuleRegistry;
const onClientAuthenticatedCallbacks = _G[_CALLBACKS_KEY] as Array<(identifier: string) => void>;
// 2. Refresh the cross-plugin API object every call so that sendRule closure
// always reads the live transport from globalThis.
_G["__yonexusServer"] = {
ruleRegistry,
sendRule: (identifier: string, ruleId: string, content: string): boolean =>
(_G[_TRANSPORT_KEY] as ServerTransport | undefined)?.send(identifier, encodeRuleMessage(ruleId, content)) ?? false,
onClientAuthenticated: onClientAuthenticatedCallbacks
};
// 3. Start the runtime only once — the globalThis flag survives hot-reload
if (_G[_STARTED_KEY]) return;
_G[_STARTED_KEY] = true;
const config = validateYonexusServerConfig(api.pluginConfig); const config = validateYonexusServerConfig(api.pluginConfig);
const store = createYonexusServerStore(stateFilePath); const store = createYonexusServerStore(stateFilePath);
const ruleRegistry = createServerRuleRegistry(); // runtimeRef is local; transport is stored in globalThis so sendRule closures stay valid
const onClientAuthenticatedCallbacks: Array<(identifier: string) => void> = [];
let runtimeRef: ReturnType<typeof createYonexusServerRuntime> | null = null; let runtimeRef: ReturnType<typeof createYonexusServerRuntime> | null = null;
const transport = createServerTransport({ const transport = createServerTransport({
config, config,
@@ -161,14 +184,7 @@ export function createYonexusServerPlugin(api: {
} }
} }
}); });
_G[_TRANSPORT_KEY] = transport;
// Expose registry and helpers for other plugins loaded in the same process
(globalThis as Record<string, unknown>)["__yonexusServer"] = {
ruleRegistry,
sendRule: (identifier: string, ruleId: string, content: string): boolean =>
transport.send(identifier, encodeRuleMessage(ruleId, content)),
onClientAuthenticated: onClientAuthenticatedCallbacks
};
const runtime = createYonexusServerRuntime({ const runtime = createYonexusServerRuntime({
config, config,