@juspay/neurolink
Version:
The pipe layer of an AI nervous system: one interface connecting provider neurons to your application, across three inference types — generate, stream and decide. `decide` returns typed, calibrated judgements from a non-generative model (~400ms, ~$0.00002
77 lines (76 loc) • 2.41 kB
JavaScript
/**
* Create a push-based channel bridging a background producer (an agentic
* tool-calling loop) with an async-iterable consumer, enabling truly
* incremental streaming: values are yielded to the caller as they arrive
* rather than being buffered until the producer finishes.
*/
export function createStreamChannel() {
const queue = [];
let done = false;
let fatalError = undefined;
// Tracked separately from `fatalError`: a producer can legitimately
// reject with `undefined` (e.g. `throw undefined`), and `fatalError !==
// undefined` would then be indistinguishable from "no error occurred",
// closing the stream cleanly instead of surfacing the failure.
let hasError = false;
let notify = null;
function wake() {
if (notify) {
const fn = notify;
notify = null;
fn();
}
}
function push(value) {
if (done) {
return;
}
queue.push(value);
wake();
}
function close() {
done = true;
wake();
}
function error(err) {
done = true;
fatalError = err;
hasError = true;
wake();
}
let readIndex = 0;
async function* iterable() {
try {
while (true) {
if (readIndex < queue.length) {
yield queue[readIndex++];
// Periodically compact consumed entries to avoid unbounded retention.
if (readIndex > 1024 && readIndex * 2 >= queue.length) {
queue.splice(0, readIndex);
readIndex = 0;
}
}
else if (done) {
if (hasError) {
throw fatalError instanceof Error
? fatalError
: new Error(String(fatalError));
}
return;
}
else {
await new Promise((resolve) => {
notify = resolve;
});
}
}
}
finally {
// Consumer stopped reading (disconnect/cancel): stop buffering.
done = true;
queue.length = 0;
notify?.();
}
}
return { push, close, error, iterable: iterable() };
}