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

102 lines (101 loc) • 3.96 kB
/** * Artifact store factory — picks a backend the way conversation memory does. * * Backend: `artifacts.store` → `artifacts.storage` → `STORAGE_TYPE` → local * Connection: `artifacts.redisConfig` → conversation memory's `redisConfig` * → `REDIS_URL` / `REDIS_HOST` … environment variables * * So `STORAGE_TYPE=redis`, which already moves sessions to Redis, moves * artifacts there too, on the same pooled connection, with nothing new to * set. The one thing never inherited is the KEY PREFIX: artifacts get their * own (`neurolink:artifact:`) even when the connection came from the * conversation config or `REDIS_KEY_PREFIX`. * * @module artifacts/artifactStoreFactory */ import { logger } from "../utils/logger.js"; import { LocalTempArtifactStore } from "./artifactStore.js"; import { DEFAULT_ARTIFACT_KEY_PREFIX, RedisArtifactStore, } from "./redisArtifactStore.js"; function numberFromEnv(name) { const raw = process.env[name]; if (raw === undefined || raw === "") { return undefined; } const value = Number(raw); return Number.isFinite(value) ? value : undefined; } /** * The Redis connection described by the environment — the same variables * conversation memory reads, minus `REDIS_KEY_PREFIX`, which names the * conversation keyspace and must not name this one. */ export function readArtifactRedisConfigFromEnv() { const config = { host: process.env.REDIS_HOST, port: numberFromEnv("REDIS_PORT"), password: process.env.REDIS_PASSWORD, db: numberFromEnv("REDIS_DB"), ttl: numberFromEnv("REDIS_TTL"), connectionOptions: { connectTimeout: numberFromEnv("REDIS_CONNECT_TIMEOUT"), maxRetriesPerRequest: numberFromEnv("REDIS_MAX_RETRIES"), retryDelayOnFailover: numberFromEnv("REDIS_RETRY_DELAY"), }, }; if (process.env.REDIS_URL) { config.url = process.env.REDIS_URL; } return config; } /** Which backend `config` and the environment select. */ export function resolveArtifactStorageType(config) { if (config?.storage) { return config.storage; } const fromEnv = process.env.STORAGE_TYPE?.trim().toLowerCase(); return fromEnv === "redis" ? "redis" : "local"; } /** * The Redis connection an artifact store should use, with its own key prefix. * * @param config `artifacts` constructor config * @param fallback conversation memory's `redisConfig`, when one was given */ export function resolveArtifactRedisConfig(config, fallback) { const source = config?.redisConfig ?? fallback ?? readArtifactRedisConfigFromEnv(); return { url: source.url, username: source.username, host: source.host, port: source.port, password: source.password, db: source.db, ttl: source.ttl, connectionOptions: source.connectionOptions, keyPrefix: config?.redisConfig?.keyPrefix ?? DEFAULT_ARTIFACT_KEY_PREFIX, }; } /** * Build the artifact store `config` asks for. * * @param config `artifacts` constructor config * @param fallbackRedis conversation memory's `redisConfig`, consulted for the * connection when `config.redisConfig` is absent */ export function createArtifactStore(config, fallbackRedis) { if (config?.store) { logger.debug("[ArtifactStore] Using the injected artifact store"); return config.store; } const storage = resolveArtifactStorageType(config); if (storage === "redis") { const redis = resolveArtifactRedisConfig(config, fallbackRedis); logger.debug("[ArtifactStore] Artifact store backend: redis", { host: redis.host ?? (redis.url ? "(url)" : "localhost"), keyPrefix: redis.keyPrefix, }); return new RedisArtifactStore(redis); } logger.debug("[ArtifactStore] Artifact store backend: local-temp"); return new LocalTempArtifactStore(); }