@caeliq/llms 1.0.57 → 1.0.59
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/LICENSE +1 -1
- package/README.md +82 -685
- package/dist/api/routes.d.ts +2 -0
- package/dist/cjs/server.cjs +279 -226
- package/dist/cjs/server.cjs.map +4 -4
- package/dist/cursor-sdk/hooks-template.d.ts +2 -1
- package/dist/cursor-sdk/host-env.d.ts +38 -0
- package/dist/cursor-sdk/lifecycle-planner.d.ts +69 -0
- package/dist/cursor-sdk/prompt.d.ts +33 -3
- package/dist/cursor-sdk/runner.d.ts +29 -0
- package/dist/cursor-sdk/session.d.ts +55 -1
- package/dist/cursor-sdk/shared.d.ts +14 -0
- package/dist/cursor-sdk/tool-paths.d.ts +26 -0
- package/dist/cursor-sdk/tools.d.ts +12 -1
- package/dist/cursor-sdk/turn-identity.d.ts +46 -0
- package/dist/cursor-sdk/turn-output.d.ts +77 -0
- package/dist/esm/server.mjs +280 -227
- package/dist/esm/server.mjs.map +4 -4
- package/dist/routing/inbound-pipeline.d.ts +31 -0
- package/dist/routing/protocol-adapter.d.ts +37 -0
- package/dist/routing/protocol-endpoints.d.ts +77 -0
- package/dist/routing/protocol-errors.d.ts +10 -0
- package/dist/server.d.ts +3 -1
- package/dist/services/provider.d.ts +1 -1
- package/dist/tests/anthropic.provider-wire.d.ts +1 -0
- package/dist/tests/anthropic.tool-call-id-sanitize.d.ts +1 -0
- package/dist/tests/anthropic.turn-intent.d.ts +1 -0
- package/dist/tests/claude-auth.identity.d.ts +1 -0
- package/dist/tests/client-abort-classification.test.d.ts +1 -0
- package/dist/tests/cursor-sdk.host-env.d.ts +1 -0
- package/dist/tests/cursor-sdk.interrupt-reentry.d.ts +1 -0
- package/dist/tests/cursor-sdk.lifecycle-planner.d.ts +1 -0
- package/dist/tests/cursor-sdk.pending-next-rejection.d.ts +1 -0
- package/dist/tests/cursor-sdk.scratch-paths.d.ts +1 -0
- package/dist/tests/cursor-sdk.scratch-report.d.ts +1 -0
- package/dist/tests/cursor-sdk.tool-call-id.d.ts +1 -0
- package/dist/tests/cursor-sdk.trailing-turn-fallback.d.ts +1 -0
- package/dist/tests/cursor-sdk.turn-coordination.d.ts +1 -0
- package/dist/tests/cursor-sdk.turn-identity.d.ts +1 -0
- package/dist/tests/inbound-protocol-routes.d.ts +1 -0
- package/dist/tests/inbound-routing-pipeline.d.ts +1 -0
- package/dist/tests/openai.inbound-chat.d.ts +1 -0
- package/dist/tests/openai.inbound-responses.d.ts +1 -0
- package/dist/tests/protocol-endpoints.d.ts +1 -0
- package/dist/tests/redact.body-for-log.d.ts +1 -0
- package/dist/tests/responses.call-id-sanitize.d.ts +1 -0
- package/dist/tests/responses.parallel-and-failure.d.ts +1 -0
- package/dist/tests/router-scenario-precedence.d.ts +1 -0
- package/dist/tests/stream.upstream-terminated.d.ts +1 -0
- package/dist/tests/system-instructions-fold.d.ts +1 -0
- package/dist/tests/upstream-error-semantics.d.ts +1 -0
- package/dist/transformer/anthropic.transformer.d.ts +16 -3
- package/dist/transformer/claude-auth.transformer.d.ts +36 -4
- package/dist/transformer/cursor-sdk.transformer.d.ts +4 -2
- package/dist/transformer/openai.responses.transformer.d.ts +17 -1
- package/dist/transformer/openai.transformer.d.ts +26 -32
- package/dist/transformer/tooluse.transformer.d.ts +1 -1
- package/dist/transformer/vercel.transformer.d.ts +1 -1
- package/dist/transformer/vertex-claude.transformer.d.ts +1 -1
- package/dist/transformer/vertex-gemini.transformer.d.ts +1 -1
- package/dist/types/transformer.d.ts +15 -0
- package/dist/types/turn-intent.d.ts +26 -0
- package/dist/utils/claude-auth.d.ts +9 -2
- package/dist/utils/claude-billing.d.ts +58 -0
- package/dist/utils/claude-model-catalog.d.ts +49 -0
- package/dist/utils/headers.d.ts +10 -0
- package/dist/utils/mistral.util.d.ts +1 -1
- package/dist/utils/openai.responses.util.d.ts +53 -0
- package/dist/utils/redact.d.ts +18 -0
- package/dist/utils/request.d.ts +1 -1
- package/dist/utils/retry.d.ts +7 -0
- package/dist/utils/router.d.ts +7 -0
- package/dist/utils/stream.d.ts +2 -0
- package/dist/utils/toolCallId.d.ts +23 -0
- package/package.json +25 -21
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { FastifyInstance, FastifyReply, FastifyRequest } from "fastify";
|
|
2
|
+
import { Transformer } from "../types/transformer";
|
|
3
|
+
import { UnifiedChatRequest } from "../types/llm";
|
|
4
|
+
import { ClientProtocolContext, ProtocolRouteMatch } from "./protocol-endpoints";
|
|
5
|
+
export interface PreparedInboundRequest {
|
|
6
|
+
match: ProtocolRouteMatch;
|
|
7
|
+
protocolContext: ClientProtocolContext;
|
|
8
|
+
/** Original client wire body (preserved for Anthropic custom routers). */
|
|
9
|
+
originalBody: any;
|
|
10
|
+
/**
|
|
11
|
+
* Client wire body after protocol adaptation and CCR-only cleanup
|
|
12
|
+
* (subagent tag stripped, REWRITE_SYSTEM_PROMPT applied). This — not
|
|
13
|
+
* originalBody — is what an exact-wire passthrough must send upstream.
|
|
14
|
+
*/
|
|
15
|
+
clientWireBody: any;
|
|
16
|
+
/** Normalized Unified body used for routing and provider conversion. */
|
|
17
|
+
unifiedBody: UnifiedChatRequest;
|
|
18
|
+
providerName: string;
|
|
19
|
+
modelName: string;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Stages 1–7 of the canonical inbound lifecycle:
|
|
23
|
+
* detect → adapt → normalize → route → validate destination.
|
|
24
|
+
*/
|
|
25
|
+
export declare function prepareInboundRequest(req: FastifyRequest, reply: FastifyReply, fastify: FastifyInstance, endpointTransformer: Transformer, routePath: string): Promise<PreparedInboundRequest>;
|
|
26
|
+
export declare function resolveDestination(model: string | undefined, protocol?: ClientProtocolContext["protocol"]): {
|
|
27
|
+
providerName: string;
|
|
28
|
+
modelName: string;
|
|
29
|
+
};
|
|
30
|
+
export declare function throwProtocolError(protocol: ClientProtocolContext["protocol"] | undefined, message: string, statusCode: number, code: string, type?: string): never;
|
|
31
|
+
export declare function protocolAwareBypass(provider: any, transformer: Transformer, protocolContext: ClientProtocolContext | undefined, modelName: string | undefined): boolean;
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import type { UnifiedChatRequest } from "../types/llm";
|
|
2
|
+
import type { Transformer } from "../types/transformer";
|
|
3
|
+
import { ClientProtocolContext, ProtocolRouteMatch } from "./protocol-endpoints";
|
|
4
|
+
export interface ProtocolAdaptResult {
|
|
5
|
+
/** Cloned client body used as normalization input (never the live req.body). */
|
|
6
|
+
normalizationInput: any;
|
|
7
|
+
context: ClientProtocolContext;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Adapt path/query fields into a cloned normalization input and build the
|
|
11
|
+
* initial ClientProtocolContext. Does not mutate the caller's body object.
|
|
12
|
+
*/
|
|
13
|
+
export declare function adaptClientRequest(match: ProtocolRouteMatch, rawBody: any, _query?: Record<string, unknown>): ProtocolAdaptResult;
|
|
14
|
+
/**
|
|
15
|
+
* Normalize client wire → Unified once via the endpoint transformer's
|
|
16
|
+
* transformRequestOut when present. Chat Completions bodies are already
|
|
17
|
+
* Unified-shaped; until Phase 2/3 add full converters, fall back to a
|
|
18
|
+
* lightweight projection sufficient for routing.
|
|
19
|
+
*/
|
|
20
|
+
export declare function normalizeClientToUnified(protocol: ClientProtocolContext["protocol"], normalizationInput: any, endpointTransformer: Transformer, context: any): Promise<UnifiedChatRequest>;
|
|
21
|
+
/**
|
|
22
|
+
* Provider transformers are allowed to mutate their input. Every primary and
|
|
23
|
+
* fallback attempt therefore needs an independent copy of the normalized body.
|
|
24
|
+
*/
|
|
25
|
+
export declare function cloneProtocolBody<T>(value: T): T;
|
|
26
|
+
/**
|
|
27
|
+
* Preserve only known protocol/version and SDK metadata headers for exact-wire
|
|
28
|
+
* passthrough. An allowlist prevents an arbitrary client header from becoming
|
|
29
|
+
* an upstream credential or tenant-routing secret. Provider authentication is
|
|
30
|
+
* generated independently.
|
|
31
|
+
*/
|
|
32
|
+
export declare function sanitizePassthroughHeaders(headers: Headers | Record<string, unknown> | undefined): Record<string, string>;
|
|
33
|
+
/**
|
|
34
|
+
* Protocol-aware passthrough: only bypass when the provider speaks the same
|
|
35
|
+
* client protocol (matching transformer name) and the request is same-protocol.
|
|
36
|
+
*/
|
|
37
|
+
export declare function shouldBypassTransformersProtocolAware(provider: any, endpointTransformer: Transformer, protocol: ClientProtocolContext["protocol"], bodyModel: string | undefined): boolean;
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import type { RouterScenarioType } from "../utils/router";
|
|
2
|
+
/**
|
|
3
|
+
* Inbound client protocols supported by CCR's gateway lifecycle.
|
|
4
|
+
*/
|
|
5
|
+
export type ClientProtocol = "anthropic_messages" | "openai_chat_completions" | "openai_responses";
|
|
6
|
+
export interface AnthropicSourceRequestFields {
|
|
7
|
+
metadata?: Record<string, unknown>;
|
|
8
|
+
thinking?: Record<string, unknown>;
|
|
9
|
+
outputConfig?: Record<string, unknown>;
|
|
10
|
+
stopSequences?: string[];
|
|
11
|
+
}
|
|
12
|
+
export interface ClientProtocolContext {
|
|
13
|
+
protocol: ClientProtocol;
|
|
14
|
+
pathname: string;
|
|
15
|
+
/** Canonical Fastify route path (without preset prefix), e.g. /v1/responses */
|
|
16
|
+
canonicalPath: string;
|
|
17
|
+
/** Alias path that matched, if different from canonical */
|
|
18
|
+
matchedPath: string;
|
|
19
|
+
originalModel?: string;
|
|
20
|
+
stream: boolean;
|
|
21
|
+
scenarioType?: RouterScenarioType;
|
|
22
|
+
/** Source-only Anthropic semantics retained before destination routing. */
|
|
23
|
+
anthropicSource?: AnthropicSourceRequestFields;
|
|
24
|
+
/** Keep explicit source cache directives or add provider-native automatic caching. */
|
|
25
|
+
anthropicCacheMode?: "preserve" | "automatic";
|
|
26
|
+
/** Claude Code routing metadata extracted without mutating the source billing block. */
|
|
27
|
+
claudeCodeSubagent?: boolean;
|
|
28
|
+
taggedSubagentModel?: string;
|
|
29
|
+
/** Transformer that owns this client protocol */
|
|
30
|
+
ownerTransformerName: string;
|
|
31
|
+
}
|
|
32
|
+
export interface ProtocolRouteMatch {
|
|
33
|
+
protocol: ClientProtocol;
|
|
34
|
+
canonicalPath: string;
|
|
35
|
+
matchedPath: string;
|
|
36
|
+
ownerTransformerName: string;
|
|
37
|
+
/** True when matchedPath is an alias of canonicalPath */
|
|
38
|
+
isAlias: boolean;
|
|
39
|
+
stream: boolean;
|
|
40
|
+
/** Preset namespace prefix without trailing slash, e.g. /preset/foo */
|
|
41
|
+
presetPrefix?: string;
|
|
42
|
+
}
|
|
43
|
+
interface ProtocolRouteSpec {
|
|
44
|
+
protocol: ClientProtocol;
|
|
45
|
+
canonicalPath: string;
|
|
46
|
+
aliases: string[];
|
|
47
|
+
ownerTransformerName: string;
|
|
48
|
+
/** Default stream intent when not encoded in the path */
|
|
49
|
+
defaultStream?: boolean;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Client-facing route table. Aliases are first-class; registration must not
|
|
53
|
+
* rely on transformer endPoint first-wins.
|
|
54
|
+
*/
|
|
55
|
+
export declare const PROTOCOL_ROUTE_SPECS: ProtocolRouteSpec[];
|
|
56
|
+
/**
|
|
57
|
+
* Match a client LLM POST path to a protocol. Works with preset prefixes,
|
|
58
|
+
* trailing-slash normalization, and query stripping.
|
|
59
|
+
*/
|
|
60
|
+
export declare function matchClientProtocol(method: string, pathnameOrUrl: string): ProtocolRouteMatch | null;
|
|
61
|
+
/** True when method+path is an in-scope routed LLM POST. */
|
|
62
|
+
export declare function isRoutedLlmPost(method: string, pathnameOrUrl: string): boolean;
|
|
63
|
+
/** All Fastify paths that should be registered for a protocol (canonical + aliases). */
|
|
64
|
+
export declare function getRegisteredPathsForProtocol(protocol: ClientProtocol): string[];
|
|
65
|
+
/** Flat list of registered client routes and their owner transformers. */
|
|
66
|
+
export declare function listClientRouteRegistrations(): Array<{
|
|
67
|
+
path: string;
|
|
68
|
+
protocol: ClientProtocol;
|
|
69
|
+
ownerTransformerName: string;
|
|
70
|
+
isCanonical: boolean;
|
|
71
|
+
}>;
|
|
72
|
+
export declare function createClientProtocolContext(match: ProtocolRouteMatch, options?: {
|
|
73
|
+
originalModel?: string;
|
|
74
|
+
stream?: boolean;
|
|
75
|
+
scenarioType?: RouterScenarioType;
|
|
76
|
+
}): ClientProtocolContext;
|
|
77
|
+
export {};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { ClientProtocol } from "./protocol-endpoints";
|
|
2
|
+
export interface ProtocolErrorBody {
|
|
3
|
+
statusCode: number;
|
|
4
|
+
body: Record<string, unknown>;
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* Build a client-protocol-shaped error envelope for pre-provider failures
|
|
8
|
+
* (auth, validation, missing Router.default, etc.).
|
|
9
|
+
*/
|
|
10
|
+
export declare function protocolErrorBody(protocol: ClientProtocol | undefined, message: string, statusCode: number, code: string, type?: string): ProtocolErrorBody;
|
package/dist/server.d.ts
CHANGED
|
@@ -56,5 +56,7 @@ export { TokenizerService } from "./services/tokenizer";
|
|
|
56
56
|
export { pluginManager, tokenSpeedPlugin, getTokenSpeedStats, getGlobalTokenSpeedStats, CCRPlugin, CCRPluginOptions, PluginMetadata } from "./plugins";
|
|
57
57
|
export { SSEParserTransform, SSESerializerTransform, rewriteStream } from "./utils/sse";
|
|
58
58
|
export { isClientAbortError } from "./utils/retry";
|
|
59
|
-
export { sanitizeHeadersForLog, diffHeadersForLog, } from "./utils/redact";
|
|
59
|
+
export { sanitizeHeadersForLog, diffHeadersForLog, sanitizeBodyForLog, DEFAULT_LOG_BODY_MAX_BYTES, } from "./utils/redact";
|
|
60
60
|
export { exchangeAuthorizationCode, fetchUserEmail, resolveProjectId, saveTokens, loadTokens, getValidAccessToken, ANTIGRAVITY_CLIENT_ID, ANTIGRAVITY_CLIENT_SECRET, ANTIGRAVITY_REDIRECT_URI, ANTIGRAVITY_SCOPES, type AntigravityTokens, } from "./utils/antigravity-auth";
|
|
61
|
+
export { matchClientProtocol, isRoutedLlmPost, listClientRouteRegistrations, type ClientProtocol, type ClientProtocolContext, type ProtocolRouteMatch, } from "./routing/protocol-endpoints";
|
|
62
|
+
export { protocolErrorBody } from "./routing/protocol-errors";
|
|
@@ -17,7 +17,7 @@ export declare class ProviderService {
|
|
|
17
17
|
getProvider(name: string): LLMProvider | undefined;
|
|
18
18
|
updateProvider(id: string, updates: Partial<LLMProvider>): LLMProvider | null;
|
|
19
19
|
deleteProvider(id: string): boolean;
|
|
20
|
-
toggleProvider(name: string,
|
|
20
|
+
toggleProvider(name: string, _enabled: boolean): boolean;
|
|
21
21
|
resolveModelRoute(modelName: string): RequestRouteInfo | null;
|
|
22
22
|
getAvailableModelNames(): string[];
|
|
23
23
|
getModelRoutes(): ModelRoute[];
|
|
@@ -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 {};
|
|
@@ -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 {};
|
|
@@ -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 {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -7,15 +7,28 @@ export declare class AnthropicTransformer implements Transformer {
|
|
|
7
7
|
private useBearer;
|
|
8
8
|
logger?: any;
|
|
9
9
|
constructor(options?: TransformerOptions | undefined);
|
|
10
|
-
auth(request: any, provider: LLMProvider,
|
|
11
|
-
|
|
10
|
+
auth(request: any, provider: LLMProvider, context?: TransformerContext): Promise<any>;
|
|
11
|
+
/**
|
|
12
|
+
* Provider-side: Unified → Anthropic Messages wire.
|
|
13
|
+
* Enables cross-protocol clients (Chat/Responses) to reach Anthropic-shaped
|
|
14
|
+
* upstreams. Same-protocol Anthropic clients still use transformRequestOut
|
|
15
|
+
* for client→Unified and may bypass via protocol-aware passthrough.
|
|
16
|
+
*/
|
|
17
|
+
transformRequestIn(request: UnifiedChatRequest, provider: LLMProvider, _context?: TransformerContext): Promise<Record<string, any>>;
|
|
18
|
+
/**
|
|
19
|
+
* Provider-side: Anthropic Messages wire → Unified (Chat Completions shape).
|
|
20
|
+
* Reuses the Vertex Claude Anthropic→Unified converter so streaming and JSON
|
|
21
|
+
* envelopes match existing Anthropic upstream behavior.
|
|
22
|
+
*/
|
|
23
|
+
transformResponseOut(response: Response, _context?: TransformerContext): Promise<Response>;
|
|
24
|
+
transformRequestOut(request: Record<string, any>, context?: TransformerContext): Promise<UnifiedChatRequest>;
|
|
12
25
|
transformResponseIn(response: Response, context?: TransformerContext): Promise<Response>;
|
|
13
26
|
/**
|
|
14
27
|
* Rebuild an Anthropic-format request body from a UnifiedChatRequest.
|
|
15
28
|
* Used by claude-auth.transformRequestIn() to reconstruct the body before
|
|
16
29
|
* sending to Anthropic, preserving all original parameters.
|
|
17
30
|
*/
|
|
18
|
-
static buildAnthropicBody(request: UnifiedChatRequest, logger?: any): Record<string, any>;
|
|
31
|
+
static buildAnthropicBody(request: UnifiedChatRequest, logger?: any, context?: TransformerContext): Record<string, any>;
|
|
19
32
|
private convertAnthropicToolsToUnified;
|
|
20
33
|
private convertOpenAIStreamToAnthropic;
|
|
21
34
|
private convertOpenAIResponseToAnthropic;
|
|
@@ -1,25 +1,57 @@
|
|
|
1
1
|
import { UnifiedChatRequest } from "../types/llm";
|
|
2
2
|
import { Transformer, TransformerContext } from "../types/transformer";
|
|
3
|
+
import { ClaudeModelCatalogEntry } from "../utils/claude-model-catalog";
|
|
3
4
|
/** Anthropic beta required for Claude subscription / Claude Code OAuth Bearer auth. */
|
|
4
5
|
export declare const CLAUDE_OAUTH_REQUIRED_BETA = "oauth-2025-04-20";
|
|
5
6
|
export declare function mergeAnthropicBetaValues(...values: Array<string | undefined | null>): string;
|
|
6
7
|
/** Read a named header value from a Fastify/Node headers object (case-insensitive). */
|
|
7
8
|
export declare function readHeaderValue(headers: Record<string, unknown> | undefined, name: string): string | undefined;
|
|
9
|
+
/** True when the client's User-Agent identifies it as the genuine Claude Code CLI. */
|
|
10
|
+
export declare function isClaudeCodeClient(userAgent: string | undefined): boolean;
|
|
8
11
|
/**
|
|
9
12
|
* Build outbound anthropic-beta for Claude subscription OAuth.
|
|
10
13
|
*
|
|
11
14
|
* - If the client sent anthropic-beta (e.g. Claude Code), merge with
|
|
12
15
|
* oauth-2025-04-20 (deduped, case-insensitive).
|
|
13
|
-
* - Otherwise, send only oauth-2025-04-20.
|
|
14
|
-
* betas — Anthropic validates the attestation on claude-code-20250219
|
|
15
|
-
* and subscription OAuth works without it for non-Claude-Code clients.
|
|
16
|
+
* - Otherwise, send only oauth-2025-04-20.
|
|
16
17
|
*/
|
|
17
18
|
export declare function resolveClaudeAuthAnthropicBeta(input: {
|
|
18
19
|
clientBeta?: string;
|
|
19
20
|
}): string;
|
|
21
|
+
/**
|
|
22
|
+
* Build outbound anthropic-beta for the non-Claude-Code (full synthesis)
|
|
23
|
+
* branch, mirroring Claude Code's own model-driven beta selection. Never
|
|
24
|
+
* derived from model-name prefix matching — always from the capability
|
|
25
|
+
* catalog. `ANTHROPIC_BETA_FLAGS` replaces the list wholesale.
|
|
26
|
+
*/
|
|
27
|
+
export declare function resolveClaudeAuthBetas(modelId: string | undefined, opts?: {
|
|
28
|
+
envBeta?: string;
|
|
29
|
+
}): string;
|
|
30
|
+
/**
|
|
31
|
+
* Reshape a built Anthropic body's `thinking`/`output_config`/`max_tokens`
|
|
32
|
+
* to what the resolved model actually supports, replacing a hand-rolled
|
|
33
|
+
* per-model denylist with a single catalog-driven pass. Operates on the
|
|
34
|
+
* post-build Anthropic body (not the Unified request) because
|
|
35
|
+
* `buildAnthropicBody` may synthesize `thinking`/`output_config` itself.
|
|
36
|
+
*/
|
|
37
|
+
export declare function applyClaudeModelCapabilityAdjustments(anthropicBody: Record<string, any>, entry: ClaudeModelCatalogEntry | undefined): void;
|
|
38
|
+
/** Test-only reset hook so session-id state doesn't leak across test cases. */
|
|
39
|
+
export declare function __resetClaudeAuthTransformerStateForTests(): void;
|
|
20
40
|
export declare class ClaudeAuthTransformer implements Transformer {
|
|
21
41
|
name: string;
|
|
22
42
|
logger?: any;
|
|
23
43
|
transformRequestIn(request: UnifiedChatRequest, provider: any, context?: TransformerContext): Promise<Record<string, any>>;
|
|
24
|
-
|
|
44
|
+
/**
|
|
45
|
+
* Body/URL/wire-format conversion belong to AnthropicTransformer's
|
|
46
|
+
* provider pair, which already ran (response-side order is reversed, so
|
|
47
|
+
* it runs before this stage). This stage only inspects the resulting
|
|
48
|
+
* response for subscription-specific overage observability.
|
|
49
|
+
*/
|
|
50
|
+
transformResponseOut(response: Response, context?: TransformerContext): Promise<Response>;
|
|
51
|
+
/**
|
|
52
|
+
* 401 recovery: reload the token file in case another process (e.g. a
|
|
53
|
+
* concurrent `ccr claude-auth` re-login) rotated it externally, otherwise
|
|
54
|
+
* refresh and persist. Never falls through to an unauthenticated request.
|
|
55
|
+
*/
|
|
56
|
+
private recoverUnauthorizedAuth;
|
|
25
57
|
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { UnifiedChatRequest } from "../types/llm";
|
|
2
|
-
import type { Transformer, TransformerOptions } from "../types/transformer";
|
|
2
|
+
import type { Transformer, TransformerContext, TransformerOptions } from "../types/transformer";
|
|
3
|
+
import { type CursorSdkRunnerOptions } from "../cursor-sdk/runner";
|
|
3
4
|
import { type CursorSdkMode } from "../cursor-sdk/shared";
|
|
4
5
|
export interface CursorSdkTransformerOptions extends TransformerOptions {
|
|
5
6
|
cursorMode?: CursorSdkMode;
|
|
@@ -7,6 +8,7 @@ export interface CursorSdkTransformerOptions extends TransformerOptions {
|
|
|
7
8
|
/** Opt-in only; forced off in Docker. Default false. */
|
|
8
9
|
sandboxEnabled?: boolean;
|
|
9
10
|
}
|
|
11
|
+
export declare function buildCursorSdkRunnerOptions(options: CursorSdkTransformerOptions, context?: TransformerContext, logger?: any): CursorSdkRunnerOptions;
|
|
10
12
|
/**
|
|
11
13
|
* Thin CCR transformer that owns the full upstream call via @cursor/sdk.
|
|
12
14
|
* Returns OpenAI-compatible SSE/JSON through config.__providerResponse so
|
|
@@ -18,6 +20,6 @@ export declare class CursorSdkTransformer implements Transformer {
|
|
|
18
20
|
logger?: any;
|
|
19
21
|
private options;
|
|
20
22
|
constructor(options?: CursorSdkTransformerOptions);
|
|
21
|
-
transformRequestIn(request: UnifiedChatRequest, provider: any, context?:
|
|
23
|
+
transformRequestIn(request: UnifiedChatRequest, provider: any, context?: TransformerContext): Promise<Record<string, any>>;
|
|
22
24
|
transformResponseOut(response: Response): Promise<Response>;
|
|
23
25
|
}
|
|
@@ -1,11 +1,27 @@
|
|
|
1
1
|
import { UnifiedChatRequest } from "../types/llm";
|
|
2
|
-
import { Transformer } from "../types/transformer";
|
|
2
|
+
import { Transformer, TransformerContext } from "../types/transformer";
|
|
3
3
|
export declare class OpenAIResponsesTransformer implements Transformer {
|
|
4
4
|
logger?: any;
|
|
5
5
|
name: string;
|
|
6
6
|
endPoint: string;
|
|
7
|
+
/**
|
|
8
|
+
* Client → Unified: validate Responses MVP and project to Chat Completions shape.
|
|
9
|
+
* Call-id mapping is stored on the transformer context for the response path.
|
|
10
|
+
*/
|
|
11
|
+
transformRequestOut(request: any, context?: TransformerContext): Promise<UnifiedChatRequest>;
|
|
12
|
+
/**
|
|
13
|
+
* Unified → client Responses: JSON object or SSE lifecycle with mandatory
|
|
14
|
+
* content_part events (Codex requires these or streamed text is discarded).
|
|
15
|
+
*/
|
|
16
|
+
transformResponseIn(response: Response, context?: TransformerContext): Promise<Response>;
|
|
17
|
+
private convertUnifiedStreamToResponses;
|
|
7
18
|
transformRequestIn(request: UnifiedChatRequest, provider?: any, context?: any): Promise<UnifiedChatRequest>;
|
|
8
19
|
transformResponseOut(response: Response): Promise<Response>;
|
|
20
|
+
/**
|
|
21
|
+
* Convert one Responses stream event to a Chat chunk. `choices[0].index` is
|
|
22
|
+
* always 0 — parallel-call identity lives in `delta.tool_calls[n].index`,
|
|
23
|
+
* allocated per Responses item by `toolIndexFor`.
|
|
24
|
+
*/
|
|
9
25
|
private convertStreamEvent;
|
|
10
26
|
private normalizeRequestContent;
|
|
11
27
|
private convertResponseToChat;
|
|
@@ -1,39 +1,12 @@
|
|
|
1
|
-
import { Transformer } from "../types/transformer";
|
|
1
|
+
import { Transformer, TransformerContext } from "../types/transformer";
|
|
2
2
|
import { UnifiedChatRequest } from "../types/llm";
|
|
3
3
|
/**
|
|
4
4
|
* Server-side route handler for the OpenAI Chat Completions API.
|
|
5
5
|
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
* `POST` route at that path. When a request hits the route,
|
|
11
|
-
* `handleTransformerEndpoint` is invoked with the matching transformer as
|
|
12
|
-
* the "endpoint transformer" — the one responsible for converting between
|
|
13
|
-
* the external wire format and the internal Unified format.
|
|
14
|
-
*
|
|
15
|
-
* ## Request handling
|
|
16
|
-
*
|
|
17
|
-
* The Unified format IS the OpenAI Chat Completions format. The conversion
|
|
18
|
-
* from Anthropic → Unified already happened in
|
|
19
|
-
* `AnthropicTransformer.transformRequestOut()` (which runs first in the
|
|
20
|
-
* pipeline). So by the time the provider chain executes, the body is already
|
|
21
|
-
* in the right shape — no further conversion is needed.
|
|
22
|
-
*
|
|
23
|
-
* `transformRequestIn` also translates Claude Code cache intent to the
|
|
24
|
-
* selected provider's native Chat Completions behavior. The provider identity
|
|
25
|
-
* is checked before adding request-level fields so OpenAI-compatible services
|
|
26
|
-
* do not receive OpenAI-only parameters.
|
|
27
|
-
*
|
|
28
|
-
* ## Relationship to OpenAIResponsesTransformer
|
|
29
|
-
*
|
|
30
|
-
* `OpenAIResponsesTransformer` (in `openai.responses.transformer.ts`) is the
|
|
31
|
-
* counterpart for the Responses API (`/v1/responses`). Unlike this
|
|
32
|
-
* transformer, it defines `transformRequestIn` / `transformResponseOut`
|
|
33
|
-
* because the Responses API uses a different wire format (e.g. `messages`
|
|
34
|
-
* → `input`, function tools → flat tool definitions). It also uses the
|
|
35
|
-
* shared utilities in `openai.util.ts` (`validateOpenAIToolCalls`,
|
|
36
|
-
* `injectPromptCaching`) to sanitize the Unified body before converting it.
|
|
6
|
+
* The Unified format IS the OpenAI Chat Completions format. Client inbound
|
|
7
|
+
* normalization validates the MVP subset and passes through already-correct
|
|
8
|
+
* Chat bodies. Provider-side transformRequestIn applies cache policy for
|
|
9
|
+
* OpenAI-compatible upstreams.
|
|
37
10
|
*
|
|
38
11
|
* ## Full request pipeline (for context)
|
|
39
12
|
*
|
|
@@ -44,9 +17,30 @@ import { UnifiedChatRequest } from "../types/llm";
|
|
|
44
17
|
* → provider.transformer.use[].transformResponseOut() // provider middleware (reversed)
|
|
45
18
|
* → AnthropicTransformer.transformResponseIn() // Unified (OpenAI) → Anthropic
|
|
46
19
|
* → Client
|
|
20
|
+
*
|
|
21
|
+
* For inbound Chat Completions clients:
|
|
22
|
+
*
|
|
23
|
+
* Client → POST /v1/chat/completions
|
|
24
|
+
* → OpenAITransformer.transformRequestOut() // validate → Unified
|
|
25
|
+
* → provider.transformer.use[].transformRequestIn()
|
|
26
|
+
* → … → OpenAITransformer.transformResponseIn() // identity / light normalize
|
|
47
27
|
*/
|
|
48
28
|
export declare class OpenAITransformer implements Transformer {
|
|
49
29
|
name: string;
|
|
50
30
|
endPoint: string;
|
|
31
|
+
/**
|
|
32
|
+
* Client → Unified: validate the Chat Completions MVP subset.
|
|
33
|
+
* Unified is already Chat-shaped, so this is validation + light normalization.
|
|
34
|
+
*/
|
|
35
|
+
transformRequestOut(request: any, _context?: TransformerContext): Promise<UnifiedChatRequest>;
|
|
36
|
+
/**
|
|
37
|
+
* Provider-side: apply OpenAI-native cache policy to a Unified Chat body.
|
|
38
|
+
*/
|
|
51
39
|
transformRequestIn(request: UnifiedChatRequest, provider: any, context: any): Promise<UnifiedChatRequest>;
|
|
40
|
+
/**
|
|
41
|
+
* Unified → client Chat Completions: pass through already-correct Chat JSON/SSE.
|
|
42
|
+
* Ensures Content-Type and that streaming responses terminate with [DONE] when
|
|
43
|
+
* the upstream already speaks Chat Completions.
|
|
44
|
+
*/
|
|
45
|
+
transformResponseIn(response: Response, _context?: TransformerContext): Promise<Response>;
|
|
52
46
|
}
|
|
@@ -2,6 +2,6 @@ import { UnifiedChatRequest } from "../types/llm";
|
|
|
2
2
|
import { Transformer } from "../types/transformer";
|
|
3
3
|
export declare class TooluseTransformer implements Transformer {
|
|
4
4
|
name: string;
|
|
5
|
-
transformRequestIn(request: UnifiedChatRequest,
|
|
5
|
+
transformRequestIn(request: UnifiedChatRequest, _provider?: any, _context?: any): Promise<any>;
|
|
6
6
|
transformResponseOut(response: Response): Promise<Response>;
|
|
7
7
|
}
|
|
@@ -6,6 +6,6 @@ export declare class VercelTransformer implements Transformer {
|
|
|
6
6
|
logger?: any;
|
|
7
7
|
endPoint: string;
|
|
8
8
|
constructor(options?: TransformerOptions | undefined);
|
|
9
|
-
transformRequestIn(request: UnifiedChatRequest,
|
|
9
|
+
transformRequestIn(request: UnifiedChatRequest, _provider?: any, _context?: any): Promise<UnifiedChatRequest>;
|
|
10
10
|
transformResponseOut(response: Response): Promise<Response>;
|
|
11
11
|
}
|
|
@@ -3,7 +3,7 @@ import { Transformer } from "../types/transformer";
|
|
|
3
3
|
export declare class VertexClaudeTransformer implements Transformer {
|
|
4
4
|
logger?: any;
|
|
5
5
|
name: string;
|
|
6
|
-
transformRequestIn(request: UnifiedChatRequest,
|
|
6
|
+
transformRequestIn(request: UnifiedChatRequest, _provider: LLMProvider): Promise<Record<string, any>>;
|
|
7
7
|
transformRequestOut(request: Record<string, any>): Promise<UnifiedChatRequest>;
|
|
8
8
|
transformResponseOut(response: Response): Promise<Response>;
|
|
9
9
|
}
|
|
@@ -6,7 +6,7 @@ export declare class VertexGeminiTransformer implements Transformer {
|
|
|
6
6
|
name: string;
|
|
7
7
|
private readonly thoughtSignatureFallback;
|
|
8
8
|
constructor(options?: TransformerOptions);
|
|
9
|
-
transformRequestIn(request: UnifiedChatRequest, provider: LLMProvider,
|
|
9
|
+
transformRequestIn(request: UnifiedChatRequest, provider: LLMProvider, _context?: any): Promise<Record<string, any>>;
|
|
10
10
|
transformRequestOut(request: Record<string, any>): Promise<UnifiedChatRequest>;
|
|
11
11
|
transformResponseOut(response: Response, context?: TransformerContext): Promise<Response>;
|
|
12
12
|
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { LLMProvider, UnifiedChatRequest } from "./llm";
|
|
2
|
+
import type { UnifiedRequestRuntime } from "./turn-intent";
|
|
2
3
|
export interface TransformerOptions {
|
|
3
4
|
[key: string]: any;
|
|
4
5
|
}
|
|
@@ -8,6 +9,20 @@ interface TransformerWithStaticName {
|
|
|
8
9
|
}
|
|
9
10
|
export type TransformerConstructor = TransformerWithStaticName;
|
|
10
11
|
export interface TransformerContext {
|
|
12
|
+
req?: any;
|
|
13
|
+
provider?: any;
|
|
14
|
+
signal?: AbortSignal;
|
|
15
|
+
/** Protocol semantics that must not be serialized into the provider body. */
|
|
16
|
+
unifiedRequest?: UnifiedRequestRuntime;
|
|
17
|
+
/**
|
|
18
|
+
* Set by claude-auth's transformRequestIn (non-Claude-Code branch) so that
|
|
19
|
+
* AnthropicTransformer.transformRequestIn — which owns building the wire
|
|
20
|
+
* body — can apply claude-auth's catalog-driven capability clamping and
|
|
21
|
+
* synthesized user_id metadata immediately after building it. Keeps model
|
|
22
|
+
* capability/identity-synthesis policy owned by claude-auth while
|
|
23
|
+
* AnthropicTransformer remains the sole body-shape/timing owner.
|
|
24
|
+
*/
|
|
25
|
+
claudeAuthPostBuildHook?: (anthropicBody: Record<string, any>) => void;
|
|
11
26
|
[key: string]: any;
|
|
12
27
|
}
|
|
13
28
|
export type Transformer = {
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Request-local semantics recovered by a wire-protocol transformer.
|
|
3
|
+
*
|
|
4
|
+
* This state belongs on TransformerContext, not UnifiedChatRequest: the latter
|
|
5
|
+
* is also the OpenAI-compatible outbound body and is serialized for providers.
|
|
6
|
+
*/
|
|
7
|
+
export type UnifiedTrailingToolResult = {
|
|
8
|
+
toolCallId: string;
|
|
9
|
+
content: string;
|
|
10
|
+
isError: boolean;
|
|
11
|
+
};
|
|
12
|
+
export type UnifiedTurnIntent = {
|
|
13
|
+
source: "anthropic" | "unified-fallback";
|
|
14
|
+
trailingToolResults: UnifiedTrailingToolResult[];
|
|
15
|
+
interruption: "none" | "synthetic_client_interrupt";
|
|
16
|
+
steering: "none" | "meaningful";
|
|
17
|
+
};
|
|
18
|
+
export type UnifiedRequestRuntime = {
|
|
19
|
+
source: "anthropic";
|
|
20
|
+
sourceSessionIdentity?: string;
|
|
21
|
+
turnIntent: UnifiedTurnIntent;
|
|
22
|
+
};
|
|
23
|
+
export declare const ANTHROPIC_SYNTHETIC_INTERRUPT_MARKERS: readonly ["[Request interrupted by user]", "[Request interrupted by user for tool use]"];
|
|
24
|
+
export declare function classifyAnthropicTurnIntent(requestMessages: unknown): UnifiedTurnIntent;
|
|
25
|
+
export declare function extractAnthropicSourceSessionIdentity(metadata: unknown): string | undefined;
|
|
26
|
+
export declare function buildAnthropicRequestRuntime(request: Record<string, any>): UnifiedRequestRuntime;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
declare
|
|
1
|
+
declare function getClaudeAuthFilePath(): string;
|
|
2
|
+
declare function getClaudeDeviceFilePath(): string;
|
|
2
3
|
declare const OAUTH_CONFIG: {
|
|
3
4
|
client_id: string;
|
|
4
5
|
authorization_endpoint: string;
|
|
@@ -19,4 +20,10 @@ export declare function saveTokens(tokens: ClaudeTokens): void;
|
|
|
19
20
|
export declare function isTokenExpired(tokens: ClaudeTokens, leewaySeconds?: number): boolean;
|
|
20
21
|
export declare function refreshTokens(refreshToken: string): Promise<ClaudeTokens>;
|
|
21
22
|
export declare function getValidAccessToken(): Promise<ClaudeTokens>;
|
|
22
|
-
|
|
23
|
+
/**
|
|
24
|
+
* Load the persisted synthesized-client device id, minting and persisting a
|
|
25
|
+
* fresh 64-hex value on first use. Stored alongside the OAuth token file
|
|
26
|
+
* (mode 0600) but kept separate from it — it is not a credential.
|
|
27
|
+
*/
|
|
28
|
+
export declare function loadOrCreateDeviceId(): string;
|
|
29
|
+
export { OAUTH_CONFIG, getClaudeAuthFilePath, getClaudeDeviceFilePath };
|