@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
315 lines (314 loc) • 10.7 kB
TypeScript
import type { DeferredUsage, NeuroLinkEvents, TypedEventEmitter } from "./common.js";
import type { JSONSchema7 } from "./middleware.js";
import type { LanguageModelV3, LanguageModelV3CallOptions } from "./middleware.js";
import type { StreamOptions } from "./stream.js";
import type { Tool } from "./tools.js";
export type OpenAICompatChatRole = "system" | "user" | "assistant" | "tool";
export type OpenAICompatTextContent = {
type: "text";
text: string;
};
export type OpenAICompatImageURLContent = {
type: "image_url";
image_url: {
url: string;
detail?: "auto" | "low" | "high";
};
};
export type OpenAICompatMessageContent = OpenAICompatTextContent | OpenAICompatImageURLContent;
export type OpenAICompatToolCallWire = {
id: string;
type: "function";
function: {
name: string;
arguments: string;
};
};
export type OpenAICompatChatMessage = {
role: "system";
content: string | OpenAICompatMessageContent[];
} | {
role: "user";
content: string | OpenAICompatMessageContent[];
} | {
role: "assistant";
content?: string | OpenAICompatMessageContent[] | null;
tool_calls?: OpenAICompatToolCallWire[];
/** The turn's reasoning, sent back only where the catalog opts in
* (DeepSeek's replayReasoningContent quirk). */
reasoning_content?: string;
} | {
role: "tool";
content: string;
tool_call_id: string;
};
export type OpenAICompatChatTool = {
type: "function";
function: {
name: string;
description?: string;
parameters: JSONSchema7;
strict?: boolean;
};
};
export type OpenAICompatToolChoiceWire = "auto" | "none" | "required" | {
type: "function";
function: {
name: string;
};
};
export type OpenAICompatResponseFormat = {
type: "text";
} | {
type: "json_object";
} | {
type: "json_schema";
json_schema: {
name: string;
schema: JSONSchema7;
description?: string;
strict?: boolean;
};
};
export type OpenAICompatChatRequest = {
model: string;
messages: OpenAICompatChatMessage[];
stream?: boolean;
stream_options?: {
include_usage?: boolean;
};
max_tokens?: number;
max_completion_tokens?: number;
temperature?: number;
top_p?: number;
presence_penalty?: number;
frequency_penalty?: number;
seed?: number;
stop?: string[];
tools?: OpenAICompatChatTool[];
tool_choice?: OpenAICompatToolChoiceWire;
response_format?: OpenAICompatResponseFormat;
parallel_tool_calls?: boolean;
user?: string;
};
export type OpenAICompatUsage = {
prompt_tokens?: number;
completion_tokens?: number;
total_tokens?: number;
prompt_tokens_details?: {
cached_tokens?: number;
};
completion_tokens_details?: {
reasoning_tokens?: number;
};
};
export type OpenAICompatChatChoiceMessage = {
role: "assistant";
content?: string | null;
tool_calls?: OpenAICompatToolCallWire[];
refusal?: string | null;
reasoning_content?: string | null;
reasoning?: string | null;
};
export type OpenAICompatChatChoice = {
index: number;
message: OpenAICompatChatChoiceMessage;
finish_reason: "stop" | "length" | "tool_calls" | "function_call" | "content_filter" | null;
};
export type OpenAICompatChatResponse = {
id?: string;
object?: string;
created?: number;
model?: string;
choices: OpenAICompatChatChoice[];
usage?: OpenAICompatUsage;
system_fingerprint?: string;
};
export type OpenAICompatStreamDelta = {
role?: OpenAICompatChatRole;
content?: string | null;
tool_calls?: Array<{
index: number;
id?: string;
type?: "function";
function?: {
name?: string;
arguments?: string;
};
}>;
refusal?: string | null;
reasoning_content?: string | null;
reasoning?: string | null;
};
export type OpenAICompatStreamChunkChoice = {
index: number;
delta: OpenAICompatStreamDelta;
finish_reason: "stop" | "length" | "tool_calls" | "function_call" | "content_filter" | null;
};
export type OpenAICompatChatStreamChunk = {
id?: string;
object?: string;
created?: number;
model?: string;
choices: OpenAICompatStreamChunkChoice[];
usage?: OpenAICompatUsage;
};
export type OpenAICompatErrorMessage = string | ReadonlyArray<{
msg?: string;
}>;
export type OpenAICompatErrorBody = {
error?: {
message?: OpenAICompatErrorMessage;
type?: string;
code?: string | number;
param?: string | null;
};
detail?: string;
};
export type OpenAICompatConfig = {
provider: string;
modelId: string;
baseURL: string;
apiKey?: string;
headers?: Record<string, string> | (() => Record<string, string>);
fetch?: typeof globalThis.fetch;
};
export type OpenAICompatToolWarning = NonNullable<Awaited<ReturnType<LanguageModelV3["doGenerate"]>>["warnings"]>[number];
export type OpenAICompatV3Content = Awaited<ReturnType<LanguageModelV3["doGenerate"]>>["content"][number];
export type OpenAICompatV3FinishReason = Awaited<ReturnType<LanguageModelV3["doGenerate"]>>["finishReason"];
export type OpenAICompatV3Usage = Awaited<ReturnType<LanguageModelV3["doGenerate"]>>["usage"];
export type OpenAICompatV3StreamPart = Awaited<ReturnType<LanguageModelV3["doStream"]>>["stream"] extends ReadableStream<infer P> ? P : never;
export type OpenAICompatV3CallTools = NonNullable<LanguageModelV3CallOptions["tools"]>;
export type OpenAICompatV3CallToolChoice = NonNullable<LanguageModelV3CallOptions["toolChoice"]>;
export type OpenAICompatUserOrAssistantPart = {
type: "text";
text: string;
} | {
type: "file";
mediaType: string;
data: Uint8Array | string | URL;
filename?: string;
};
export type OpenAICompatMessage = {
role: "system" | "user" | "assistant" | "tool";
content: unknown;
toolCallId?: string;
toolName?: string;
};
export type OpenAICompatSSEResult = {
text: string;
/** Accumulated reasoner-model output (`reasoning_content` / `reasoning` deltas). */
reasoning: string;
toolCalls: Map<number, {
id: string;
name: string;
argsBuffered: string;
}>;
finishReason: "stop" | "length" | "tool_calls" | "function_call" | "content_filter" | null;
usage?: OpenAICompatUsage;
/** Response id from the first stream chunk that carried one. */
id?: string;
/** Served model from the first stream chunk that carried one. */
model?: string;
};
export type OpenAICompatStreamChunk = {
content: string;
reasoning?: string;
};
export type ToolExecutionSummaryInternal = {
toolCallId: string;
toolName: string;
input: unknown;
output?: unknown;
error?: string;
startTime: Date;
endTime: Date;
};
export type StreamLoopArgs = {
maxSteps: number;
modelId: string;
url: string;
fetchImpl: typeof fetch;
abortSignal: AbortSignal | undefined;
options: StreamOptions;
conversation: OpenAICompatChatMessage[];
openAITools: OpenAICompatChatTool[] | undefined;
openAIToolChoice: OpenAICompatToolChoiceWire | undefined;
toolsRecord: Record<string, Tool>;
/** Wire → registered tool-name map when sanitization was needed (see buildWireToolNameMaps). */
toolNameFromWire?: Map<string, string>;
emitter: TypedEventEmitter<NeuroLinkEvents> | undefined;
toolsUsed: string[];
toolExecutionSummaries: ToolExecutionSummaryInternal[];
pushChunk: (chunk: OpenAICompatStreamChunk) => void;
/** Signals the channel that no further chunks will arrive (success or error path alike). */
closeChannel: () => void;
resolveUsage: (u: {
promptTokens: number;
completionTokens: number;
totalTokens: number;
}) => void;
resolveFinish: (reason: string) => void;
/**
* `response_format` for this turn's requests, computed once up front from
* `options.schema` (see `suppressResponseFormatWithTools`). Absent when no
* schema was requested, or when tools suppress it.
*/
responseFormat?: OpenAICompatResponseFormat;
/**
* Fired once per step that echoes a `model` field on the wire (SSE
* `chunk.model`, captured by `parseSSEStream` into `OpenAICompatSSEResult.model`).
* Lets the caller learn what the SERVER actually served, distinct from the
* pre-call resolved/requested `modelId` — a gateway or router can rewrite
* an alias to a concrete model id. Not called when a step's response omits
* `model` (some backends don't echo it), so the caller must keep its own
* fallback.
*/
onModelObserved?: (model: string) => void;
};
export type OpenAICompatBuildBodyArgs = {
modelId: string;
messages: OpenAICompatChatMessage[];
options: {
maxTokens?: number | null;
temperature?: number | null;
topP?: number | null;
presencePenalty?: number | null;
frequencyPenalty?: number | null;
seed?: number | null;
stopSequences?: string[];
/**
* Provider-specific extra wire fields, spread verbatim onto the final
* request body by `buildBody` (after the standard fields). This is the
* explicit channel for non-OpenAI knobs (e.g. NVIDIA NIM's `top_k` /
* `chat_template_kwargs`) — loose unknown keys returned from
* `adjustBuildBodyOptions` are intentionally NOT forwarded.
*/
extraBody?: Record<string, unknown>;
};
tools?: OpenAICompatChatTool[];
toolChoice?: OpenAICompatToolChoiceWire;
streaming: boolean;
responseFormat?: OpenAICompatResponseFormat;
};
/**
* Per-stream lifecycle listeners returned from an OpenAIChatCompletionsProvider
* subclass's `onStreamStart` hook. Every property is optional — provide only
* what the subclass cares about. Used by LiteLLM to wire an OTel span around
* the deferred analytics promises.
*/
export type OpenAICompatStreamLifecycleListeners = {
/**
* Fired once the deferred usage promise resolves with the final aggregated
* token counts. promptTokens is the UNCACHED remainder; cacheReadTokens
* carries the cached portion (non-overlapping convention), and
* reasoningTokens is a subset of completionTokens.
*/
onUsage?: (usage: DeferredUsage) => void;
/**
* Fired once the deferred finish promise resolves. `reason` is "stop",
* "length", "tool-calls", "content-filter", or "error". When the loop
* errored, the upstream cause is passed as `capturedError`.
*/
onFinish?: (reason: string, capturedError?: unknown) => void;
};