Initial commit: Discord-Claude Gateway with event-driven agent runtime
This commit is contained in:
116
src/event-queue.ts
Normal file
116
src/event-queue.ts
Normal file
@@ -0,0 +1,116 @@
|
||||
export type EventType = "message" | "heartbeat" | "cron" | "hook" | "webhook";
|
||||
|
||||
export type HookType = "startup" | "agent_begin" | "agent_stop" | "shutdown";
|
||||
|
||||
export interface MessagePayload {
|
||||
prompt: { text: string; channelId: string; userId: string; guildId: string | null };
|
||||
}
|
||||
|
||||
export interface HeartbeatPayload {
|
||||
instruction: string;
|
||||
checkName: string;
|
||||
}
|
||||
|
||||
export interface CronPayload {
|
||||
instruction: string;
|
||||
jobName: string;
|
||||
}
|
||||
|
||||
export interface HookPayload {
|
||||
hookType: HookType;
|
||||
instruction?: string;
|
||||
}
|
||||
|
||||
export type EventPayload = MessagePayload | HeartbeatPayload | CronPayload | HookPayload;
|
||||
|
||||
export interface Event {
|
||||
id: number;
|
||||
type: EventType;
|
||||
payload: EventPayload;
|
||||
timestamp: Date;
|
||||
source: string;
|
||||
}
|
||||
|
||||
export class EventQueue {
|
||||
private queue: Event[] = [];
|
||||
private nextId = 1;
|
||||
private maxDepth: number;
|
||||
private handler: ((event: Event) => Promise<void>) | null = null;
|
||||
private processing = false;
|
||||
private drainResolvers: Array<() => void> = [];
|
||||
|
||||
constructor(maxDepth: number) {
|
||||
this.maxDepth = maxDepth;
|
||||
}
|
||||
|
||||
enqueue(event: Omit<Event, "id" | "timestamp">): Event | null {
|
||||
if (this.queue.length >= this.maxDepth) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const fullEvent: Event = {
|
||||
...event,
|
||||
id: this.nextId++,
|
||||
timestamp: new Date(),
|
||||
};
|
||||
|
||||
this.queue.push(fullEvent);
|
||||
this.processNext();
|
||||
return fullEvent;
|
||||
}
|
||||
|
||||
dequeue(): Event | undefined {
|
||||
return this.queue.shift();
|
||||
}
|
||||
|
||||
size(): number {
|
||||
return this.queue.length;
|
||||
}
|
||||
|
||||
onEvent(handler: (event: Event) => Promise<void>): void {
|
||||
this.handler = handler;
|
||||
this.processNext();
|
||||
}
|
||||
|
||||
drain(): Promise<void> {
|
||||
if (this.queue.length === 0 && !this.processing) {
|
||||
return Promise.resolve();
|
||||
}
|
||||
return new Promise<void>((resolve) => {
|
||||
this.drainResolvers.push(resolve);
|
||||
});
|
||||
}
|
||||
|
||||
private processNext(): void {
|
||||
if (this.processing || !this.handler || this.queue.length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.processing = true;
|
||||
const event = this.queue.shift()!;
|
||||
|
||||
this.handler(event)
|
||||
.then(() => {
|
||||
this.processing = false;
|
||||
if (this.queue.length === 0) {
|
||||
const resolvers = this.drainResolvers.splice(0);
|
||||
for (const resolve of resolvers) {
|
||||
resolve();
|
||||
}
|
||||
} else {
|
||||
this.processNext();
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
this.processing = false;
|
||||
if (this.queue.length === 0) {
|
||||
const resolvers = this.drainResolvers.splice(0);
|
||||
for (const resolve of resolvers) {
|
||||
resolve();
|
||||
}
|
||||
} else {
|
||||
this.processNext();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user