UNPKG

@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

126 lines (125 loc) • 7.14 kB
/** * Wire-format translation: Anthropic `ClaudeResponse` shape -> the Codex * Responses shape a native Codex client expects. * * Pure wire-format only — no account selection, retry policy, or transport. * Mirrors `claudeFormat.ts`'s role for the opposite direction: that module * serializes NeuroLink's internal result into Claude SSE, this one serializes * an already-Claude-shaped result into Codex SSE (or one JSON envelope). */ import type { ClaudeContentBlock, ClaudeResponse, ClaudeUsage, CodexNativeToolKind, CodexResponseEnvelope, CodexResponseItem, CodexResponseUsage } from "../types/index.js"; /** Same idiom as `generateToolUseId` (`claudeFormat.ts`), Codex's own prefix. */ export declare function generateCodexResponseId(): string; /** Item ids are prefixed by kind so a client can tell message/tool items apart at a glance. */ export declare function generateCodexItemId(kind: "message" | "function_call" | "custom_tool_call"): string; /** * Reuse the Anthropic `tool_use.id` (`toolu_...`) verbatim as the Codex `call_id`. * No id-mapping table exists anywhere in this codebase's translation modules, and * nothing on the way in validates `call_id` format — see the design doc's §5 for * the full reasoning and its one unresolved edge (a real, non-fallback Codex * backend rejecting a non-`call_`-prefixed id on a later turn). */ export declare function codexCallIdFromToolUseId(toolUseId: string): string; /** * Absent cache fields are omitted rather than zeroed (never conflate "not * observed" with "observed as zero" — the field's own doc comment on * `CodexResponseUsage` states this contract). */ export declare function synthesizeCodexUsage(usage: ClaudeUsage): CodexResponseUsage; /** * Shared by the streaming serializer's non-failure item close and the * non-streaming path (`serializeCodexResponse`), so item shape is defined * once. Always produces a "completed" item — the streaming failure path * (an item closed "incomplete" mid-turn) builds its item directly, since it * must preserve the raw accumulated text/argument bytes rather than a value * reconstructed through this function. */ export declare function buildCodexResponseItem(block: ClaudeContentBlock, itemId: string, toolKindByName?: ReadonlyMap<string, CodexNativeToolKind>): CodexResponseItem | null; /** Non-streaming path: `§7` of the design — the document root IS a `CodexResponseEnvelope`. */ export declare function serializeCodexResponse(result: ClaudeResponse, requestModel: string, toolKindByName?: ReadonlyMap<string, CodexNativeToolKind>): CodexResponseEnvelope; /** * Push-based streaming serializer. A genuinely incremental tool-call-argument * path (`openToolCall`/`pushToolCallArgsDelta`/`closeToolCall`) forwards each * raw `input_json_delta` chunk as it arrives rather than buffering the whole * call before emitting anything — `partial_json` is not individually valid * JSON, so a serializer that validated per-chunk could not do this. */ export declare class CodexResponsesStreamSerializer { private readonly model; private readonly toolKindByName; private state; private readonly responseId; private outputIndex; private openKind; private openItemId; private textAccum; private argsAccum; private toolCallId; private toolName; private readonly closedItems; private terminalEnvelope; constructor(model: string, toolKindByName?: ReadonlyMap<string, CodexNativeToolKind>); start(): Generator<string>; pushDelta(text: string): Generator<string>; /** Opens the tool-call item header at content_block_start, before any argument text * is known — mirrors what content_block_start already gives us (id, name). A tool * the request declared `custom` opens as a `custom_tool_call` item. */ openToolCall(toolUseId: string, name: string): Generator<string>; /** Forwards one raw partial_json fragment as-is — no JSON.parse here, because a lone * fragment is not required to be valid JSON on its own. A custom call's fragments * are the `{"input":"..."}` wrapper, not client text, so they are only buffered; * `closeToolCall` emits the unwrapped input once the whole wrapper is known. */ pushToolCallArgsDelta(rawChunk: string): Generator<string>; /** * Public close for a tool-use block at `content_block_stop`. A no-op when no * tool-call item is open, so a driver can call it unconditionally. * Validates the accumulated arguments once, here — the one place validity * is required. Throws on malformed JSON; the caller must catch and route to * `emitFailure` (never swallowed, never retried after this point). */ closeToolCall(): Generator<string>; /** * Public close for a text block at `content_block_stop`, mirroring * `closeToolCall`'s role for the message item. A no-op when no message item * is open, so a driver can call it unconditionally alongside `closeToolCall` * without first inspecting which kind is currently open. */ closeTextBlock(): Generator<string>; finish(stopReason: string | null, usage: ClaudeUsage): Generator<string, CodexResponseEnvelope>; /** * Post-commit terminal path. Closes any open item as "incomplete" — now * representable via `CodexResponseItemStatus` — then emits a single * `response.failed`. Idempotent: a second call after this one already ran * returns the same envelope without emitting further frames, so a driver * that reaches it defensively from more than one place never double-emits. */ emitFailure(_status: number, message: string, code?: string): Generator<string, CodexResponseEnvelope>; private assertNotTerminal; /** * The custom-kind close: nothing was streamed live, so one input delta * carries the whole unwrapped input, then its done event. Lenient where the * function path throws: the wrapper is Claude's own output for the * single-field schema `mapCodexCustomToolToClaude` declared, so a parse * failure is an internal bug, and the raw accumulated text is emitted rather * than failing the turn over it. */ private closeCustomToolCall; private openMessage; /** Closes whichever item is currently open, as "incomplete" when `failed`. */ private closeOpenItem; /** * The failure-close counterpart to `closeToolCall`. Arguments are carried * verbatim from `argsAccum` and never re-validated — `JSON.parse` is not * called on the failure path, and no `function_call_arguments.done` is * emitted, since the arguments never reached a validated, complete state. */ private closeFailedFunctionCall; /** * The failure close for a custom call. Its accumulated bytes are Anthropic's * JSON wrapper, not the client's grammar text, so `input` is the unwrapped * string when the wrapper already parses and "" otherwise — an incomplete * item is never executed. No input done event, as on the function path. */ private closeFailedCustomToolCall; private closeMessageItem; }