@caeliq/llms 1.0.64 → 1.0.66
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -1
- package/dist/cjs/server.cjs +261 -211
- package/dist/cjs/server.cjs.map +4 -4
- package/dist/esm/server.mjs +261 -211
- package/dist/esm/server.mjs.map +4 -4
- package/dist/routing/inbound-pipeline.d.ts +6 -2
- package/dist/routing/protocol-adapter.d.ts +2 -0
- package/dist/server.d.ts +4 -0
- package/dist/tests/codex-system-instructions.d.ts +1 -0
- package/dist/tests/latency-cadence.d.ts +1 -0
- package/dist/tests/message-debug.d.ts +1 -0
- package/dist/tests/openrouter-headers.d.ts +1 -0
- package/dist/tests/proxy-dispatcher-cache.d.ts +1 -0
- package/dist/tests/reasoning.auto-summary.d.ts +1 -0
- package/dist/tests/sse-event-native.d.ts +1 -0
- package/dist/tests/transformer-plan.d.ts +1 -0
- package/dist/transformer/antigravity-auth.transformer.d.ts +2 -0
- package/dist/transformer/codex.transformer.d.ts +4 -14
- package/dist/transformer/cursor-sdk.transformer.d.ts +2 -0
- package/dist/transformer/openai.transformer.d.ts +2 -0
- package/dist/transformer/opencode-headers.transformer.d.ts +4 -0
- package/dist/transformer/openrouter.transformer.d.ts +15 -1
- package/dist/transformer/reasoning.transformer.d.ts +1 -0
- package/dist/types/llm.d.ts +16 -0
- package/dist/types/transformer.d.ts +10 -0
- package/dist/utils/message-debug.d.ts +35 -0
- package/dist/utils/openai.responses.util.d.ts +10 -0
- package/dist/utils/paced-sse.d.ts +38 -0
- package/dist/utils/reasoning-effort.d.ts +22 -0
- package/dist/utils/request-latency.d.ts +33 -0
- package/dist/utils/request.d.ts +8 -1
- package/dist/utils/sse/incremental-parser.d.ts +35 -0
- package/dist/utils/sse-debug-tap.d.ts +32 -0
- package/dist/utils/stream.d.ts +26 -3
- package/dist/utils/token-count-worker.d.ts +12 -0
- package/dist/utils/transformer-plan.d.ts +21 -0
- package/package.json +9 -9
|
@@ -11,8 +11,12 @@ export interface PreparedInboundRequest {
|
|
|
11
11
|
clientWireBody: any;
|
|
12
12
|
/** Normalized Unified body used for routing and provider conversion. */
|
|
13
13
|
unifiedBody: UnifiedChatRequest;
|
|
14
|
-
/**
|
|
15
|
-
|
|
14
|
+
/**
|
|
15
|
+
* Unified projection before destination-specific Anthropic emulation.
|
|
16
|
+
* Only cloned when global fallback is configured; otherwise undefined so
|
|
17
|
+
* fallback can fall back to `unifiedBody`.
|
|
18
|
+
*/
|
|
19
|
+
prePolicyUnifiedBody?: UnifiedChatRequest;
|
|
16
20
|
providerName: string;
|
|
17
21
|
modelName: string;
|
|
18
22
|
}
|
|
@@ -21,6 +21,8 @@ export declare function normalizeClientToUnified(protocol: ClientProtocolContext
|
|
|
21
21
|
/**
|
|
22
22
|
* Provider transformers are allowed to mutate their input. Every primary and
|
|
23
23
|
* fallback attempt therefore needs an independent copy of the normalized body.
|
|
24
|
+
* Prefers structuredClone when available; falls back to JSON round-trip for
|
|
25
|
+
* environments without it.
|
|
24
26
|
*/
|
|
25
27
|
export declare function cloneProtocolBody<T>(value: T): T;
|
|
26
28
|
/**
|
package/dist/server.d.ts
CHANGED
|
@@ -45,6 +45,8 @@ declare class Server {
|
|
|
45
45
|
}
|
|
46
46
|
export default Server;
|
|
47
47
|
export { sessionUsageCache };
|
|
48
|
+
export { closeProxyDispatchers } from "./utils/request";
|
|
49
|
+
export { closeTokenCountWorkers } from "./utils/token-count-worker";
|
|
48
50
|
export { router };
|
|
49
51
|
export { calculateTokenCount };
|
|
50
52
|
export { searchProjectBySession };
|
|
@@ -57,6 +59,8 @@ export { pluginManager, tokenSpeedPlugin, getTokenSpeedStats, getGlobalTokenSpee
|
|
|
57
59
|
export { SSEParserTransform, SSESerializerTransform, rewriteStream } from "./utils/sse";
|
|
58
60
|
export { isClientAbortError } from "./utils/retry";
|
|
59
61
|
export { sanitizeHeadersForLog, diffHeadersForLog, sanitizeBodyForLog, DEFAULT_LOG_BODY_MAX_BYTES, } from "./utils/redact";
|
|
62
|
+
export { logMessageBody, bodyToLogString, shouldLogRequestBodies, shouldLogSSEEvents, resolveLogBodyMaxBytes, isTruthyConfigFlag, type MessageDebugDirection, } from "./utils/message-debug";
|
|
63
|
+
export { tapUpstreamSSEDebug, tapClientSSEDebug, } from "./utils/sse-debug-tap";
|
|
60
64
|
export { exchangeAuthorizationCode, fetchUserEmail, resolveProjectId, saveTokens, loadTokens, getValidAccessToken, getValidAccessToken as getAntigravityAccessToken, ANTIGRAVITY_CLIENT_ID, ANTIGRAVITY_CLIENT_SECRET, ANTIGRAVITY_REDIRECT_URI, ANTIGRAVITY_SCOPES, type AntigravityTokens, } from "./utils/antigravity-auth";
|
|
61
65
|
export { getValidAccessToken as getClaudeAccessToken } from "./utils/claude-auth";
|
|
62
66
|
export { getValidAccessToken as getCodexAccessToken, } from "./utils/codex-auth";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { Transformer } from "../types/transformer";
|
|
2
2
|
export declare class AntigravityAuthTransformer implements Transformer {
|
|
3
3
|
name: string;
|
|
4
|
+
ownsTransport: boolean;
|
|
5
|
+
requestPhase: "transport";
|
|
4
6
|
logger?: any;
|
|
5
7
|
private buildAuthAndEnvelope;
|
|
6
8
|
private buildHeaders;
|
|
@@ -38,20 +38,10 @@ export declare class CodexTransformer implements Transformer {
|
|
|
38
38
|
*/
|
|
39
39
|
private jsonToSseStream;
|
|
40
40
|
/**
|
|
41
|
-
* Peek
|
|
42
|
-
*
|
|
43
|
-
*
|
|
44
|
-
*
|
|
45
|
-
*
|
|
46
|
-
* - **For flat JSON** (`{` / `[`): reads the full clone body and returns
|
|
47
|
-
* `{ firstChar, text }` so the caller can parse and handle it.
|
|
48
|
-
* - **For SSE** (anything else): returns `null` immediately after reading
|
|
49
|
-
* only the first chunk from the clone. The original `response.body` on
|
|
50
|
-
* the other side of the tee is untouched and can still be streamed live
|
|
51
|
-
* by the SSE reader — avoiding buffering the entire response.
|
|
52
|
-
*
|
|
53
|
-
* Callers must pass `response.clone().body!` so the original body is not
|
|
54
|
-
* consumed by the peek.
|
|
41
|
+
* Peek the first chunk of the response body to distinguish flat JSON from
|
|
42
|
+
* SSE without Response.clone(). JSON drains the body into text; SSE returns
|
|
43
|
+
* a new Response whose stream replays the peeked chunk then continues from
|
|
44
|
+
* the same reader.
|
|
55
45
|
*/
|
|
56
46
|
private readBodyAndPeek;
|
|
57
47
|
private collectSseIntoChatCompletion;
|
|
@@ -17,6 +17,8 @@ export declare function buildCursorSdkRunnerOptions(options: CursorSdkTransforme
|
|
|
17
17
|
export declare class CursorSdkTransformer implements Transformer {
|
|
18
18
|
static TransformerName: string;
|
|
19
19
|
name: string;
|
|
20
|
+
ownsTransport: boolean;
|
|
21
|
+
requestPhase: "transport";
|
|
20
22
|
logger?: any;
|
|
21
23
|
private options;
|
|
22
24
|
constructor(options?: CursorSdkTransformerOptions);
|
|
@@ -35,6 +35,8 @@ export declare class OpenAITransformer implements Transformer {
|
|
|
35
35
|
transformRequestOut(request: any, _context?: TransformerContext): Promise<UnifiedChatRequest>;
|
|
36
36
|
/**
|
|
37
37
|
* Provider-side: apply OpenAI-native cache policy to a Unified Chat body.
|
|
38
|
+
* Avoid cloning the entire Unified body (~800KB at longContext) when no
|
|
39
|
+
* mutation will occur – native opencode mutates in place.
|
|
38
40
|
*/
|
|
39
41
|
transformRequestIn(request: UnifiedChatRequest, provider: any, context: any): Promise<UnifiedChatRequest>;
|
|
40
42
|
/**
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { Transformer } from "../types/transformer";
|
|
2
2
|
export declare class OpencodeHeadersTransformer implements Transformer {
|
|
3
3
|
name: string;
|
|
4
|
+
ownsTransport: boolean;
|
|
5
|
+
requestPhase: "transport";
|
|
4
6
|
private sessionCache;
|
|
5
7
|
private readonly MAX_SESSIONS;
|
|
6
8
|
private lastTimestamp;
|
|
@@ -18,6 +20,7 @@ export declare class OpencodeHeadersTransformer implements Transformer {
|
|
|
18
20
|
private preserveZenStreamErrors;
|
|
19
21
|
private static zenStreamFailure;
|
|
20
22
|
private buildHeaders;
|
|
23
|
+
private resolveParentSessionId;
|
|
21
24
|
/**
|
|
22
25
|
* True only for the two Zen session-hash routing failures — a re-roll can
|
|
23
26
|
* recover these. Kept deliberately narrow (exact status + message) so genuine
|
|
@@ -29,6 +32,7 @@ export declare class OpencodeHeadersTransformer implements Transformer {
|
|
|
29
32
|
private retryDelayMs;
|
|
30
33
|
private exponentialRetryDelayMs;
|
|
31
34
|
private retryAfterHeaders;
|
|
35
|
+
private ensurePromptCacheKey;
|
|
32
36
|
private fingerprintConversation;
|
|
33
37
|
private getOrCreateSessionId;
|
|
34
38
|
private invalidateSession;
|
|
@@ -1,10 +1,24 @@
|
|
|
1
1
|
import { UnifiedChatRequest } from "../types/llm";
|
|
2
2
|
import { Transformer, TransformerOptions } from "../types/transformer";
|
|
3
|
+
import { HeaderRecord } from "../utils/headers";
|
|
4
|
+
/**
|
|
5
|
+
* OpenRouter app attribution headers. Some routed upstreams also require a
|
|
6
|
+
* Claude Code–shaped User-Agent; attribution alone is not enough for those.
|
|
7
|
+
* @see https://openrouter.ai/docs/app-attribution
|
|
8
|
+
*/
|
|
9
|
+
export declare function buildOpenRouterAttributionHeaders(options?: TransformerOptions): HeaderRecord;
|
|
10
|
+
/**
|
|
11
|
+
* Claude Code CLI identity headers. Prefer the caller's genuine CLI headers;
|
|
12
|
+
* otherwise synthesize the same profile claude-auth uses for non-CLI clients.
|
|
13
|
+
* Several OpenRouter upstreams reject requests without a claude-cli User-Agent.
|
|
14
|
+
*/
|
|
15
|
+
export declare function buildOpenRouterClaudeIdentityHeaders(clientHeaders?: Record<string, unknown>, options?: TransformerOptions): HeaderRecord;
|
|
16
|
+
export declare function buildOpenRouterOutboundHeaders(clientHeaders?: Record<string, unknown>, options?: TransformerOptions): HeaderRecord;
|
|
3
17
|
export declare class OpenrouterTransformer implements Transformer {
|
|
4
18
|
private readonly options?;
|
|
5
19
|
static TransformerName: string;
|
|
6
20
|
logger?: any;
|
|
7
21
|
constructor(options?: TransformerOptions | undefined);
|
|
8
|
-
transformRequestIn(request: UnifiedChatRequest, provider?: any, context?: any): Promise<
|
|
22
|
+
transformRequestIn(request: UnifiedChatRequest, provider?: any, context?: any): Promise<Record<string, any>>;
|
|
9
23
|
transformResponseOut(response: Response): Promise<Response>;
|
|
10
24
|
}
|
|
@@ -3,6 +3,7 @@ import { Transformer, TransformerOptions } from "../types/transformer";
|
|
|
3
3
|
export declare class ReasoningTransformer implements Transformer {
|
|
4
4
|
private readonly options?;
|
|
5
5
|
static TransformerName: string;
|
|
6
|
+
name: string;
|
|
6
7
|
enable: any;
|
|
7
8
|
constructor(options?: TransformerOptions | undefined);
|
|
8
9
|
transformRequestIn(request: UnifiedChatRequest, provider?: any, context?: any): Promise<UnifiedChatRequest>;
|
package/dist/types/llm.d.ts
CHANGED
|
@@ -115,6 +115,11 @@ export interface UnifiedChatRequest {
|
|
|
115
115
|
};
|
|
116
116
|
reasoning?: {
|
|
117
117
|
effort?: ThinkLevel;
|
|
118
|
+
/**
|
|
119
|
+
* Request readable reasoning text from destinations that gate it
|
|
120
|
+
* (Responses `reasoning.summary`, Codex, etc.). `"none"` opts out.
|
|
121
|
+
*/
|
|
122
|
+
summary?: "auto" | "detailed" | "concise" | "none";
|
|
118
123
|
max_tokens?: number;
|
|
119
124
|
enabled?: boolean;
|
|
120
125
|
};
|
|
@@ -133,6 +138,17 @@ export interface UnifiedChatRequest {
|
|
|
133
138
|
anthropic_metadata?: Record<string, any>;
|
|
134
139
|
anthropic_stop_sequences?: string[];
|
|
135
140
|
reasoning_effort?: string;
|
|
141
|
+
/**
|
|
142
|
+
* Responses opaque `include` list (e.g. `reasoning.encrypted_content`).
|
|
143
|
+
* Client-driven: only set when the inbound protocol was Responses and the
|
|
144
|
+
* client sent it. Chat/Anthropic clients have no equivalent field.
|
|
145
|
+
*/
|
|
146
|
+
include?: string[];
|
|
147
|
+
/**
|
|
148
|
+
* Responses `store`. Only `false` is preserved (CCR rejects `store: true`).
|
|
149
|
+
* Client-driven same-protocol hint, paired with `include` by OpenCode/AI SDK.
|
|
150
|
+
*/
|
|
151
|
+
store?: false;
|
|
136
152
|
}
|
|
137
153
|
export interface UnifiedChatResponse {
|
|
138
154
|
id: string;
|
|
@@ -25,6 +25,8 @@ export interface TransformerContext {
|
|
|
25
25
|
claudeAuthPostBuildHook?: (anthropicBody: Record<string, any>) => void;
|
|
26
26
|
[key: string]: any;
|
|
27
27
|
}
|
|
28
|
+
/** Where a request transformer runs in the compiled provider/model plan. */
|
|
29
|
+
export type TransformerRequestPhase = "body" | "headers" | "transport";
|
|
28
30
|
export type Transformer = {
|
|
29
31
|
transformRequestIn?: (request: UnifiedChatRequest, provider: LLMProvider, context: TransformerContext) => Promise<Record<string, any>>;
|
|
30
32
|
transformResponseIn?: (response: Response, context?: TransformerContext) => Promise<Response>;
|
|
@@ -32,6 +34,14 @@ export type Transformer = {
|
|
|
32
34
|
transformResponseOut?: (response: Response, context: TransformerContext) => Promise<Response>;
|
|
33
35
|
endPoint?: string;
|
|
34
36
|
name?: string;
|
|
37
|
+
/**
|
|
38
|
+
* When true, this transformer performs the upstream call (fetch, SDK, etc.)
|
|
39
|
+
* and returns the Response via config.__providerResponse. The request plan
|
|
40
|
+
* runs at most one such transformer, after every body/header transform.
|
|
41
|
+
*/
|
|
42
|
+
ownsTransport?: boolean;
|
|
43
|
+
/** Optional phase hint; ownsTransport implies "transport". */
|
|
44
|
+
requestPhase?: TransformerRequestPhase;
|
|
35
45
|
auth?: (request: any, provider: LLMProvider, context: TransformerContext) => Promise<any>;
|
|
36
46
|
logger?: any;
|
|
37
47
|
};
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/** Wire direction for request/response body and SSE message debug logs. */
|
|
2
|
+
export type MessageDebugDirection = "client→ccr" | "ccr→provider" | "provider→ccr" | "ccr→client";
|
|
3
|
+
export declare function isTruthyConfigFlag(value: unknown): boolean;
|
|
4
|
+
export declare function resolveLogBodyMaxBytes(configService: {
|
|
5
|
+
get?: (key: string) => unknown;
|
|
6
|
+
} | null | undefined): number;
|
|
7
|
+
export declare function shouldLogRequestBodies(configService: {
|
|
8
|
+
get?: (key: string) => unknown;
|
|
9
|
+
} | null | undefined): boolean;
|
|
10
|
+
export declare function shouldLogSSEEvents(configService: {
|
|
11
|
+
get?: (key: string) => unknown;
|
|
12
|
+
} | null | undefined): boolean;
|
|
13
|
+
/** Serialize a request/response body for sanitizeBodyForLog. */
|
|
14
|
+
export declare function bodyToLogString(body: unknown): string;
|
|
15
|
+
export type MessageBodyLogOptions = {
|
|
16
|
+
logger: {
|
|
17
|
+
debug?: (...args: any[]) => void;
|
|
18
|
+
info?: (...args: any[]) => void;
|
|
19
|
+
};
|
|
20
|
+
direction: MessageDebugDirection;
|
|
21
|
+
/** Prefer debug; info kept for the legacy Anthropic-only inbound path. */
|
|
22
|
+
level?: "debug" | "info";
|
|
23
|
+
reqId?: string | number;
|
|
24
|
+
protocol?: string;
|
|
25
|
+
provider?: string;
|
|
26
|
+
model?: string;
|
|
27
|
+
maxBytes?: number;
|
|
28
|
+
/** Override the historical `type` field when needed. */
|
|
29
|
+
type?: string;
|
|
30
|
+
};
|
|
31
|
+
/**
|
|
32
|
+
* Opt-in full message-body capture with a stable direction tag so operators
|
|
33
|
+
* can grep client↔CCR and CCR↔provider legs independently.
|
|
34
|
+
*/
|
|
35
|
+
export declare function logMessageBody(body: unknown, opts: MessageBodyLogOptions): void;
|
|
@@ -12,6 +12,8 @@ export declare function mapCallId(map: ResponsesCallIdMap, id: unknown, directio
|
|
|
12
12
|
* Supports the Responses MVP subset; rejects CCR-unsupported stateful fields.
|
|
13
13
|
*/
|
|
14
14
|
export declare function responsesRequestToUnified(body: any, callIdMap?: ResponsesCallIdMap, customToolNames?: Set<string>): UnifiedChatRequest;
|
|
15
|
+
/** Responses `include` is a string list; drop non-strings rather than invent values. */
|
|
16
|
+
export declare function normalizeResponsesInclude(include: unknown): string[] | undefined;
|
|
15
17
|
export declare function isResponsesReasoningItemId(value: unknown): value is string;
|
|
16
18
|
/**
|
|
17
19
|
* Ciphertext Codex/OpenAI will verify. Item ids and Anthropic/Gemini
|
|
@@ -82,6 +84,11 @@ export declare function responsesReasoningItemFromThinking(thinking: {
|
|
|
82
84
|
encrypted_content?: string;
|
|
83
85
|
id?: string;
|
|
84
86
|
} | undefined, id?: string): any | null;
|
|
87
|
+
/**
|
|
88
|
+
* Zen rejects Requests whose `input` repeats the same reasoning item id.
|
|
89
|
+
* Rewrite placeholders / collisions using ciphertext (or summary) as seed.
|
|
90
|
+
*/
|
|
91
|
+
export declare function uniquifyReasoningItemIds(items: any[] | undefined): void;
|
|
85
92
|
/** Synthetic argument key used to carry a `custom` tool's freeform text
|
|
86
93
|
* through the Unified/Chat Completions function-call shape. */
|
|
87
94
|
export declare const CUSTOM_TOOL_INPUT_KEY = "input";
|
|
@@ -192,6 +199,9 @@ export interface ResponsesStreamState {
|
|
|
192
199
|
thinkingContent: string;
|
|
193
200
|
thinkingEncryptedContent?: string;
|
|
194
201
|
thinkingId?: string;
|
|
202
|
+
thinkingStarted: boolean;
|
|
203
|
+
thinkingClosed: boolean;
|
|
204
|
+
thinkingOutputIndex?: number;
|
|
195
205
|
codexIsolateConventions: boolean;
|
|
196
206
|
}
|
|
197
207
|
export declare function createResponsesStreamState(options?: {
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Hermetic paced SSE upstream for latency / cadence benchmarks.
|
|
3
|
+
* Emits fixed-cadence Chat Completions SSE events with configurable delays.
|
|
4
|
+
*/
|
|
5
|
+
export type PacedSSEOptions = {
|
|
6
|
+
/** Delay before response headers resolve (ms). */
|
|
7
|
+
headerDelayMs?: number;
|
|
8
|
+
/** Delay before first SSE body byte after headers (ms). */
|
|
9
|
+
firstByteDelayMs?: number;
|
|
10
|
+
/** Gap between successive events (ms). */
|
|
11
|
+
eventIntervalMs?: number;
|
|
12
|
+
/** Number of content delta events. */
|
|
13
|
+
eventCount?: number;
|
|
14
|
+
/** Split each event across this many TCP-ish chunks (default 1). */
|
|
15
|
+
fragmentChunks?: number;
|
|
16
|
+
/** Abort tracking. */
|
|
17
|
+
signal?: AbortSignal;
|
|
18
|
+
/** Optional terminal Zen-style network_error finish_reason. */
|
|
19
|
+
terminalNetworkError?: boolean;
|
|
20
|
+
/** Fail with this HTTP status instead of streaming. */
|
|
21
|
+
httpErrorStatus?: number;
|
|
22
|
+
httpErrorBody?: string;
|
|
23
|
+
};
|
|
24
|
+
export type PacedSSEEventStamp = {
|
|
25
|
+
index: number;
|
|
26
|
+
enqueuedAt: number;
|
|
27
|
+
};
|
|
28
|
+
/**
|
|
29
|
+
* Build a Response whose body emits Chat Completions SSE at a fixed cadence.
|
|
30
|
+
* `stamps` is filled as each logical event is enqueued (before fragmentation).
|
|
31
|
+
*/
|
|
32
|
+
export declare function createPacedSSEResponse(options?: PacedSSEOptions, stamps?: PacedSSEEventStamp[]): Promise<Response>;
|
|
33
|
+
/** Read a stream and record when each complete SSE event (blank-line delimited) arrives. */
|
|
34
|
+
export declare function collectSSEEventTimings(body: ReadableStream<Uint8Array>, t0?: number): Promise<{
|
|
35
|
+
events: string[];
|
|
36
|
+
arrivalsMs: number[];
|
|
37
|
+
}>;
|
|
38
|
+
export declare function interArrivalGaps(arrivalsMs: number[]): number[];
|
|
@@ -1,7 +1,29 @@
|
|
|
1
1
|
import type { ThinkLevel, UnifiedChatRequest } from "../types/llm";
|
|
2
2
|
type UnifiedReasoning = UnifiedChatRequest["reasoning"];
|
|
3
|
+
/** Readable-reasoning request levels shared across Responses / Codex / config. */
|
|
4
|
+
export type ReasoningSummaryLevel = "auto" | "detailed" | "concise";
|
|
3
5
|
/** Normalize effort tokens at the protocol boundary without rejecting extensions. */
|
|
4
6
|
export declare function normalizeReasoningEffort(value: unknown): ThinkLevel | undefined;
|
|
7
|
+
/**
|
|
8
|
+
* Parse `REASONING_AUTO_SUMMARY` / provider `reasoningSummary`.
|
|
9
|
+
* `true` → `"detailed"` (LiteLLM-compatible). `"none"` / false / unset → off.
|
|
10
|
+
*/
|
|
11
|
+
export declare function resolveReasoningAutoSummary(value: unknown): ReasoningSummaryLevel | undefined;
|
|
12
|
+
/** True when reasoning is on (effort present and not none, or enabled:true). */
|
|
13
|
+
export declare function isReasoningActive(reasoning: UnifiedReasoning | undefined, thinking?: UnifiedChatRequest["thinking"]): boolean;
|
|
14
|
+
/**
|
|
15
|
+
* Opt-in: when config asks for auto-summary and the client enabled reasoning
|
|
16
|
+
* without an explicit `reasoning.summary`, stamp the Unified field so every
|
|
17
|
+
* destination protocol can request readable thinking the same way.
|
|
18
|
+
*/
|
|
19
|
+
export declare function applyReasoningAutoSummary(request: UnifiedChatRequest, configValue: unknown): UnifiedChatRequest;
|
|
20
|
+
/**
|
|
21
|
+
* Outbound precedence: Unified `reasoning.summary` → provider.reasoningSummary.
|
|
22
|
+
* `"none"` means do not request a readable summary.
|
|
23
|
+
*/
|
|
24
|
+
export declare function resolveOutboundReasoningSummary(request: Pick<UnifiedChatRequest, "reasoning" | "thinking">, provider?: {
|
|
25
|
+
reasoningSummary?: unknown;
|
|
26
|
+
} | null): ReasoningSummaryLevel | undefined;
|
|
5
27
|
/** `none` and an explicit enabled:false are the canonical off signals. */
|
|
6
28
|
export declare function isReasoningDisabled(reasoning: UnifiedReasoning | undefined, thinking?: UnifiedChatRequest["thinking"]): boolean;
|
|
7
29
|
/** Build the canonical reasoning state used by every inbound protocol. */
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Request-stage latency timings. Allocation-light monotonic stamps; one
|
|
3
|
+
* terminal structured record per request. No per-event logging, no tee.
|
|
4
|
+
*/
|
|
5
|
+
export type LatencyStage = "received" | "bodyParsed" | "normalized" | "projectLookup" | "tokenizeStart" | "tokenizeEnd" | "routeSelected" | "destinationPolicy" | "requestTransformers" | "upstreamFetchStart" | "upstreamHeaders" | "upstreamFirstByte" | "responseTransformers" | "downstreamFirstByte" | "complete";
|
|
6
|
+
export type RequestLatency = {
|
|
7
|
+
t0: number;
|
|
8
|
+
stages: Partial<Record<LatencyStage, number>>;
|
|
9
|
+
meta: {
|
|
10
|
+
protocol?: string;
|
|
11
|
+
provider?: string;
|
|
12
|
+
model?: string;
|
|
13
|
+
scenario?: string;
|
|
14
|
+
bypass?: boolean;
|
|
15
|
+
tokenCount?: number;
|
|
16
|
+
inputBytes?: number;
|
|
17
|
+
upstreamAttempts?: number;
|
|
18
|
+
cancelled?: boolean;
|
|
19
|
+
error?: string;
|
|
20
|
+
};
|
|
21
|
+
emitted?: boolean;
|
|
22
|
+
};
|
|
23
|
+
export declare function createRequestLatency(): RequestLatency;
|
|
24
|
+
export declare function markLatency(latency: RequestLatency | undefined | null, stage: LatencyStage): void;
|
|
25
|
+
export declare function tapResponseFirstByte(response: Response, onFirstByte: () => void): Response;
|
|
26
|
+
export declare function attachLatencyMeta(latency: RequestLatency | undefined | null, meta: Partial<RequestLatency["meta"]>): void;
|
|
27
|
+
/** Emit one structured terminal latency record. Safe to call multiple times. */
|
|
28
|
+
export declare function emitLatencyRecord(logger: {
|
|
29
|
+
info?: (obj: unknown, msg?: string) => void;
|
|
30
|
+
} | undefined | null, latency: RequestLatency | undefined | null): void;
|
|
31
|
+
export declare function ensureRequestLatency(req: {
|
|
32
|
+
_latency?: RequestLatency;
|
|
33
|
+
}): RequestLatency;
|
package/dist/utils/request.d.ts
CHANGED
|
@@ -1,4 +1,11 @@
|
|
|
1
|
+
import { ProxyAgent } from "undici";
|
|
1
2
|
import { UnifiedChatRequest } from "../types/llm";
|
|
3
|
+
/** One Undici ProxyAgent per normalized proxy URL so connections can be reused. */
|
|
4
|
+
export declare function getProxyDispatcher(httpsProxy: string): ProxyAgent;
|
|
5
|
+
/** Close every cached ProxyAgent (call on server shutdown). */
|
|
6
|
+
export declare function closeProxyDispatchers(): void;
|
|
7
|
+
/** Test-only: inspect the module-level dispatcher cache. */
|
|
8
|
+
export declare function __getProxyDispatcherCacheForTests(): Map<string, ProxyAgent>;
|
|
2
9
|
/** Loopback and NO_PROXY/no_proxy hosts should not go through HTTPS_PROXY. */
|
|
3
10
|
export declare function shouldBypassProxy(target: URL | string): boolean;
|
|
4
|
-
export declare function sendUnifiedRequest(url: URL | string, request: UnifiedChatRequest, config: any,
|
|
11
|
+
export declare function sendUnifiedRequest(url: URL | string, request: UnifiedChatRequest, config: any, context: any, _logger?: any): Promise<Response>;
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Incremental SSE event parser that preserves each event's raw bytes/text so
|
|
3
|
+
* unchanged events can be forwarded without re-serialization.
|
|
4
|
+
*/
|
|
5
|
+
export type ParsedSSEEvent = {
|
|
6
|
+
event?: string;
|
|
7
|
+
id?: string;
|
|
8
|
+
retry?: number;
|
|
9
|
+
/** Parsed JSON, `{ type: "done" }` for [DONE], or `{ raw, error }`. */
|
|
10
|
+
data?: unknown;
|
|
11
|
+
/** Original data field string (without the `data:` prefix), if any. */
|
|
12
|
+
dataRaw?: string;
|
|
13
|
+
/**
|
|
14
|
+
* Exact event block as received, including the blank-line delimiter.
|
|
15
|
+
* Forward this unchanged for byte-preserving passthrough.
|
|
16
|
+
*/
|
|
17
|
+
raw: string;
|
|
18
|
+
};
|
|
19
|
+
/**
|
|
20
|
+
* Feed decoded SSE text and emit complete events. Tolerates `\n` and `\r\n`.
|
|
21
|
+
*/
|
|
22
|
+
export declare class IncrementalSSEParser {
|
|
23
|
+
private buffer;
|
|
24
|
+
push(chunk: string): ParsedSSEEvent[];
|
|
25
|
+
flush(): ParsedSSEEvent[];
|
|
26
|
+
private takeComplete;
|
|
27
|
+
}
|
|
28
|
+
/** Serialize a (possibly modified) event. Prefer `event.raw` when unchanged. */
|
|
29
|
+
export declare function serializeSSEEvent(event: {
|
|
30
|
+
event?: string;
|
|
31
|
+
id?: string;
|
|
32
|
+
retry?: number;
|
|
33
|
+
data?: unknown;
|
|
34
|
+
dataRaw?: string;
|
|
35
|
+
}): string;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { type CacheAffinityHeaders, type CachePrefixDiff, type CachePrefixStage } from "./cache-prefix-debug";
|
|
2
|
+
import type { MessageDebugDirection } from "./message-debug";
|
|
2
3
|
export type UpstreamSSEDebugOptions = {
|
|
3
4
|
logger?: any;
|
|
4
5
|
reqId?: string | number;
|
|
@@ -19,6 +20,31 @@ export type UpstreamSSEDebugOptions = {
|
|
|
19
20
|
cacheDiff?: CachePrefixDiff | null;
|
|
20
21
|
/** Cap for a single logged payload string (raw `data` field). */
|
|
21
22
|
maxBytes?: number;
|
|
23
|
+
/**
|
|
24
|
+
* Opt-in raw per-event SSE logging. Independent of LOG_LEVEL=debug.
|
|
25
|
+
* When false (default), the debug tap still computes terminal cache outcome
|
|
26
|
+
* summaries but does not log every delta.
|
|
27
|
+
*/
|
|
28
|
+
rawEvents?: boolean;
|
|
29
|
+
/**
|
|
30
|
+
* Which wire leg produced these bytes. Defaults to `provider→ccr` for the
|
|
31
|
+
* upstream tap and `ccr→client` for the client tap.
|
|
32
|
+
*/
|
|
33
|
+
direction?: MessageDebugDirection;
|
|
34
|
+
/**
|
|
35
|
+
* When true, only emit raw SSE/JSON event logs (no cache outcome summary).
|
|
36
|
+
* Used for the client-bound leg where cache usage was already observed upstream.
|
|
37
|
+
*/
|
|
38
|
+
eventsOnly?: boolean;
|
|
39
|
+
};
|
|
40
|
+
export type ClientSSEDebugOptions = {
|
|
41
|
+
logger?: any;
|
|
42
|
+
reqId?: string | number;
|
|
43
|
+
provider?: string;
|
|
44
|
+
model?: string;
|
|
45
|
+
protocol?: string;
|
|
46
|
+
maxBytes?: number;
|
|
47
|
+
rawEvents?: boolean;
|
|
22
48
|
};
|
|
23
49
|
/**
|
|
24
50
|
* Byte-preserving upstream response debug tap.
|
|
@@ -42,6 +68,12 @@ export type UpstreamSSEDebugOptions = {
|
|
|
42
68
|
* the single shared place that covers every outbound provider.
|
|
43
69
|
*/
|
|
44
70
|
export declare function tapUpstreamSSEDebug(response: Response, opts: UpstreamSSEDebugOptions): Promise<Response>;
|
|
71
|
+
/**
|
|
72
|
+
* Byte-preserving tap for the SSE body CCR sends back to the client after
|
|
73
|
+
* response transformers. Same non-blocking tunnel as the upstream tap; events
|
|
74
|
+
* are tagged `direction: "ccr→client"` so greps can split the two legs.
|
|
75
|
+
*/
|
|
76
|
+
export declare function tapClientSSEDebug(body: ReadableStream<Uint8Array>, opts: ClientSSEDebugOptions): ReadableStream<Uint8Array>;
|
|
45
77
|
export type CacheStructureSummary = {
|
|
46
78
|
systemBreakpoints: number;
|
|
47
79
|
messageBreakpoints: number;
|
package/dist/utils/stream.d.ts
CHANGED
|
@@ -1,13 +1,36 @@
|
|
|
1
|
+
import { type ParsedSSEEvent } from "./sse/incremental-parser";
|
|
1
2
|
export interface StreamContext {
|
|
2
3
|
controller: ReadableStreamDefaultController;
|
|
3
4
|
encoder: TextEncoder;
|
|
4
5
|
}
|
|
5
|
-
export
|
|
6
|
+
export type SSEEvent = ParsedSSEEvent;
|
|
7
|
+
export type ProcessSSEEvent = (event: SSEEvent, context: StreamContext) => void;
|
|
8
|
+
export type ProcessSSELine = (line: string, context: StreamContext) => void;
|
|
9
|
+
/** Forward an event using its original raw bytes/string. */
|
|
10
|
+
export declare function forwardSSEEvent(event: SSEEvent, context: StreamContext): void;
|
|
11
|
+
/** Serialize and enqueue a modified event (only when data changed). */
|
|
12
|
+
export declare function emitSSEEvent(event: {
|
|
13
|
+
event?: string;
|
|
14
|
+
id?: string;
|
|
15
|
+
retry?: number;
|
|
16
|
+
data?: unknown;
|
|
17
|
+
dataRaw?: string;
|
|
18
|
+
}, context: StreamContext): void;
|
|
19
|
+
type StreamReaderOptions = {
|
|
6
20
|
bufferSize?: number;
|
|
7
21
|
onComplete?: (context: StreamContext) => void;
|
|
8
|
-
/** Return true when the protocol adapter emitted its own terminal error. */
|
|
9
22
|
onError?: (error: unknown, context: StreamContext) => boolean | void;
|
|
10
23
|
logger?: any;
|
|
11
|
-
|
|
24
|
+
processEvent?: ProcessSSEEvent;
|
|
25
|
+
};
|
|
26
|
+
/**
|
|
27
|
+
* Create a transformed SSE Response.
|
|
28
|
+
*
|
|
29
|
+
* Prefer `options.processEvent` for event-native handling (parse once, forward
|
|
30
|
+
* raw when unchanged). The legacy `processLine` callback is still supported via
|
|
31
|
+
* a shim that feeds reconstructed data lines.
|
|
32
|
+
*/
|
|
33
|
+
export declare function createSSEStreamReader(response: Response, processLineOrOptions?: ProcessSSELine | StreamReaderOptions, maybeOptions?: StreamReaderOptions): Response;
|
|
12
34
|
export declare function encodeSSEData(data: string, encoder: TextEncoder): Uint8Array;
|
|
13
35
|
export declare function encodeSSELine(line: string, encoder: TextEncoder): Uint8Array;
|
|
36
|
+
export { serializeSSEEvent } from "./sse/incremental-parser";
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export type TokenCountWorkerRequest = {
|
|
2
|
+
messages: unknown;
|
|
3
|
+
system: unknown;
|
|
4
|
+
tools: unknown;
|
|
5
|
+
};
|
|
6
|
+
/** Offload when serialized payload exceeds this many characters. */
|
|
7
|
+
export declare const TOKEN_COUNT_WORKER_THRESHOLD_CHARS = 200000;
|
|
8
|
+
export declare function estimateTokenizePayloadChars(messages: unknown, system: unknown, tools: unknown): number;
|
|
9
|
+
/** Conservative under-estimate: ~4 chars/token. Safe for "below threshold" skips. */
|
|
10
|
+
export declare function estimateTokensFromChars(charCount: number): number;
|
|
11
|
+
export declare function countTokensInWorker(request: TokenCountWorkerRequest): Promise<number>;
|
|
12
|
+
export declare function closeTokenCountWorkers(): Promise<void>;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { Transformer } from "../types/transformer";
|
|
2
|
+
export type CompiledTransformerPlan = {
|
|
3
|
+
/** Body/header middleware, then at most one transport owner. */
|
|
4
|
+
request: Transformer[];
|
|
5
|
+
/** Reverse of `request` for onion-style response transforms. */
|
|
6
|
+
response: Transformer[];
|
|
7
|
+
transportOwner?: Transformer;
|
|
8
|
+
};
|
|
9
|
+
/**
|
|
10
|
+
* Compile provider-level + model-level transformer chains into one plan.
|
|
11
|
+
*
|
|
12
|
+
* - Deduplicates by transformer name (first occurrence wins).
|
|
13
|
+
* - Runs every non-transport transformer before the transport owner.
|
|
14
|
+
* - Rejects configurations that leave more than one distinct transport owner.
|
|
15
|
+
*/
|
|
16
|
+
export declare function compileTransformerPlan(providerUse: Transformer[] | undefined, modelUse: Transformer[] | undefined, options?: {
|
|
17
|
+
skipName?: string;
|
|
18
|
+
}): CompiledTransformerPlan;
|
|
19
|
+
export declare function isExactProtocolResponsePlan(plan: CompiledTransformerPlan, endpointTransformer: Transformer, clientProtocolOwnerName: string | undefined): boolean;
|
|
20
|
+
/** Cancel a Response body when a newer transport result replaces it. */
|
|
21
|
+
export declare function cancelReplacedProviderResponse(previous: Response | undefined | null, next: Response | undefined | null): void;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@caeliq/llms",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.66",
|
|
4
4
|
"description": "A universal LLM API transformation server",
|
|
5
5
|
"main": "dist/cjs/server.cjs",
|
|
6
6
|
"module": "dist/esm/server.mjs",
|
|
@@ -29,28 +29,28 @@
|
|
|
29
29
|
"LICENSE"
|
|
30
30
|
],
|
|
31
31
|
"dependencies": {
|
|
32
|
-
"@anthropic-ai/sdk": "^0.
|
|
33
|
-
"@caeliq/ccr-shared": "^2.1.
|
|
34
|
-
"@cursor/sdk": "^1.0.
|
|
32
|
+
"@anthropic-ai/sdk": "^0.120.0",
|
|
33
|
+
"@caeliq/ccr-shared": "^2.1.8",
|
|
34
|
+
"@cursor/sdk": "^1.0.30",
|
|
35
35
|
"@fastify/cors": "^11.3.0",
|
|
36
36
|
"@fastify/rate-limit": "^11.2.0",
|
|
37
|
-
"@google/genai": "^2.
|
|
37
|
+
"@google/genai": "^2.18.0",
|
|
38
38
|
"@huggingface/tokenizers": "^0.1.3",
|
|
39
39
|
"dotenv": "^17.4.2",
|
|
40
|
-
"fastify": "^5.12.
|
|
40
|
+
"fastify": "^5.12.1",
|
|
41
41
|
"fastify-plugin": "^6.0.0",
|
|
42
42
|
"google-auth-library": "^11.0.2",
|
|
43
43
|
"json5": "^2.2.3",
|
|
44
44
|
"jsonrepair": "^3.15.0",
|
|
45
45
|
"latex-to-unicode": "^0.1.0",
|
|
46
46
|
"lru-cache": "^11.5.2",
|
|
47
|
-
"openai": "^7.
|
|
47
|
+
"openai": "^7.5.0",
|
|
48
48
|
"tiktoken": "^1.0.22",
|
|
49
49
|
"undici": "^8.10.0",
|
|
50
|
-
"uuid": "^14.0.
|
|
50
|
+
"uuid": "^14.0.2"
|
|
51
51
|
},
|
|
52
52
|
"devDependencies": {
|
|
53
|
-
"@types/node": "^26.
|
|
53
|
+
"@types/node": "^26.4.0",
|
|
54
54
|
"esbuild": "^0.28.2",
|
|
55
55
|
"tsx": "^4.23.12",
|
|
56
56
|
"typescript": "^6.0.3"
|