UNPKG

@juspay/neurolink

Version:

Universal AI Development Platform with working MCP integration, multi-provider support, voice (TTS/STT/realtime), and professional CLI. 58+ external MCP servers discoverable, multimodal file processing, RAG pipelines. Build, test, and deploy AI applicatio

145 lines (144 loc) 5.24 kB
/** * Claude Messages API format conversion layer. * * Provides a request parser (Claude -> NeuroLink), a response serializer * (NeuroLink -> Claude), a streaming SSE state machine, and an error * envelope helper. Together they allow NeuroLink to act as a * drop-in Claude API proxy. * * Reference: https://docs.anthropic.com/en/api/messages */ import type { ClaudeErrorResponse, ClaudeRequest, ClaudeResponse, ContentBlockType, InternalResult, ParsedClaudeRequest, StreamLifecycleState } from "../types/index.js"; /** Generate a unique message id in the Claude format. */ export declare function generateMessageId(): string; /** Generate a Claude-format tool use ID (`toolu_` + 24 random chars). */ export declare function generateToolUseId(): string; /** * Reset the internal id counter (useful in tests). * @internal */ export declare function _resetIdCounter(): void; /** * Parse an incoming Claude Messages API request into an intermediate * representation consumable by NeuroLink's generate/stream pipeline. * * Handles: * - System prompt extraction (string or content-block array) * - Message flattening (text + image blocks) * - Tool definition conversion * - tool_choice mapping * - top_p pass-through * - thinking configuration */ export declare function parseClaudeRequest(body: ClaudeRequest): ParsedClaudeRequest; /** * Serialize a NeuroLink GenerateResult into a Claude Messages API response. */ export declare function serializeClaudeResponse(result: InternalResult, requestModel: string): ClaudeResponse; /** * Build a Claude-compatible error envelope. */ export declare function buildClaudeError(status: number, message: string, errorType?: string): ClaudeErrorResponse; /** * Format a single SSE frame (one `event:` + `data:` pair). */ export declare function formatSSE(eventType: string, data: unknown): string; /** * Stateful SSE serializer that emits a well-formed Claude SSE stream. * * Tracks both lifecycle state (`idle` -> `streaming` -> `done`) and the * current content block type (`text`, `thinking`, `tool_use`). Each * content block gets a unique, monotonically increasing `blockIndex`. * * Usage: * ```ts * const sse = new ClaudeStreamSerializer(requestModel, inputTokens); * * // Thinking deltas * for await (const thought of thinkingStream) { * yield* sse.pushThinkingDelta(thought); * } * * // Text deltas * for await (const chunk of textStream) { * yield* sse.pushDelta(chunk); * } * * // Tool use * yield* sse.pushToolUse(toolId, toolName, toolInput); * * // Finalize * yield* sse.finish(outputTokens, finishReason); * ``` */ export declare class ClaudeStreamSerializer { private state; private currentBlockType; private sawToolUseBlock; private blockIndex; private hasOpenedBlock; private outputTokens; private messageStarted; private readonly messageId; private readonly model; private readonly inputTokens; constructor(model: string, inputTokens?: number); /** Current lifecycle state (exposed for testing). */ getState(): StreamLifecycleState; /** Current content block type (exposed for testing). */ getCurrentBlockType(): ContentBlockType; /** Current block index (exposed for testing). */ getBlockIndex(): number; /** * Emit a ping event frame. The actual periodic timer is wired in * the route handler; this method just formats the SSE frame. */ static pingEvent(): string; /** * Emit `message_start` and initial ping if not already done. */ private ensureMessageStarted; /** * Close the current content block if one is open. */ private closeCurrentBlock; /** * Open a new content block of the given type. * Increments blockIndex for each new block. */ private openBlock; /** * Emit the opening frames: message_start and ping. * The first actual content decides which content block opens next. */ start(): Generator<string>; /** * Push a text delta. Returns zero or more SSE frames. * If currently in a thinking block, the thinking block is closed first. */ pushDelta(text: string): Generator<string>; /** * Push a thinking delta. Returns zero or more SSE frames. * If currently in a text or tool_use block, that block is closed first * and a new thinking block is opened. */ pushThinkingDelta(text: string): Generator<string>; /** * Push a complete tool use block. * * 1. Closes any open content block * 2. Emits `content_block_start` with `{type: "tool_use", id, name}` * 3. JSON-stringifies the input, chunks it into ~100 char segments * 4. Emits `content_block_delta` with `{type: "input_json_delta", partial_json}` per chunk * 5. Emits `content_block_stop` */ pushToolUse(id: string, name: string, input: unknown): Generator<string>; /** * Finalize the stream: content_block_stop, message_delta, message_stop. */ finish(outputTokens?: number, finishReason?: string): Generator<string>; /** * Emit an error event. Transitions to terminal ERROR state. */ emitError(status: number, message: string): Generator<string>; }