UNPKG

@juspay/neurolink

Version:

The pipe layer of an AI nervous system: one interface connecting provider neurons to your application, across three inference types — generate, stream and decide. `decide` returns typed, calibrated judgements from a non-generative model (~400ms, ~$0.00002

111 lines (110 loc) • 5.23 kB
import { createRequire } from "node:module"; import { logger } from "../utils/logger.js"; // Lazy require so importing NeuroLink core does not fail when the optional // peer @juspay/hippocampus is not installed. The package was previously a // hard runtime dependency, but Hippocampus declares a peer on // @juspay/neurolink which made pnpm pull a registry NeuroLink that // transitively required @ai-sdk/google + @ai-sdk/google-vertex into the // production graph. Making memory optional breaks that cycle while keeping // the same runtime behavior whenever the package is installed. const lazyRequire = createRequire(import.meta.url); let cachedModule; function loadHippocampusModule() { if (cachedModule !== undefined) { return cachedModule; } try { cachedModule = lazyRequire("@juspay/hippocampus"); return cachedModule; } catch (error) { cachedModule = null; logger.debug("[memoryInitializer] @juspay/hippocampus is not installed; memory features disabled.", { error: error instanceof Error ? error.message : String(error), }); return null; } } /** * The client methods NeuroLink core calls: `add()` on the write path and * `get()` on the read path. `delete()` and `close()` are on the type for a * host's own use, but core never calls them, so a client without them is * still usable. */ const REQUIRED_CLIENT_METHODS = ["add", "get"]; /** * Construct (or adopt) the Hippocampus client. `config.neurolink.instance` * and `config.neurolink.credentials` are read by `@juspay/hippocampus` * ≥0.2.0 itself (the peer floor is 0.2.1, which also fixes literal * placeholder substitution), so condensation runs through the * instance NeuroLink supplies (the one carrying this host's credentials) * with no help from this side. * * Every path that disables memory logs at `error`: warnings are hidden at * the default log level, and a host whose memory is silently off has no * other way to learn it. */ export function initializeHippocampus(config, injectedClient) { if (injectedClient) { try { const client = typeof injectedClient === "function" ? injectedClient(config) : injectedClient; // A loosely typed or async factory can hand back undefined or a // Promise; cache neither. A partial client — a write-only double with // no get() — would make every read fail silently, so it is refused // here rather than on each call. Memory is disabled with a clear // message instead of failing every call with a generic error. // // The Promise case falls through to the same "missing" check below // (a thenable has none of the required methods), but a rejecting // factory's Promise needs a handler attached NOW — nothing else ever // awaits it, so an unhandled rejection would otherwise end the // process under the default Node rejection policy. const maybeThenable = client; if (client && typeof client === "object" && typeof maybeThenable.then === "function") { maybeThenable.then(undefined, () => { logger.error("[memoryInitializer] Host-supplied async client factory rejected"); }); } const missing = !client || typeof client !== "object" ? [...REQUIRED_CLIENT_METHODS] : REQUIRED_CLIENT_METHODS.filter((name) => typeof client[name] !== "function"); if (missing.length > 0) { logger.error(`[memoryInitializer] Host-supplied client has no ${missing .map((name) => `${name}()`) .join(" / ")}; disabling memory`); return null; } logger.info("[memoryInitializer] Memory initialized with host-supplied client", { fromFactory: typeof injectedClient === "function" }); return client; } catch (error) { logger.error("[memoryInitializer] Host-supplied client factory threw; disabling memory", { error: error instanceof Error ? error.message : String(error) }); return null; } } const mod = loadHippocampusModule(); if (!mod) { logger.error("[memoryInitializer] Memory configuration provided but @juspay/hippocampus is not installed. Run `pnpm add @juspay/hippocampus` (or your package manager equivalent) to enable memory."); return null; } try { const instance = new mod.Hippocampus(config); logger.info("[memoryInitializer] Memory initialized successfully", { storageType: config.storage?.type || "sqlite", maxWords: config.maxWords || 50, hasCustomPrompt: !!config.prompt, condenserSupplied: config.neurolink?.instance !== undefined, }); return instance; } catch (error) { logger.error("[memoryInitializer] Failed to initialize memory; disabling", { error: error instanceof Error ? error.message : String(error), }); return null; } }