VibeGame / src /lib /server /console-buffer.ts
dylanebert's picture
improved prompting/UX
db9635c
export interface ConsoleBufferMessage {
id: string;
type: "log" | "warn" | "error" | "info";
message: string;
timestamp: number;
context?: string;
}
export class ConsoleBuffer {
private static instance: ConsoleBuffer | null = null;
private messages: ConsoleBufferMessage[] = [];
private maxMessages = 200;
private lastReadTimestamp = 0;
private executionContext: string | null = null;
private messagesSinceLastTool: ConsoleBufferMessage[] = [];
private constructor() {}
static getInstance(): ConsoleBuffer {
if (!ConsoleBuffer.instance) {
ConsoleBuffer.instance = new ConsoleBuffer();
}
return ConsoleBuffer.instance;
}
addMessage(message: ConsoleBufferMessage): void {
if (this.executionContext) {
message.context = this.executionContext;
}
this.messages.push(message);
this.messagesSinceLastTool.push(message);
if (this.messages.length > this.maxMessages) {
this.messages = this.messages.slice(-this.maxMessages);
}
if (this.messagesSinceLastTool.length > 50) {
this.messagesSinceLastTool = this.messagesSinceLastTool.slice(-50);
}
}
getRecentMessages(since?: number, limit?: number): ConsoleBufferMessage[] {
const sinceTimestamp = since || this.lastReadTimestamp;
const filtered = this.messages.filter(
(msg) => msg.timestamp > sinceTimestamp,
);
if (limit && limit > 0 && filtered.length > limit) {
return filtered.slice(-limit);
}
return filtered;
}
getAllMessages(limit?: number): ConsoleBufferMessage[] {
if (limit && limit > 0 && this.messages.length > limit) {
return this.messages.slice(-limit);
}
return [...this.messages];
}
markAsRead(): void {
if (this.messages.length > 0) {
this.lastReadTimestamp =
this.messages[this.messages.length - 1].timestamp;
}
}
clear(): void {
this.lastReadTimestamp = Date.now();
this.messagesSinceLastTool = [];
}
onGameReloadStart(): void {
this.messagesSinceLastTool = [];
this.lastReadTimestamp = Date.now();
this.addMessage({
id: `reload-${Date.now()}`,
type: "info",
message: "๐Ÿ”„ Game reloading...",
timestamp: Date.now(),
});
}
onGameReloadComplete(): void {
this.addMessage({
id: `reload-complete-${Date.now()}`,
type: "info",
message: "โœ… Game reload complete",
timestamp: Date.now(),
});
}
setExecutionContext(context: string | null): void {
this.executionContext = context;
}
getMessagesSinceLastTool(): ConsoleBufferMessage[] {
return [...this.messagesSinceLastTool];
}
clearToolMessages(): void {
this.messagesSinceLastTool = [];
}
getGameStateFromMessages(): {
isLoading: boolean;
hasError: boolean;
lastError?: string;
isReady: boolean;
isReloading: boolean;
messageCount: number;
} {
const recentMessages =
this.messagesSinceLastTool.length > 0
? this.messagesSinceLastTool
: this.getRecentMessages(Date.now() - 5000);
const hasReloadStartMessage = recentMessages.some((msg) =>
msg.message.includes("๐Ÿ”„ Game reloading"),
);
const hasReloadCompleteMessage = recentMessages.some((msg) =>
msg.message.includes("โœ… Game reload complete"),
);
const hasStartMessage = recentMessages.some(
(msg) =>
msg.message.includes("๐ŸŽฎ Starting game") ||
msg.message.includes("Starting game") ||
msg.message.includes("loading") ||
msg.message.includes("Loading"),
);
const hasSuccessMessage = recentMessages.some(
(msg) =>
msg.message.includes("โœ… Game started") ||
msg.message.includes("Game started!") ||
msg.message.includes("Game script loaded!") ||
msg.message.includes("โœ… Game reload complete") ||
msg.message.includes("successfully"),
);
const errorMessages = recentMessages.filter(
(msg) =>
msg.type === "error" ||
msg.message.includes("โŒ Error") ||
msg.message.includes("Error:") ||
msg.message.includes("Failed") ||
msg.message.includes("failed"),
);
const lastError =
errorMessages.length > 0
? errorMessages[errorMessages.length - 1].message
: undefined;
const isReloading = hasReloadStartMessage && !hasReloadCompleteMessage;
return {
isLoading:
(hasStartMessage || isReloading) &&
!hasSuccessMessage &&
errorMessages.length === 0,
hasError: errorMessages.length > 0,
lastError,
isReady: hasSuccessMessage && errorMessages.length === 0 && !isReloading,
isReloading,
messageCount: recentMessages.length,
};
}
}
export const consoleBuffer = ConsoleBuffer.getInstance();