feat(session): use blocks, use rfc6902 for stream with patching

This commit is contained in:
ItzCrazyKns
2025-11-21 23:52:55 +05:30
parent 70bcd8c6f1
commit f7a43b3cb9

View File

@@ -1,13 +1,20 @@
import { EventEmitter } from 'stream'; import { EventEmitter } from 'stream';
/* todo implement history saving and better artifact typing and handling */ import { applyPatch } from 'rfc6902';
class SessionManager { class SessionManager {
private static sessions = new Map<string, SessionManager>(); private static sessions = new Map<string, SessionManager>();
readonly id: string; readonly id: string;
private artifacts = new Map<string, Artifact>(); private blocks = new Map<string, Block>();
private events: { event: string; data: any }[] = [];
private emitter = new EventEmitter(); private emitter = new EventEmitter();
private TTL_MS = 30 * 60 * 1000;
constructor() { constructor(id?: string) {
this.id = crypto.randomUUID(); this.id = id ?? crypto.randomUUID();
setTimeout(() => {
SessionManager.sessions.delete(this.id);
}, this.TTL_MS);
} }
static getSession(id: string): SessionManager | undefined { static getSession(id: string): SessionManager | undefined {
@@ -18,26 +25,55 @@ class SessionManager {
return Array.from(this.sessions.values()); return Array.from(this.sessions.values());
} }
static createSession(): SessionManager {
const session = new SessionManager();
this.sessions.set(session.id, session);
return session;
}
removeAllListeners() {
this.emitter.removeAllListeners();
}
emit(event: string, data: any) { emit(event: string, data: any) {
this.emitter.emit(event, data); this.emitter.emit(event, data);
this.events.push({ event, data });
} }
emitArtifact(artifact: Artifact) { emitBlock(block: Block) {
this.artifacts.set(artifact.id, artifact); this.blocks.set(block.id, block);
this.emitter.emit('addArtifact', artifact); this.emit('data', {
type: 'block',
block: block,
});
} }
appendToArtifact(artifactId: string, data: any) { getBlock(blockId: string): Block | undefined {
const artifact = this.artifacts.get(artifactId); return this.blocks.get(blockId);
if (artifact) {
if (typeof artifact.data === 'string') {
artifact.data += data;
} else if (Array.isArray(artifact.data)) {
artifact.data.push(data);
} else if (typeof artifact.data === 'object') {
Object.assign(artifact.data, data);
} }
this.emitter.emit('updateArtifact', artifact);
updateBlock(blockId: string, patch: any[]) {
const block = this.blocks.get(blockId);
if (block) {
applyPatch(block, patch);
this.blocks.set(blockId, block);
this.emit('data', {
type: 'updateBlock',
blockId: blockId,
patch: patch,
});
}
}
addListener(event: string, listener: (data: any) => void) {
this.emitter.addListener(event, listener);
}
replay() {
for (const { event, data } of this.events) {
/* Using emitter directly to avoid infinite loop */
this.emitter.emit(event, data);
} }
} }
} }