export { validateYonexusClientConfig, YonexusClientConfigError } from "./core/config.js"; export type { YonexusClientConfig } from "./core/config.js"; export { CLIENT_STATE_VERSION, YonexusClientStateError, YonexusClientStateCorruptionError, createYonexusClientStateStore, loadYonexusClientState, saveYonexusClientState, createInitialClientState, hasClientSecret, hasClientKeyPair, type YonexusClientState, type YonexusClientStateFile, type YonexusClientStateStore } from "./core/state.js"; export { createClientTransport, YonexusClientTransport, type ClientTransport, type ClientTransportOptions, type ClientConnectionState, type ClientMessageHandler, type ClientStateChangeHandler, type ClientErrorHandler } from "./core/transport.js"; export { createYonexusClientRuntime, YonexusClientRuntime, type YonexusClientRuntimeOptions, type YonexusClientRuntimeState, type YonexusClientPhase } from "./core/runtime.js"; export { createClientRuleRegistry, YonexusClientRuleRegistry, ClientRuleRegistryError, type ClientRuleRegistry, type ClientRuleProcessor } from "./core/rules.js"; import path from "node:path"; import { validateYonexusClientConfig } from "./core/config.js"; import { createYonexusClientStateStore } from "./core/state.js"; import { createClientTransport } from "./core/transport.js"; import { createYonexusClientRuntime, type YonexusClientRuntime } from "./core/runtime.js"; import { createClientRuleRegistry, YonexusClientRuleRegistry } from "./core/rules.js"; const _G = globalThis as Record; const _STARTED_KEY = "_yonexusClientStarted"; const _RUNTIME_KEY = "_yonexusClientRuntime"; const _REGISTRY_KEY = "_yonexusClientRegistry"; const _CALLBACKS_KEY = "_yonexusClientOnAuthCallbacks"; export interface YonexusClientPluginManifest { readonly name: "Yonexus.Client"; readonly version: string; readonly description: string; } const manifest: YonexusClientPluginManifest = { name: "Yonexus.Client", version: "0.1.0", description: "Yonexus client plugin for cross-instance OpenClaw communication" }; export function createYonexusClientPlugin(api: { rootDir: string; pluginConfig: unknown }): void { // 1. Ensure shared state survives hot-reload — only initialise when absent if (!(_G[_REGISTRY_KEY] instanceof YonexusClientRuleRegistry)) { _G[_REGISTRY_KEY] = createClientRuleRegistry(); } if (!Array.isArray(_G[_CALLBACKS_KEY])) { _G[_CALLBACKS_KEY] = []; } const ruleRegistry = _G[_REGISTRY_KEY] as YonexusClientRuleRegistry; const onAuthenticatedCallbacks = _G[_CALLBACKS_KEY] as Array<() => void>; // 2. Refresh the cross-plugin API object every call so that sendRule / submitPairingCode // closures always read the live runtime from globalThis. _G["__yonexusClient"] = { ruleRegistry, sendRule: (ruleId: string, content: string): boolean => (_G[_RUNTIME_KEY] as YonexusClientRuntime | undefined)?.sendRuleMessage(ruleId, content) ?? false, submitPairingCode: (code: string): boolean => (_G[_RUNTIME_KEY] as YonexusClientRuntime | undefined)?.submitPairingCode(code) ?? false, onAuthenticated: onAuthenticatedCallbacks }; // 3. Start the runtime only once — the globalThis flag survives hot-reload if (_G[_STARTED_KEY]) return; _G[_STARTED_KEY] = true; const config = validateYonexusClientConfig(api.pluginConfig); const stateStore = createYonexusClientStateStore(path.join(api.rootDir, "state.json")); const transport = createClientTransport({ config, onMessage: (msg) => { (_G[_RUNTIME_KEY] as YonexusClientRuntime | undefined)?.handleMessage(msg).catch((err: unknown) => { console.error("[yonexus-client] message handler error:", err); }); }, onStateChange: (state) => { (_G[_RUNTIME_KEY] as YonexusClientRuntime | undefined)?.handleTransportStateChange(state); } }); const runtime = createYonexusClientRuntime({ config, transport, stateStore, ruleRegistry, onAuthenticated: () => { for (const cb of onAuthenticatedCallbacks) cb(); } }); _G[_RUNTIME_KEY] = runtime; const shutdown = (): void => { runtime.stop().catch((err: unknown) => { console.error("[yonexus-client] shutdown error:", err); }); }; process.once("SIGTERM", shutdown); process.once("SIGINT", shutdown); runtime.start().catch((err: unknown) => { console.error("[yonexus-client] failed to start:", err); }); } export default createYonexusClientPlugin; export { manifest };