@sema-agent/core
Version:
Stateless, task-oriented AI agent core
91 lines (90 loc) • 2.74 kB
JavaScript
export class EventStream {
queue = [];
waiting = [];
done = false;
finalResolved = false;
finalResultPromise;
resolveFinalResult;
rejectFinalResult;
isComplete;
extractResult;
constructor(isComplete, extractResult) {
this.isComplete = isComplete;
this.extractResult = extractResult;
this.finalResultPromise = new Promise((resolve, reject) => {
this.resolveFinalResult = resolve;
this.rejectFinalResult = reject;
});
this.finalResultPromise.catch(() => { });
}
push(event) {
if (this.done) {
return;
}
if (this.isComplete(event)) {
this.done = true;
this.finalResolved = true;
this.resolveFinalResult(this.extractResult(event));
}
const waiter = this.waiting.shift();
if (waiter) {
waiter({ value: event, done: false });
}
else {
this.queue.push(event);
}
}
end(result) {
this.done = true;
if (result !== undefined) {
this.finalResolved = true;
this.resolveFinalResult(result);
}
else if (!this.finalResolved) {
this.finalResolved = true;
this.rejectFinalResult(new Error("EventStream ended without a final result (end() called with no result and no terminal event was pushed)"));
}
while (this.waiting.length > 0) {
const waiter = this.waiting.shift();
waiter({ value: undefined, done: true });
}
}
async *[Symbol.asyncIterator]() {
while (true) {
if (this.queue.length > 0) {
yield this.queue.shift();
}
else if (this.done) {
return;
}
else {
const result = await new Promise((resolve) => {
this.waiting.push(resolve);
});
if (result.done) {
return;
}
yield result.value;
}
}
}
result() {
return this.finalResultPromise;
}
}
export class AssistantMessageEventStream extends EventStream {
constructor() {
super((event) => event.type === "done" || event.type === "error", (event) => {
if (event.type === "done") {
return event.message;
}
else if (event.type === "error") {
return event.error;
}
throw new Error("Unexpected event type for final result");
});
}
}
export function createAssistantMessageEventStream() {
return new AssistantMessageEventStream();
}