trellis
Version:
Agentic State Engine — event-sourced causal graph with branching, decision traces, and realtime sync for AI-native applications
120 lines (117 loc) • 3.51 kB
JavaScript
import {
__esm
} from "./chunk-2ESYSVXG.js";
// src/realtime/relay-persistence.ts
function chatKey(msg) {
return msg.id ?? `${msg.from}:${msg.ts}`;
}
function tieKey(msg) {
if (msg.t === "msg") return chatKey(msg);
if (msg.t === "presence" || msg.t === "bye") return msg.from;
return "";
}
function messageTs(msg) {
if (msg.t === "presence" || msg.t === "bye" || msg.t === "msg") {
return msg.ts;
}
return 0;
}
var DEFAULT_MAX_CHAT, DEFAULT_MAX_TEXT_OPS, RelayPersistence;
var init_relay_persistence = __esm({
"src/realtime/relay-persistence.ts"() {
"use strict";
DEFAULT_MAX_CHAT = 200;
DEFAULT_MAX_TEXT_OPS = 2e3;
RelayPersistence = class {
maxChat;
maxTextOps;
presence = /* @__PURE__ */ new Map();
/** Chat is a grow-only set keyed by {@link chatKey} — dedup on record. */
chatLog = [];
chatKeys = /* @__PURE__ */ new Set();
textSnapshot = null;
textOps = [];
constructor(opts = {}) {
this.maxChat = opts.maxChat ?? DEFAULT_MAX_CHAT;
this.maxTextOps = opts.maxTextOps ?? DEFAULT_MAX_TEXT_OPS;
}
/** Record an inbound client message (skip `hello` / `replay`). */
record(message) {
if (message.v !== 1) return;
switch (message.t) {
case "hello":
return;
case "replay":
return;
case "presence":
this.presence.set(message.from, message);
return;
case "bye":
this.presence.delete(message.from);
return;
case "msg":
this.recordBroadcast(message);
return;
}
}
/** Ordered messages to replay to a peer that just connected. */
buildReplay() {
const out = [
...this.presence.values(),
...this.chatLog
];
if (this.textSnapshot) {
out.push(this.textSnapshot);
} else {
out.push(...this.textOps);
}
out.sort((a, b) => {
const dt = messageTs(a) - messageTs(b);
if (dt !== 0) return dt;
return tieKey(a).localeCompare(tieKey(b));
});
return out;
}
getPresenceCount() {
return this.presence.size;
}
getChatCount() {
return this.chatLog.length;
}
hasTextSnapshot() {
return this.textSnapshot !== null;
}
recordBroadcast(message) {
if (message.channel === "chat" && message.event === "message") {
const key = chatKey(message);
if (this.chatKeys.has(key)) return;
this.chatKeys.add(key);
this.chatLog.push(message);
if (this.chatLog.length > this.maxChat) {
const evicted = this.chatLog.splice(0, this.chatLog.length - this.maxChat);
for (const m of evicted) this.chatKeys.delete(chatKey(m));
}
return;
}
if (message.channel === "text" && message.event === "state") {
this.textSnapshot = message;
this.textOps = [];
return;
}
if (message.channel === "text" && message.event === "op") {
if (this.textSnapshot) return;
this.textOps.push(message);
if (this.textOps.length > this.maxTextOps) {
this.textOps.splice(0, this.textOps.length - this.maxTextOps);
}
}
}
};
}
});
export {
DEFAULT_MAX_CHAT,
DEFAULT_MAX_TEXT_OPS,
RelayPersistence,
init_relay_persistence
};