Initial commit: Complete Hive distributed AI orchestration platform

This comprehensive implementation includes:
- FastAPI backend with MCP server integration
- React/TypeScript frontend with Vite
- PostgreSQL database with Redis caching
- Grafana/Prometheus monitoring stack
- Docker Compose orchestration
- Full MCP protocol support for Claude Code integration

Features:
- Agent discovery and management across network
- Visual workflow editor and execution engine
- Real-time task coordination and monitoring
- Multi-model support with specialized agents
- Distributed development task allocation

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
anthonyrawlins
2025-07-07 21:44:31 +10:00
commit d7ad321176
2631 changed files with 870175 additions and 0 deletions

21
mcp-server/node_modules/eventsource-parser/LICENSE generated vendored Normal file
View File

@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2025 Espen Hovlandsdal <espen@hovlandsdal.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

126
mcp-server/node_modules/eventsource-parser/README.md generated vendored Normal file
View File

@@ -0,0 +1,126 @@
# eventsource-parser
[![npm version](https://img.shields.io/npm/v/eventsource-parser.svg?style=flat-square)](https://www.npmjs.com/package/eventsource-parser)[![npm bundle size](https://img.shields.io/bundlephobia/minzip/eventsource-parser?style=flat-square)](https://bundlephobia.com/result?p=eventsource-parser)[![npm weekly downloads](https://img.shields.io/npm/dw/eventsource-parser.svg?style=flat-square)](https://www.npmjs.com/package/eventsource-parser)
A streaming parser for [server-sent events/eventsource](https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events), without any assumptions about how the actual stream of data is retrieved. It is intended to be a building block for [clients](https://github.com/rexxars/eventsource-client) and polyfills in javascript environments such as browsers, node.js and deno.
If you are looking for a modern client implementation, see [eventsource-client](https://github.com/rexxars/eventsource-client).
You create an instance of the parser, and _feed_ it chunks of data - partial or complete, and the parse emits parsed messages once it receives a complete message. A [TransformStream variant](#stream-usage) is also available for environments that support it (modern browsers, Node 18 and higher).
Other modules in the EventSource family:
- [eventsource-client](https://github.com/rexxars/eventsource-client): modern, feature rich eventsource client for browsers, node.js, bun, deno and other modern JavaScript environments.
- [eventsource-encoder](https://github.com/rexxars/eventsource-encoder): encodes messages in the EventSource/Server-Sent Events format.
- [eventsource](https://github.com/eventsource/eventsource): Node.js polyfill for the WhatWG EventSource API.
> [!NOTE]
> Migrating from eventsource-parser 1.x/2.x? See the [migration guide](./MIGRATE-v3.md).
## Installation
```bash
npm install --save eventsource-parser
```
## Usage
```ts
import {createParser, type EventSourceMessage} from 'eventsource-parser'
function onEvent(event: EventSourceMessage) {
console.log('Received event!')
console.log('id: %s', event.id || '<none>')
console.log('name: %s', event.name || '<none>')
console.log('data: %s', event.data)
}
const parser = createParser({onEvent})
const sseStream = getSomeReadableStream()
for await (const chunk of sseStream) {
parser.feed(chunk)
}
// If you want to re-use the parser for a new stream of events, make sure to reset it!
parser.reset()
console.log('Done!')
```
### Retry intervals
If the server sends a `retry` field in the event stream, the parser will call any `onRetry` callback specified to the `createParser` function:
```ts
const parser = createParser({
onRetry(retryInterval) {
console.log('Server requested retry interval of %dms', retryInterval)
},
onEvent(event) {
// …
},
})
```
### Parse errors
If the parser encounters an error while parsing, it will call any `onError` callback provided to the `createParser` function:
```ts
import {type ParseError} from 'eventsource-parser'
const parser = createParser({
onError(error: ParseError) {
console.error('Error parsing event:', error)
if (error.type === 'invalid-field') {
console.error('Field name:', error.field)
console.error('Field value:', error.value)
console.error('Line:', error.line)
} else if (error.type === 'invalid-retry') {
console.error('Invalid retry interval:', error.value)
}
},
onEvent(event) {
// …
},
})
```
Note that `invalid-field` errors will usually be called for any invalid data - not only data shaped as `field: value`. This is because the EventSource specification says to treat anything prior to a `:` as the field name. Use the `error.line` property to get the full line that caused the error.
> [!NOTE]
> When encountering the end of a stream, calling `.reset({consume: true})` on the parser to flush any remaining data and reset the parser state. This will trigger the `onError` callback if the pending data is not a valid event.
### Comments
The parser will ignore comments (lines starting with `:`) by default. If you want to handle comments, you can provide an `onComment` callback to the `createParser` function:
```ts
const parser = createParser({
onComment(comment) {
console.log('Received comment:', comment)
},
onEvent(event) {
// …
},
})
```
> [!NOTE]
> Leading whitespace is not stripped from comments, eg `: comment` will give ` comment` as the comment value, not `comment` (note the leading space).
## Stream usage
```ts
import {EventSourceParserStream} from 'eventsource-parser/stream'
const eventStream = response.body
.pipeThrough(new TextDecoderStream())
.pipeThrough(new EventSourceParserStream())
```
Note that the TransformStream is exposed under a separate export (`eventsource-parser/stream`), in order to maximize compatibility with environments that do not have the `TransformStream` constructor available.
## License
MIT © [Espen Hovlandsdal](https://espen.codes/)

View File

@@ -0,0 +1,106 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: !0 });
class ParseError extends Error {
constructor(message, options) {
super(message), this.name = "ParseError", this.type = options.type, this.field = options.field, this.value = options.value, this.line = options.line;
}
}
function noop(_arg) {
}
function createParser(callbacks) {
if (typeof callbacks == "function")
throw new TypeError(
"`callbacks` must be an object, got a function instead. Did you mean `{onEvent: fn}`?"
);
const { onEvent = noop, onError = noop, onRetry = noop, onComment } = callbacks;
let incompleteLine = "", isFirstChunk = !0, id, data = "", eventType = "";
function feed(newChunk) {
const chunk = isFirstChunk ? newChunk.replace(/^\xEF\xBB\xBF/, "") : newChunk, [complete, incomplete] = splitLines(`${incompleteLine}${chunk}`);
for (const line of complete)
parseLine(line);
incompleteLine = incomplete, isFirstChunk = !1;
}
function parseLine(line) {
if (line === "") {
dispatchEvent();
return;
}
if (line.startsWith(":")) {
onComment && onComment(line.slice(line.startsWith(": ") ? 2 : 1));
return;
}
const fieldSeparatorIndex = line.indexOf(":");
if (fieldSeparatorIndex !== -1) {
const field = line.slice(0, fieldSeparatorIndex), offset = line[fieldSeparatorIndex + 1] === " " ? 2 : 1, value = line.slice(fieldSeparatorIndex + offset);
processField(field, value, line);
return;
}
processField(line, "", line);
}
function processField(field, value, line) {
switch (field) {
case "event":
eventType = value;
break;
case "data":
data = `${data}${value}
`;
break;
case "id":
id = value.includes("\0") ? void 0 : value;
break;
case "retry":
/^\d+$/.test(value) ? onRetry(parseInt(value, 10)) : onError(
new ParseError(`Invalid \`retry\` value: "${value}"`, {
type: "invalid-retry",
value,
line
})
);
break;
default:
onError(
new ParseError(
`Unknown field "${field.length > 20 ? `${field.slice(0, 20)}\u2026` : field}"`,
{ type: "unknown-field", field, value, line }
)
);
break;
}
}
function dispatchEvent() {
data.length > 0 && onEvent({
id,
event: eventType || void 0,
// If the data buffer's last character is a U+000A LINE FEED (LF) character,
// then remove the last character from the data buffer.
data: data.endsWith(`
`) ? data.slice(0, -1) : data
}), id = void 0, data = "", eventType = "";
}
function reset(options = {}) {
incompleteLine && options.consume && parseLine(incompleteLine), isFirstChunk = !0, id = void 0, data = "", eventType = "", incompleteLine = "";
}
return { feed, reset };
}
function splitLines(chunk) {
const lines = [];
let incompleteLine = "", searchIndex = 0;
for (; searchIndex < chunk.length; ) {
const crIndex = chunk.indexOf("\r", searchIndex), lfIndex = chunk.indexOf(`
`, searchIndex);
let lineEnd = -1;
if (crIndex !== -1 && lfIndex !== -1 ? lineEnd = Math.min(crIndex, lfIndex) : crIndex !== -1 ? lineEnd = crIndex : lfIndex !== -1 && (lineEnd = lfIndex), lineEnd === -1) {
incompleteLine = chunk.slice(searchIndex);
break;
} else {
const line = chunk.slice(searchIndex, lineEnd);
lines.push(line), searchIndex = lineEnd + 1, chunk[searchIndex - 1] === "\r" && chunk[searchIndex] === `
` && searchIndex++;
}
}
return [lines, incompleteLine];
}
exports.ParseError = ParseError;
exports.createParser = createParser;
//# sourceMappingURL=index.cjs.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,144 @@
/**
* Creates a new EventSource parser.
*
* @param callbacks - Callbacks to invoke on different parsing events:
* - `onEvent` when a new event is parsed
* - `onError` when an error occurs
* - `onRetry` when a new reconnection interval has been sent from the server
* - `onComment` when a comment is encountered in the stream
*
* @returns A new EventSource parser, with `parse` and `reset` methods.
* @public
*/
export declare function createParser(callbacks: ParserCallbacks): EventSourceParser
/**
* The type of error that occurred.
* @public
*/
export declare type ErrorType = 'invalid-retry' | 'unknown-field'
/**
* A parsed EventSource message event
*
* @public
*/
export declare interface EventSourceMessage {
/**
* The event type sent from the server. Note that this differs from the browser `EventSource`
* implementation in that browsers will default this to `message`, whereas this parser will
* leave this as `undefined` if not explicitly declared.
*/
event?: string
/**
* ID of the message, if any was provided by the server. Can be used by clients to keep the
* last received message ID in sync when reconnecting.
*/
id?: string
/**
* The data received for this message
*/
data: string
}
/**
* EventSource parser instance.
*
* Needs to be reset between reconnections/when switching data source, using the `reset()` method.
*
* @public
*/
export declare interface EventSourceParser {
/**
* Feeds the parser another chunk. The method _does not_ return a parsed message.
* Instead, if the chunk was a complete message (or completed a previously incomplete message),
* it will invoke the `onParse` callback used to create the parsers.
*
* @param chunk - The chunk to parse. Can be a partial, eg in the case of streaming messages.
* @public
*/
feed(chunk: string): void
/**
* Resets the parser state. This is required when you have a new stream of messages -
* for instance in the case of a client being disconnected and reconnecting.
*
* Previously received, incomplete data will NOT be parsed unless you pass `consume: true`,
* which tells the parser to attempt to consume any incomplete data as if it ended with a newline
* character. This is useful for cases when a server sends a non-EventSource message that you
* want to be able to react to in an `onError` callback.
*
* @public
*/
reset(options?: {consume?: boolean}): void
}
/**
* Error thrown when encountering an issue during parsing.
*
* @public
*/
export declare class ParseError extends Error {
/**
* The type of error that occurred.
*/
type: ErrorType
/**
* In the case of an unknown field encountered in the stream, this will be the field name.
*/
field?: string
/**
* In the case of an unknown field encountered in the stream, this will be the value of the field.
*/
value?: string
/**
* The line that caused the error, if available.
*/
line?: string
constructor(
message: string,
options: {
type: ErrorType
field?: string
value?: string
line?: string
},
)
}
/**
* Callbacks that can be passed to the parser to handle different types of parsed messages
* and errors.
*
* @public
*/
export declare interface ParserCallbacks {
/**
* Callback for when a new event/message is parsed from the stream.
* This is the main callback that clients will use to handle incoming messages.
*
* @param event - The parsed event/message
*/
onEvent?: (event: EventSourceMessage) => void
/**
* Callback for when the server sends a new reconnection interval through the `retry` field.
*
* @param retry - The number of milliseconds to wait before reconnecting.
*/
onRetry?: (retry: number) => void
/**
* Callback for when a comment is encountered in the stream.
*
* @param comment - The comment encountered in the stream.
*/
onComment?: (comment: string) => void
/**
* Callback for when an error occurs during parsing. This is a catch-all for any errors
* that occur during parsing, and can be used to handle them in a custom way. Most clients
* tend to silently ignore any errors and instead retry, but it can be helpful to log/debug.
*
* @param error - The error that occurred during parsing
*/
onError?: (error: ParseError) => void
}
export {}

View File

@@ -0,0 +1,144 @@
/**
* Creates a new EventSource parser.
*
* @param callbacks - Callbacks to invoke on different parsing events:
* - `onEvent` when a new event is parsed
* - `onError` when an error occurs
* - `onRetry` when a new reconnection interval has been sent from the server
* - `onComment` when a comment is encountered in the stream
*
* @returns A new EventSource parser, with `parse` and `reset` methods.
* @public
*/
export declare function createParser(callbacks: ParserCallbacks): EventSourceParser
/**
* The type of error that occurred.
* @public
*/
export declare type ErrorType = 'invalid-retry' | 'unknown-field'
/**
* A parsed EventSource message event
*
* @public
*/
export declare interface EventSourceMessage {
/**
* The event type sent from the server. Note that this differs from the browser `EventSource`
* implementation in that browsers will default this to `message`, whereas this parser will
* leave this as `undefined` if not explicitly declared.
*/
event?: string
/**
* ID of the message, if any was provided by the server. Can be used by clients to keep the
* last received message ID in sync when reconnecting.
*/
id?: string
/**
* The data received for this message
*/
data: string
}
/**
* EventSource parser instance.
*
* Needs to be reset between reconnections/when switching data source, using the `reset()` method.
*
* @public
*/
export declare interface EventSourceParser {
/**
* Feeds the parser another chunk. The method _does not_ return a parsed message.
* Instead, if the chunk was a complete message (or completed a previously incomplete message),
* it will invoke the `onParse` callback used to create the parsers.
*
* @param chunk - The chunk to parse. Can be a partial, eg in the case of streaming messages.
* @public
*/
feed(chunk: string): void
/**
* Resets the parser state. This is required when you have a new stream of messages -
* for instance in the case of a client being disconnected and reconnecting.
*
* Previously received, incomplete data will NOT be parsed unless you pass `consume: true`,
* which tells the parser to attempt to consume any incomplete data as if it ended with a newline
* character. This is useful for cases when a server sends a non-EventSource message that you
* want to be able to react to in an `onError` callback.
*
* @public
*/
reset(options?: {consume?: boolean}): void
}
/**
* Error thrown when encountering an issue during parsing.
*
* @public
*/
export declare class ParseError extends Error {
/**
* The type of error that occurred.
*/
type: ErrorType
/**
* In the case of an unknown field encountered in the stream, this will be the field name.
*/
field?: string
/**
* In the case of an unknown field encountered in the stream, this will be the value of the field.
*/
value?: string
/**
* The line that caused the error, if available.
*/
line?: string
constructor(
message: string,
options: {
type: ErrorType
field?: string
value?: string
line?: string
},
)
}
/**
* Callbacks that can be passed to the parser to handle different types of parsed messages
* and errors.
*
* @public
*/
export declare interface ParserCallbacks {
/**
* Callback for when a new event/message is parsed from the stream.
* This is the main callback that clients will use to handle incoming messages.
*
* @param event - The parsed event/message
*/
onEvent?: (event: EventSourceMessage) => void
/**
* Callback for when the server sends a new reconnection interval through the `retry` field.
*
* @param retry - The number of milliseconds to wait before reconnecting.
*/
onRetry?: (retry: number) => void
/**
* Callback for when a comment is encountered in the stream.
*
* @param comment - The comment encountered in the stream.
*/
onComment?: (comment: string) => void
/**
* Callback for when an error occurs during parsing. This is a catch-all for any errors
* that occur during parsing, and can be used to handle them in a custom way. Most clients
* tend to silently ignore any errors and instead retry, but it can be helpful to log/debug.
*
* @param error - The error that occurred during parsing
*/
onError?: (error: ParseError) => void
}
export {}

View File

@@ -0,0 +1,106 @@
class ParseError extends Error {
constructor(message, options) {
super(message), this.name = "ParseError", this.type = options.type, this.field = options.field, this.value = options.value, this.line = options.line;
}
}
function noop(_arg) {
}
function createParser(callbacks) {
if (typeof callbacks == "function")
throw new TypeError(
"`callbacks` must be an object, got a function instead. Did you mean `{onEvent: fn}`?"
);
const { onEvent = noop, onError = noop, onRetry = noop, onComment } = callbacks;
let incompleteLine = "", isFirstChunk = !0, id, data = "", eventType = "";
function feed(newChunk) {
const chunk = isFirstChunk ? newChunk.replace(/^\xEF\xBB\xBF/, "") : newChunk, [complete, incomplete] = splitLines(`${incompleteLine}${chunk}`);
for (const line of complete)
parseLine(line);
incompleteLine = incomplete, isFirstChunk = !1;
}
function parseLine(line) {
if (line === "") {
dispatchEvent();
return;
}
if (line.startsWith(":")) {
onComment && onComment(line.slice(line.startsWith(": ") ? 2 : 1));
return;
}
const fieldSeparatorIndex = line.indexOf(":");
if (fieldSeparatorIndex !== -1) {
const field = line.slice(0, fieldSeparatorIndex), offset = line[fieldSeparatorIndex + 1] === " " ? 2 : 1, value = line.slice(fieldSeparatorIndex + offset);
processField(field, value, line);
return;
}
processField(line, "", line);
}
function processField(field, value, line) {
switch (field) {
case "event":
eventType = value;
break;
case "data":
data = `${data}${value}
`;
break;
case "id":
id = value.includes("\0") ? void 0 : value;
break;
case "retry":
/^\d+$/.test(value) ? onRetry(parseInt(value, 10)) : onError(
new ParseError(`Invalid \`retry\` value: "${value}"`, {
type: "invalid-retry",
value,
line
})
);
break;
default:
onError(
new ParseError(
`Unknown field "${field.length > 20 ? `${field.slice(0, 20)}\u2026` : field}"`,
{ type: "unknown-field", field, value, line }
)
);
break;
}
}
function dispatchEvent() {
data.length > 0 && onEvent({
id,
event: eventType || void 0,
// If the data buffer's last character is a U+000A LINE FEED (LF) character,
// then remove the last character from the data buffer.
data: data.endsWith(`
`) ? data.slice(0, -1) : data
}), id = void 0, data = "", eventType = "";
}
function reset(options = {}) {
incompleteLine && options.consume && parseLine(incompleteLine), isFirstChunk = !0, id = void 0, data = "", eventType = "", incompleteLine = "";
}
return { feed, reset };
}
function splitLines(chunk) {
const lines = [];
let incompleteLine = "", searchIndex = 0;
for (; searchIndex < chunk.length; ) {
const crIndex = chunk.indexOf("\r", searchIndex), lfIndex = chunk.indexOf(`
`, searchIndex);
let lineEnd = -1;
if (crIndex !== -1 && lfIndex !== -1 ? lineEnd = Math.min(crIndex, lfIndex) : crIndex !== -1 ? lineEnd = crIndex : lfIndex !== -1 && (lineEnd = lfIndex), lineEnd === -1) {
incompleteLine = chunk.slice(searchIndex);
break;
} else {
const line = chunk.slice(searchIndex, lineEnd);
lines.push(line), searchIndex = lineEnd + 1, chunk[searchIndex - 1] === "\r" && chunk[searchIndex] === `
` && searchIndex++;
}
}
return [lines, incompleteLine];
}
export {
ParseError,
createParser
};
//# sourceMappingURL=index.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,28 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: !0 });
var index = require("./index.cjs");
class EventSourceParserStream extends TransformStream {
constructor({ onError, onRetry, onComment } = {}) {
let parser;
super({
start(controller) {
parser = index.createParser({
onEvent: (event) => {
controller.enqueue(event);
},
onError(error) {
onError === "terminate" ? controller.error(error) : typeof onError == "function" && onError(error);
},
onRetry,
onComment
});
},
transform(chunk) {
parser.feed(chunk);
}
});
}
}
exports.ParseError = index.ParseError;
exports.EventSourceParserStream = EventSourceParserStream;
//# sourceMappingURL=stream.cjs.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"stream.cjs","sources":["../src/stream.ts"],"sourcesContent":["import {createParser} from './parse.ts'\nimport type {EventSourceMessage, EventSourceParser} from './types.ts'\n\n/**\n * Options for the EventSourceParserStream.\n *\n * @public\n */\nexport interface StreamOptions {\n /**\n * Behavior when a parsing error occurs.\n *\n * - A custom function can be provided to handle the error.\n * - `'terminate'` will error the stream and stop parsing.\n * - Any other value will ignore the error and continue parsing.\n *\n * @defaultValue `undefined`\n */\n onError?: 'terminate' | ((error: Error) => void)\n\n /**\n * Callback for when a reconnection interval is sent from the server.\n *\n * @param retry - The number of milliseconds to wait before reconnecting.\n */\n onRetry?: (retry: number) => void\n\n /**\n * Callback for when a comment is encountered in the stream.\n *\n * @param comment - The comment encountered in the stream.\n */\n onComment?: (comment: string) => void\n}\n\n/**\n * A TransformStream that ingests a stream of strings and produces a stream of `EventSourceMessage`.\n *\n * @example Basic usage\n * ```\n * const eventStream =\n * response.body\n * .pipeThrough(new TextDecoderStream())\n * .pipeThrough(new EventSourceParserStream())\n * ```\n *\n * @example Terminate stream on parsing errors\n * ```\n * const eventStream =\n * response.body\n * .pipeThrough(new TextDecoderStream())\n * .pipeThrough(new EventSourceParserStream({terminateOnError: true}))\n * ```\n *\n * @public\n */\nexport class EventSourceParserStream extends TransformStream<string, EventSourceMessage> {\n constructor({onError, onRetry, onComment}: StreamOptions = {}) {\n let parser!: EventSourceParser\n\n super({\n start(controller) {\n parser = createParser({\n onEvent: (event) => {\n controller.enqueue(event)\n },\n onError(error) {\n if (onError === 'terminate') {\n controller.error(error)\n } else if (typeof onError === 'function') {\n onError(error)\n }\n\n // Ignore by default\n },\n onRetry,\n onComment,\n })\n },\n transform(chunk) {\n parser.feed(chunk)\n },\n })\n }\n}\n\nexport {type ErrorType, ParseError} from './errors.ts'\nexport type {EventSourceMessage} from './types.ts'\n"],"names":["createParser"],"mappings":";;;AAwDO,MAAM,gCAAgC,gBAA4C;AAAA,EACvF,YAAY,EAAC,SAAS,SAAS,UAAS,IAAmB,CAAA,GAAI;AACzD,QAAA;AAEE,UAAA;AAAA,MACJ,MAAM,YAAY;AAChB,iBAASA,MAAAA,aAAa;AAAA,UACpB,SAAS,CAAC,UAAU;AAClB,uBAAW,QAAQ,KAAK;AAAA,UAC1B;AAAA,UACA,QAAQ,OAAO;AACT,wBAAY,cACd,WAAW,MAAM,KAAK,IACb,OAAO,WAAY,cAC5B,QAAQ,KAAK;AAAA,UAIjB;AAAA,UACA;AAAA,UACA;AAAA,QAAA,CACD;AAAA,MACH;AAAA,MACA,UAAU,OAAO;AACf,eAAO,KAAK,KAAK;AAAA,MAAA;AAAA,IACnB,CACD;AAAA,EAAA;AAEL;;;"}

View File

@@ -0,0 +1,118 @@
/**
* The type of error that occurred.
* @public
*/
export declare type ErrorType = 'invalid-retry' | 'unknown-field'
/**
* A parsed EventSource message event
*
* @public
*/
export declare interface EventSourceMessage {
/**
* The event type sent from the server. Note that this differs from the browser `EventSource`
* implementation in that browsers will default this to `message`, whereas this parser will
* leave this as `undefined` if not explicitly declared.
*/
event?: string
/**
* ID of the message, if any was provided by the server. Can be used by clients to keep the
* last received message ID in sync when reconnecting.
*/
id?: string
/**
* The data received for this message
*/
data: string
}
/**
* A TransformStream that ingests a stream of strings and produces a stream of `EventSourceMessage`.
*
* @example Basic usage
* ```
* const eventStream =
* response.body
* .pipeThrough(new TextDecoderStream())
* .pipeThrough(new EventSourceParserStream())
* ```
*
* @example Terminate stream on parsing errors
* ```
* const eventStream =
* response.body
* .pipeThrough(new TextDecoderStream())
* .pipeThrough(new EventSourceParserStream({terminateOnError: true}))
* ```
*
* @public
*/
export declare class EventSourceParserStream extends TransformStream<string, EventSourceMessage> {
constructor({onError, onRetry, onComment}?: StreamOptions)
}
/**
* Error thrown when encountering an issue during parsing.
*
* @public
*/
export declare class ParseError extends Error {
/**
* The type of error that occurred.
*/
type: ErrorType
/**
* In the case of an unknown field encountered in the stream, this will be the field name.
*/
field?: string
/**
* In the case of an unknown field encountered in the stream, this will be the value of the field.
*/
value?: string
/**
* The line that caused the error, if available.
*/
line?: string
constructor(
message: string,
options: {
type: ErrorType
field?: string
value?: string
line?: string
},
)
}
/**
* Options for the EventSourceParserStream.
*
* @public
*/
export declare interface StreamOptions {
/**
* Behavior when a parsing error occurs.
*
* - A custom function can be provided to handle the error.
* - `'terminate'` will error the stream and stop parsing.
* - Any other value will ignore the error and continue parsing.
*
* @defaultValue `undefined`
*/
onError?: 'terminate' | ((error: Error) => void)
/**
* Callback for when a reconnection interval is sent from the server.
*
* @param retry - The number of milliseconds to wait before reconnecting.
*/
onRetry?: (retry: number) => void
/**
* Callback for when a comment is encountered in the stream.
*
* @param comment - The comment encountered in the stream.
*/
onComment?: (comment: string) => void
}
export {}

View File

@@ -0,0 +1,118 @@
/**
* The type of error that occurred.
* @public
*/
export declare type ErrorType = 'invalid-retry' | 'unknown-field'
/**
* A parsed EventSource message event
*
* @public
*/
export declare interface EventSourceMessage {
/**
* The event type sent from the server. Note that this differs from the browser `EventSource`
* implementation in that browsers will default this to `message`, whereas this parser will
* leave this as `undefined` if not explicitly declared.
*/
event?: string
/**
* ID of the message, if any was provided by the server. Can be used by clients to keep the
* last received message ID in sync when reconnecting.
*/
id?: string
/**
* The data received for this message
*/
data: string
}
/**
* A TransformStream that ingests a stream of strings and produces a stream of `EventSourceMessage`.
*
* @example Basic usage
* ```
* const eventStream =
* response.body
* .pipeThrough(new TextDecoderStream())
* .pipeThrough(new EventSourceParserStream())
* ```
*
* @example Terminate stream on parsing errors
* ```
* const eventStream =
* response.body
* .pipeThrough(new TextDecoderStream())
* .pipeThrough(new EventSourceParserStream({terminateOnError: true}))
* ```
*
* @public
*/
export declare class EventSourceParserStream extends TransformStream<string, EventSourceMessage> {
constructor({onError, onRetry, onComment}?: StreamOptions)
}
/**
* Error thrown when encountering an issue during parsing.
*
* @public
*/
export declare class ParseError extends Error {
/**
* The type of error that occurred.
*/
type: ErrorType
/**
* In the case of an unknown field encountered in the stream, this will be the field name.
*/
field?: string
/**
* In the case of an unknown field encountered in the stream, this will be the value of the field.
*/
value?: string
/**
* The line that caused the error, if available.
*/
line?: string
constructor(
message: string,
options: {
type: ErrorType
field?: string
value?: string
line?: string
},
)
}
/**
* Options for the EventSourceParserStream.
*
* @public
*/
export declare interface StreamOptions {
/**
* Behavior when a parsing error occurs.
*
* - A custom function can be provided to handle the error.
* - `'terminate'` will error the stream and stop parsing.
* - Any other value will ignore the error and continue parsing.
*
* @defaultValue `undefined`
*/
onError?: 'terminate' | ((error: Error) => void)
/**
* Callback for when a reconnection interval is sent from the server.
*
* @param retry - The number of milliseconds to wait before reconnecting.
*/
onRetry?: (retry: number) => void
/**
* Callback for when a comment is encountered in the stream.
*
* @param comment - The comment encountered in the stream.
*/
onComment?: (comment: string) => void
}
export {}

View File

@@ -0,0 +1,29 @@
import { createParser } from "./index.js";
import { ParseError } from "./index.js";
class EventSourceParserStream extends TransformStream {
constructor({ onError, onRetry, onComment } = {}) {
let parser;
super({
start(controller) {
parser = createParser({
onEvent: (event) => {
controller.enqueue(event);
},
onError(error) {
onError === "terminate" ? controller.error(error) : typeof onError == "function" && onError(error);
},
onRetry,
onComment
});
},
transform(chunk) {
parser.feed(chunk);
}
});
}
}
export {
EventSourceParserStream,
ParseError
};
//# sourceMappingURL=stream.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"stream.js","sources":["../src/stream.ts"],"sourcesContent":["import {createParser} from './parse.ts'\nimport type {EventSourceMessage, EventSourceParser} from './types.ts'\n\n/**\n * Options for the EventSourceParserStream.\n *\n * @public\n */\nexport interface StreamOptions {\n /**\n * Behavior when a parsing error occurs.\n *\n * - A custom function can be provided to handle the error.\n * - `'terminate'` will error the stream and stop parsing.\n * - Any other value will ignore the error and continue parsing.\n *\n * @defaultValue `undefined`\n */\n onError?: 'terminate' | ((error: Error) => void)\n\n /**\n * Callback for when a reconnection interval is sent from the server.\n *\n * @param retry - The number of milliseconds to wait before reconnecting.\n */\n onRetry?: (retry: number) => void\n\n /**\n * Callback for when a comment is encountered in the stream.\n *\n * @param comment - The comment encountered in the stream.\n */\n onComment?: (comment: string) => void\n}\n\n/**\n * A TransformStream that ingests a stream of strings and produces a stream of `EventSourceMessage`.\n *\n * @example Basic usage\n * ```\n * const eventStream =\n * response.body\n * .pipeThrough(new TextDecoderStream())\n * .pipeThrough(new EventSourceParserStream())\n * ```\n *\n * @example Terminate stream on parsing errors\n * ```\n * const eventStream =\n * response.body\n * .pipeThrough(new TextDecoderStream())\n * .pipeThrough(new EventSourceParserStream({terminateOnError: true}))\n * ```\n *\n * @public\n */\nexport class EventSourceParserStream extends TransformStream<string, EventSourceMessage> {\n constructor({onError, onRetry, onComment}: StreamOptions = {}) {\n let parser!: EventSourceParser\n\n super({\n start(controller) {\n parser = createParser({\n onEvent: (event) => {\n controller.enqueue(event)\n },\n onError(error) {\n if (onError === 'terminate') {\n controller.error(error)\n } else if (typeof onError === 'function') {\n onError(error)\n }\n\n // Ignore by default\n },\n onRetry,\n onComment,\n })\n },\n transform(chunk) {\n parser.feed(chunk)\n },\n })\n }\n}\n\nexport {type ErrorType, ParseError} from './errors.ts'\nexport type {EventSourceMessage} from './types.ts'\n"],"names":[],"mappings":";;AAwDO,MAAM,gCAAgC,gBAA4C;AAAA,EACvF,YAAY,EAAC,SAAS,SAAS,UAAS,IAAmB,CAAA,GAAI;AACzD,QAAA;AAEE,UAAA;AAAA,MACJ,MAAM,YAAY;AAChB,iBAAS,aAAa;AAAA,UACpB,SAAS,CAAC,UAAU;AAClB,uBAAW,QAAQ,KAAK;AAAA,UAC1B;AAAA,UACA,QAAQ,OAAO;AACT,wBAAY,cACd,WAAW,MAAM,KAAK,IACb,OAAO,WAAY,cAC5B,QAAQ,KAAK;AAAA,UAIjB;AAAA,UACA;AAAA,UACA;AAAA,QAAA,CACD;AAAA,MACH;AAAA,MACA,UAAU,OAAO;AACf,eAAO,KAAK,KAAK;AAAA,MAAA;AAAA,IACnB,CACD;AAAA,EAAA;AAEL;"}

115
mcp-server/node_modules/eventsource-parser/package.json generated vendored Normal file
View File

@@ -0,0 +1,115 @@
{
"name": "eventsource-parser",
"version": "3.0.3",
"description": "Streaming, source-agnostic EventSource/Server-Sent Events parser",
"sideEffects": false,
"type": "module",
"types": "./dist/index.d.ts",
"module": "./dist/index.js",
"main": "./dist/index.cjs",
"exports": {
".": {
"source": "./src/index.ts",
"import": "./dist/index.js",
"require": "./dist/index.cjs",
"default": "./dist/index.js"
},
"./stream": {
"source": "./src/stream.ts",
"import": "./dist/stream.js",
"require": "./dist/stream.cjs",
"default": "./dist/stream.js"
},
"./package.json": "./package.json"
},
"typesVersions": {
"*": {
"stream": [
"./dist/stream.d.ts"
]
}
},
"engines": {
"node": ">=20.0.0"
},
"browserslist": [
"node >= 20",
"chrome >= 71",
"safari >= 14.1",
"firefox >= 105",
"edge >= 79"
],
"files": [
"dist",
"!dist/stats.html",
"src",
"stream.js"
],
"scripts": {
"build": "pkg-utils build && pkg-utils --strict",
"clean": "rimraf dist coverage",
"lint": "eslint . && tsc --noEmit",
"posttest": "npm run lint",
"prebuild": "npm run clean",
"prepublishOnly": "npm run build",
"test": "npm run test:node",
"test:bun": "bun test",
"test:deno": "deno run --allow-write --allow-net --allow-run --allow-sys --allow-ffi --allow-env --allow-read npm:vitest",
"test:node": "vitest --reporter=verbose"
},
"author": "Espen Hovlandsdal <espen@hovlandsdal.com>",
"keywords": [
"sse",
"eventsource",
"server-sent-events"
],
"devDependencies": {
"@sanity/pkg-utils": "^7.2.2",
"@sanity/semantic-release-preset": "^5.0.0",
"@types/node": "^18.0.0",
"@typescript-eslint/eslint-plugin": "^7.0.0",
"@typescript-eslint/parser": "^7.0.0",
"eslint": "^8.51.0",
"eslint-config-prettier": "^9.1.0",
"eslint-config-sanity": "^7.1.2",
"eventsource-encoder": "^1.0.1",
"prettier": "^3.5.3",
"rimraf": "^6.0.1",
"rollup-plugin-visualizer": "^5.12.0",
"semantic-release": "^24.2.3",
"typescript": "^5.8.3",
"vitest": "^3.1.3"
},
"homepage": "https://github.com/rexxars/eventsource-parser#readme",
"bugs": {
"url": "https://github.com/rexxars/eventsource-parser/issues"
},
"repository": {
"type": "git",
"url": "git+ssh://git@github.com/rexxars/eventsource-parser.git"
},
"license": "MIT",
"prettier": {
"bracketSpacing": false,
"printWidth": 100,
"semi": false,
"singleQuote": true
},
"eslintConfig": {
"parserOptions": {
"ecmaFeatures": {
"modules": true
},
"ecmaVersion": 9,
"sourceType": "module"
},
"extends": [
"sanity",
"sanity/typescript",
"prettier"
],
"ignorePatterns": [
"lib/**/"
]
}
}

View File

@@ -0,0 +1,44 @@
/**
* The type of error that occurred.
* @public
*/
export type ErrorType = 'invalid-retry' | 'unknown-field'
/**
* Error thrown when encountering an issue during parsing.
*
* @public
*/
export class ParseError extends Error {
/**
* The type of error that occurred.
*/
type: ErrorType
/**
* In the case of an unknown field encountered in the stream, this will be the field name.
*/
field?: string
/**
* In the case of an unknown field encountered in the stream, this will be the value of the field.
*/
value?: string
/**
* The line that caused the error, if available.
*/
line?: string
constructor(
message: string,
options: {type: ErrorType; field?: string; value?: string; line?: string},
) {
super(message)
this.name = 'ParseError'
this.type = options.type
this.field = options.field
this.value = options.value
this.line = options.line
}
}

View File

@@ -0,0 +1,3 @@
export {type ErrorType, ParseError} from './errors.ts'
export {createParser} from './parse.ts'
export type {EventSourceMessage, EventSourceParser, ParserCallbacks} from './types.ts'

226
mcp-server/node_modules/eventsource-parser/src/parse.ts generated vendored Normal file
View File

@@ -0,0 +1,226 @@
/**
* EventSource/Server-Sent Events parser
* @see https://html.spec.whatwg.org/multipage/server-sent-events.html
*/
import {ParseError} from './errors.ts'
import type {EventSourceParser, ParserCallbacks} from './types.ts'
// eslint-disable-next-line @typescript-eslint/no-unused-vars
function noop(_arg: unknown) {
// intentional noop
}
/**
* Creates a new EventSource parser.
*
* @param callbacks - Callbacks to invoke on different parsing events:
* - `onEvent` when a new event is parsed
* - `onError` when an error occurs
* - `onRetry` when a new reconnection interval has been sent from the server
* - `onComment` when a comment is encountered in the stream
*
* @returns A new EventSource parser, with `parse` and `reset` methods.
* @public
*/
export function createParser(callbacks: ParserCallbacks): EventSourceParser {
if (typeof callbacks === 'function') {
throw new TypeError(
'`callbacks` must be an object, got a function instead. Did you mean `{onEvent: fn}`?',
)
}
const {onEvent = noop, onError = noop, onRetry = noop, onComment} = callbacks
let incompleteLine = ''
let isFirstChunk = true
let id: string | undefined
let data = ''
let eventType = ''
function feed(newChunk: string) {
// Strip any UTF8 byte order mark (BOM) at the start of the stream
const chunk = isFirstChunk ? newChunk.replace(/^\xEF\xBB\xBF/, '') : newChunk
// If there was a previous incomplete line, append it to the new chunk,
// so we may process it together as a new (hopefully complete) chunk.
const [complete, incomplete] = splitLines(`${incompleteLine}${chunk}`)
for (const line of complete) {
parseLine(line)
}
incompleteLine = incomplete
isFirstChunk = false
}
function parseLine(line: string) {
// If the line is empty (a blank line), dispatch the event
if (line === '') {
dispatchEvent()
return
}
// If the line starts with a U+003A COLON character (:), ignore the line.
if (line.startsWith(':')) {
if (onComment) {
onComment(line.slice(line.startsWith(': ') ? 2 : 1))
}
return
}
// If the line contains a U+003A COLON character (:)
const fieldSeparatorIndex = line.indexOf(':')
if (fieldSeparatorIndex !== -1) {
// Collect the characters on the line before the first U+003A COLON character (:),
// and let `field` be that string.
const field = line.slice(0, fieldSeparatorIndex)
// Collect the characters on the line after the first U+003A COLON character (:),
// and let `value` be that string. If value starts with a U+0020 SPACE character,
// remove it from value.
const offset = line[fieldSeparatorIndex + 1] === ' ' ? 2 : 1
const value = line.slice(fieldSeparatorIndex + offset)
processField(field, value, line)
return
}
// Otherwise, the string is not empty but does not contain a U+003A COLON character (:)
// Process the field using the whole line as the field name, and an empty string as the field value.
// 👆 This is according to spec. That means that a line that has the value `data` will result in
// a newline being added to the current `data` buffer, for instance.
processField(line, '', line)
}
function processField(field: string, value: string, line: string) {
// Field names must be compared literally, with no case folding performed.
switch (field) {
case 'event':
// Set the `event type` buffer to field value
eventType = value
break
case 'data':
// Append the field value to the `data` buffer, then append a single U+000A LINE FEED(LF)
// character to the `data` buffer.
data = `${data}${value}\n`
break
case 'id':
// If the field value does not contain U+0000 NULL, then set the `ID` buffer to
// the field value. Otherwise, ignore the field.
id = value.includes('\0') ? undefined : value
break
case 'retry':
// If the field value consists of only ASCII digits, then interpret the field value as an
// integer in base ten, and set the event stream's reconnection time to that integer.
// Otherwise, ignore the field.
if (/^\d+$/.test(value)) {
onRetry(parseInt(value, 10))
} else {
onError(
new ParseError(`Invalid \`retry\` value: "${value}"`, {
type: 'invalid-retry',
value,
line,
}),
)
}
break
default:
// Otherwise, the field is ignored.
onError(
new ParseError(
`Unknown field "${field.length > 20 ? `${field.slice(0, 20)}` : field}"`,
{type: 'unknown-field', field, value, line},
),
)
break
}
}
function dispatchEvent() {
const shouldDispatch = data.length > 0
if (shouldDispatch) {
onEvent({
id,
event: eventType || undefined,
// If the data buffer's last character is a U+000A LINE FEED (LF) character,
// then remove the last character from the data buffer.
data: data.endsWith('\n') ? data.slice(0, -1) : data,
})
}
// Reset for the next event
id = undefined
data = ''
eventType = ''
}
function reset(options: {consume?: boolean} = {}) {
if (incompleteLine && options.consume) {
parseLine(incompleteLine)
}
isFirstChunk = true
id = undefined
data = ''
eventType = ''
incompleteLine = ''
}
return {feed, reset}
}
/**
* For the given `chunk`, split it into lines according to spec, and return any remaining incomplete line.
*
* @param chunk - The chunk to split into lines
* @returns A tuple containing an array of complete lines, and any remaining incomplete line
* @internal
*/
function splitLines(chunk: string): [complete: Array<string>, incomplete: string] {
/**
* According to the spec, a line is terminated by either:
* - U+000D CARRIAGE RETURN U+000A LINE FEED (CRLF) character pair
* - a single U+000A LINE FEED(LF) character not preceded by a U+000D CARRIAGE RETURN(CR) character
* - a single U+000D CARRIAGE RETURN(CR) character not followed by a U+000A LINE FEED(LF) character
*/
const lines: Array<string> = []
let incompleteLine = ''
let searchIndex = 0
while (searchIndex < chunk.length) {
// Find next line terminator
const crIndex = chunk.indexOf('\r', searchIndex)
const lfIndex = chunk.indexOf('\n', searchIndex)
// Determine line end
let lineEnd = -1
if (crIndex !== -1 && lfIndex !== -1) {
// CRLF case
lineEnd = Math.min(crIndex, lfIndex)
} else if (crIndex !== -1) {
lineEnd = crIndex
} else if (lfIndex !== -1) {
lineEnd = lfIndex
}
// Extract line if terminator found
if (lineEnd === -1) {
// No terminator found, rest is incomplete
incompleteLine = chunk.slice(searchIndex)
break
} else {
const line = chunk.slice(searchIndex, lineEnd)
lines.push(line)
// Move past line terminator
searchIndex = lineEnd + 1
if (chunk[searchIndex - 1] === '\r' && chunk[searchIndex] === '\n') {
searchIndex++
}
}
}
return [lines, incompleteLine]
}

View File

@@ -0,0 +1,88 @@
import {createParser} from './parse.ts'
import type {EventSourceMessage, EventSourceParser} from './types.ts'
/**
* Options for the EventSourceParserStream.
*
* @public
*/
export interface StreamOptions {
/**
* Behavior when a parsing error occurs.
*
* - A custom function can be provided to handle the error.
* - `'terminate'` will error the stream and stop parsing.
* - Any other value will ignore the error and continue parsing.
*
* @defaultValue `undefined`
*/
onError?: 'terminate' | ((error: Error) => void)
/**
* Callback for when a reconnection interval is sent from the server.
*
* @param retry - The number of milliseconds to wait before reconnecting.
*/
onRetry?: (retry: number) => void
/**
* Callback for when a comment is encountered in the stream.
*
* @param comment - The comment encountered in the stream.
*/
onComment?: (comment: string) => void
}
/**
* A TransformStream that ingests a stream of strings and produces a stream of `EventSourceMessage`.
*
* @example Basic usage
* ```
* const eventStream =
* response.body
* .pipeThrough(new TextDecoderStream())
* .pipeThrough(new EventSourceParserStream())
* ```
*
* @example Terminate stream on parsing errors
* ```
* const eventStream =
* response.body
* .pipeThrough(new TextDecoderStream())
* .pipeThrough(new EventSourceParserStream({terminateOnError: true}))
* ```
*
* @public
*/
export class EventSourceParserStream extends TransformStream<string, EventSourceMessage> {
constructor({onError, onRetry, onComment}: StreamOptions = {}) {
let parser!: EventSourceParser
super({
start(controller) {
parser = createParser({
onEvent: (event) => {
controller.enqueue(event)
},
onError(error) {
if (onError === 'terminate') {
controller.error(error)
} else if (typeof onError === 'function') {
onError(error)
}
// Ignore by default
},
onRetry,
onComment,
})
},
transform(chunk) {
parser.feed(chunk)
},
})
}
}
export {type ErrorType, ParseError} from './errors.ts'
export type {EventSourceMessage} from './types.ts'

View File

@@ -0,0 +1,97 @@
import type {ParseError} from './errors.ts'
/**
* EventSource parser instance.
*
* Needs to be reset between reconnections/when switching data source, using the `reset()` method.
*
* @public
*/
export interface EventSourceParser {
/**
* Feeds the parser another chunk. The method _does not_ return a parsed message.
* Instead, if the chunk was a complete message (or completed a previously incomplete message),
* it will invoke the `onParse` callback used to create the parsers.
*
* @param chunk - The chunk to parse. Can be a partial, eg in the case of streaming messages.
* @public
*/
feed(chunk: string): void
/**
* Resets the parser state. This is required when you have a new stream of messages -
* for instance in the case of a client being disconnected and reconnecting.
*
* Previously received, incomplete data will NOT be parsed unless you pass `consume: true`,
* which tells the parser to attempt to consume any incomplete data as if it ended with a newline
* character. This is useful for cases when a server sends a non-EventSource message that you
* want to be able to react to in an `onError` callback.
*
* @public
*/
reset(options?: {consume?: boolean}): void
}
/**
* A parsed EventSource message event
*
* @public
*/
export interface EventSourceMessage {
/**
* The event type sent from the server. Note that this differs from the browser `EventSource`
* implementation in that browsers will default this to `message`, whereas this parser will
* leave this as `undefined` if not explicitly declared.
*/
event?: string
/**
* ID of the message, if any was provided by the server. Can be used by clients to keep the
* last received message ID in sync when reconnecting.
*/
id?: string
/**
* The data received for this message
*/
data: string
}
/**
* Callbacks that can be passed to the parser to handle different types of parsed messages
* and errors.
*
* @public
*/
export interface ParserCallbacks {
/**
* Callback for when a new event/message is parsed from the stream.
* This is the main callback that clients will use to handle incoming messages.
*
* @param event - The parsed event/message
*/
onEvent?: (event: EventSourceMessage) => void
/**
* Callback for when the server sends a new reconnection interval through the `retry` field.
*
* @param retry - The number of milliseconds to wait before reconnecting.
*/
onRetry?: (retry: number) => void
/**
* Callback for when a comment is encountered in the stream.
*
* @param comment - The comment encountered in the stream.
*/
onComment?: (comment: string) => void
/**
* Callback for when an error occurs during parsing. This is a catch-all for any errors
* that occur during parsing, and can be used to handle them in a custom way. Most clients
* tend to silently ignore any errors and instead retry, but it can be helpful to log/debug.
*
* @param error - The error that occurred during parsing
*/
onError?: (error: ParseError) => void
}

2
mcp-server/node_modules/eventsource-parser/stream.js generated vendored Normal file
View File

@@ -0,0 +1,2 @@
/* included for compatibility with react-native without package exports support */
module.exports = require('./dist/stream.cjs')