@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
85 lines (84 loc) • 3.9 kB
TypeScript
/**
* Redis Artifact Store
*
* The artifact backend for more than one machine. `LocalTempArtifactStore`
* writes to a pod's own `/tmp`: a replica that did not store an artifact
* cannot read it, a redeploy loses all of them, and `cleanup()` can only
* expire what its own process wrote. Here every replica sees every artifact,
* Redis expires them by TTL, and a paged read moves only the window.
*
* Layout, under `keyPrefix` (default `neurolink:artifact:`):
*
* <prefix><id> STRING the payload, verbatim
* <prefix><id>:meta STRING JSON `RedisArtifactRecord`
*
* Both keys carry the same TTL and are written in one MULTI, so an id either
* resolves completely or not at all.
*
* Range reads are honest about units. `retrieve_context` addresses characters;
* `GETRANGE` addresses bytes. The record stores the payload's character length
* next to its byte length, and only when the two are equal — pure ASCII, which
* is what JSON tool output and logs almost always are — is a byte range used
* as a character range. Anything else falls back to a whole read and a slice,
* which is slower and still correct. A window never starts on the wrong
* character.
*
* The connection is the same pool Redis conversation memory uses, keyed by
* host, port and database, so a deployment that already keeps sessions in
* Redis adds no connection by keeping artifacts there too.
*
* @module artifacts/redisArtifactStore
*/
import type { ArtifactMeta, ArtifactPageRequest, ArtifactRef, ArtifactStore, ArtifactWindow, RedisStorageConfig } from "../types/index.js";
/** Key prefix when the caller does not choose one. Never the conversation prefix. */
export declare const DEFAULT_ARTIFACT_KEY_PREFIX = "neurolink:artifact:";
/** Expiry when the caller does not choose one, or chooses an unusable one. */
export declare const DEFAULT_ARTIFACT_TTL_SECONDS = 86400;
/**
* Redis-backed artifact store: shared across replicas, expired by TTL,
* range reads for ASCII payloads.
*
* @example
* ```typescript
* const store = new RedisArtifactStore({ url: process.env.REDIS_URL });
* const neurolink = new NeuroLink({ artifacts: { store } });
* // or let NeuroLink build it: { artifacts: { storage: "redis" } }
* ```
*/
export declare class RedisArtifactStore implements ArtifactStore {
private readonly config;
private client?;
private connecting?;
/**
* @param config - Connection and key settings. `keyPrefix` defaults to
* `neurolink:artifact:`. `ttl` is seconds and must be positive; it
* defaults to 86400 (24 hours), and zero, negative or non-finite values
* are replaced by that default with a warning — artifacts in Redis always
* expire, there is no "keep forever". `userSessionsKeyPrefix` is
* meaningless here and ignored.
*/
constructor(config?: RedisStorageConfig);
generatePreview(payload: string): string;
store(payload: string, meta: Omit<ArtifactMeta, "createdAt">): Promise<ArtifactRef>;
retrieve(id: string): Promise<string | null>;
retrieveRange(id: string, range: ArtifactPageRequest): Promise<ArtifactWindow | null>;
delete(id: string): Promise<void>;
/**
* Nothing to sweep: Redis expires every artifact `ttl` seconds after it was
* written, on every replica at once, which is what `cleanup()` on the local
* store could never do.
*/
cleanup(olderThanMs: number): Promise<number>;
/**
* Release this store's reference on the pooled connection.
*
* Waits for a connect that is still in flight: otherwise the reference it
* is about to acquire would be assigned after this returned, and nothing
* would ever release it.
*/
close(): Promise<void>;
private payloadKey;
private metaKey;
/** Connect on first use, once, and share the pooled client afterwards. */
private getClient;
}