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:
44
mcp-server/node_modules/eventsource-parser/src/errors.ts
generated
vendored
Normal file
44
mcp-server/node_modules/eventsource-parser/src/errors.ts
generated
vendored
Normal 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
|
||||
}
|
||||
}
|
||||
3
mcp-server/node_modules/eventsource-parser/src/index.ts
generated
vendored
Normal file
3
mcp-server/node_modules/eventsource-parser/src/index.ts
generated
vendored
Normal 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
226
mcp-server/node_modules/eventsource-parser/src/parse.ts
generated
vendored
Normal 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]
|
||||
}
|
||||
88
mcp-server/node_modules/eventsource-parser/src/stream.ts
generated
vendored
Normal file
88
mcp-server/node_modules/eventsource-parser/src/stream.ts
generated
vendored
Normal 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'
|
||||
97
mcp-server/node_modules/eventsource-parser/src/types.ts
generated
vendored
Normal file
97
mcp-server/node_modules/eventsource-parser/src/types.ts
generated
vendored
Normal 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
|
||||
}
|
||||
Reference in New Issue
Block a user