@tanstack/ai-persistence
Version:
Composable state persistence for TanStack AI messages, runs, interrupts, metadata, and locks.
172 lines (171 loc) • 6.66 kB
JavaScript
import { defineRunStore, isTerminalRunStatus as isTerminalRunStatus$1 } from "@tanstack/ai";
//#region src/types.ts
/** Type a {@link MessageStore} implementation inline. */
function defineMessageStore(store) {
return store;
}
/** Type an {@link ActivityStore} implementation inline. */
function defineActivityStore(store) {
return store;
}
/** Type an {@link InterruptStore} implementation inline. */
function defineInterruptStore(store) {
return store;
}
/** Type a {@link MetadataStore} implementation inline. */
function defineMetadataStore(store) {
return store;
}
/** Type a {@link GenerationRunStore} implementation inline. */
function defineGenerationRunStore(store) {
return store;
}
/** Type an {@link ArtifactStore} implementation inline. */
function defineArtifactStore(store) {
return store;
}
/** Type a {@link BlobStore} implementation inline. */
function defineBlobStore(store) {
return store;
}
/**
* The epoch of a log that no host ever acquired. A writer that never calls
* {@link LogStore.acquireOwnership} writes with this epoch.
*/
var NO_OWNER_EPOCH = 0;
/**
* The error {@link LogStore.append} rejects with when `seq` is not the next
* free position of the log. It means that another writer appended first.
* Nothing of the rejected batch is written.
*/
var LogConflictError = class extends Error {
logId;
seq;
constructor(logId, seq) {
super(`Log conflict on log ${JSON.stringify(logId)}: position ${seq} is not the next free position.`);
this.name = "LogConflictError";
this.logId = logId;
this.seq = seq;
}
};
/**
* The error that a fenced write ({@link LogStore.append},
* {@link LogStore.putSnapshot}, {@link LogStore.truncate},
* {@link LogStore.pinToWorkers}) rejects with when `epoch` does not give the
* writer the log. It means that another host acquired the log, that the
* owner released it, that the log was deleted, or that the writer did not
* acquire a log that needs an owner. Nothing is written. Stop the work on the
* log.
*/
var OwnershipLostError = class extends Error {
logId;
epoch;
constructor(logId, epoch) {
super(`Ownership lost on log ${JSON.stringify(logId)}: epoch ${epoch} does not own the log.`);
this.name = "OwnershipLostError";
this.logId = logId;
this.epoch = epoch;
}
};
/**
* The error {@link LogStore.read} rejects with when the query starts before
* the first record that the log keeps. A truncate dropped the records before
* `firstSeq`. Load the snapshot, then read after its `seq`.
*/
var LogTruncatedError = class extends Error {
logId;
firstSeq;
constructor(logId, firstSeq) {
super(`Log ${JSON.stringify(logId)} is truncated: the first kept position is ${firstSeq}.`);
this.name = "LogTruncatedError";
this.logId = logId;
this.firstSeq = firstSeq;
}
};
/** Type a {@link LogStore} implementation inline. */
function defineLogStore(store) {
return store;
}
/** Type a {@link SessionIndexStore} implementation inline. */
function defineSessionIndexStore(store) {
return store;
}
var storeKeys = [
"messages",
"activities",
"runs",
"generationRuns",
"interrupts",
"metadata",
"artifacts",
"blobs",
"log",
"sessions"
];
var storeKeySet = new Set(storeKeys);
function assertKnownStoreKeys(stores, location) {
for (const key of Object.keys(stores)) if (!storeKeySet.has(key)) throw new Error(`Unknown AIPersistence ${location} key: ${key}`);
}
function validatePersistenceStoreKeys(persistence) {
assertKnownStoreKeys(persistence.stores, "store");
}
/**
* Chat middleware entrypoint rules:
* - `messages` is required (chat persistence means a durable transcript)
* - `interrupts` requires `runs` (interrupt records are run-scoped)
*/
function validateChatPersistenceStores(persistence) {
validatePersistenceStoreKeys(persistence);
if (!persistence.stores.messages) throw new Error("Chat persistence requires stores.messages.");
if (persistence.stores.interrupts && !persistence.stores.runs) throw new Error("Chat persistence stores.interrupts requires stores.runs.");
}
/**
* Generation middleware entrypoint rule: `generationRuns` is required (the
* generation run lifecycle is keyed on its own `runId`, not a chat conversation
* `threadId`). When artifact persistence is used, `artifacts` and `blobs` must
* be provided together.
*/
function validateGenerationPersistenceStores(persistence) {
validatePersistenceStoreKeys(persistence);
if (persistence.stores.artifacts !== void 0 !== (persistence.stores.blobs !== void 0)) throw new Error("Generation artifact persistence requires both stores.artifacts and stores.blobs.");
if (!persistence.stores.generationRuns) throw new Error("Generation persistence requires stores.generationRuns.");
}
/**
* Server hydrate entrypoint rule: `messages` is required.
*/
function validateReconstructChatStores(persistence) {
validatePersistenceStoreKeys(persistence);
if (!persistence.stores.messages) throw new Error("reconstructChat requires stores.messages.");
}
/**
* Server hydrate entrypoint rule for generation: `generationRuns` is required.
* The run store resolves the latest generation for a thread (or a specific run
* id), so a server-authoritative client can hydrate the last generation's
* status, result, and artifact refs on load.
*/
function validateReconstructGenerationStores(persistence) {
validatePersistenceStoreKeys(persistence);
if (!persistence.stores.generationRuns) throw new Error("reconstructGeneration requires stores.generationRuns.");
}
function defineAIPersistence(persistence) {
validatePersistenceStoreKeys(persistence);
return persistence;
}
function composePersistence(base, config) {
validatePersistenceStoreKeys(base);
assertKnownStoreKeys(config.overrides, "override");
const stores = { ...base.stores };
for (const key of storeKeys) {
if (!Object.prototype.hasOwnProperty.call(config.overrides, key)) continue;
const override = config.overrides[key];
if (override === false) delete stores[key];
else if (override !== void 0) setStore(stores, key, override);
}
return { stores };
}
function setStore(stores, key, value) {
stores[key] = value;
}
//#endregion
export { LogConflictError, LogTruncatedError, NO_OWNER_EPOCH, OwnershipLostError, composePersistence, defineAIPersistence, defineActivityStore, defineArtifactStore, defineBlobStore, defineGenerationRunStore, defineInterruptStore, defineLogStore, defineMessageStore, defineMetadataStore, defineRunStore, defineSessionIndexStore, isTerminalRunStatus$1 as isTerminalRunStatus, validateChatPersistenceStores, validateGenerationPersistenceStores, validatePersistenceStoreKeys, validateReconstructChatStores, validateReconstructGenerationStores };
//# sourceMappingURL=types.js.map