dev/2026-04-08 #1
@@ -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,
|
||||||
|
|||||||
Reference in New Issue
Block a user