@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.
Files changed (75) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +82 -685
  3. package/dist/api/routes.d.ts +2 -0
  4. package/dist/cjs/server.cjs +279 -226
  5. package/dist/cjs/server.cjs.map +4 -4
  6. package/dist/cursor-sdk/hooks-template.d.ts +2 -1
  7. package/dist/cursor-sdk/host-env.d.ts +38 -0
  8. package/dist/cursor-sdk/lifecycle-planner.d.ts +69 -0
  9. package/dist/cursor-sdk/prompt.d.ts +33 -3
  10. package/dist/cursor-sdk/runner.d.ts +29 -0
  11. package/dist/cursor-sdk/session.d.ts +55 -1
  12. package/dist/cursor-sdk/shared.d.ts +14 -0
  13. package/dist/cursor-sdk/tool-paths.d.ts +26 -0
  14. package/dist/cursor-sdk/tools.d.ts +12 -1
  15. package/dist/cursor-sdk/turn-identity.d.ts +46 -0
  16. package/dist/cursor-sdk/turn-output.d.ts +77 -0
  17. package/dist/esm/server.mjs +280 -227
  18. package/dist/esm/server.mjs.map +4 -4
  19. package/dist/routing/inbound-pipeline.d.ts +31 -0
  20. package/dist/routing/protocol-adapter.d.ts +37 -0
  21. package/dist/routing/protocol-endpoints.d.ts +77 -0
  22. package/dist/routing/protocol-errors.d.ts +10 -0
  23. package/dist/server.d.ts +3 -1
  24. package/dist/services/provider.d.ts +1 -1
  25. package/dist/tests/anthropic.provider-wire.d.ts +1 -0
  26. package/dist/tests/anthropic.tool-call-id-sanitize.d.ts +1 -0
  27. package/dist/tests/anthropic.turn-intent.d.ts +1 -0
  28. package/dist/tests/claude-auth.identity.d.ts +1 -0
  29. package/dist/tests/client-abort-classification.test.d.ts +1 -0
  30. package/dist/tests/cursor-sdk.host-env.d.ts +1 -0
  31. package/dist/tests/cursor-sdk.interrupt-reentry.d.ts +1 -0
  32. package/dist/tests/cursor-sdk.lifecycle-planner.d.ts +1 -0
  33. package/dist/tests/cursor-sdk.pending-next-rejection.d.ts +1 -0
  34. package/dist/tests/cursor-sdk.scratch-paths.d.ts +1 -0
  35. package/dist/tests/cursor-sdk.scratch-report.d.ts +1 -0
  36. package/dist/tests/cursor-sdk.tool-call-id.d.ts +1 -0
  37. package/dist/tests/cursor-sdk.trailing-turn-fallback.d.ts +1 -0
  38. package/dist/tests/cursor-sdk.turn-coordination.d.ts +1 -0
  39. package/dist/tests/cursor-sdk.turn-identity.d.ts +1 -0
  40. package/dist/tests/inbound-protocol-routes.d.ts +1 -0
  41. package/dist/tests/inbound-routing-pipeline.d.ts +1 -0
  42. package/dist/tests/openai.inbound-chat.d.ts +1 -0
  43. package/dist/tests/openai.inbound-responses.d.ts +1 -0
  44. package/dist/tests/protocol-endpoints.d.ts +1 -0
  45. package/dist/tests/redact.body-for-log.d.ts +1 -0
  46. package/dist/tests/responses.call-id-sanitize.d.ts +1 -0
  47. package/dist/tests/responses.parallel-and-failure.d.ts +1 -0
  48. package/dist/tests/router-scenario-precedence.d.ts +1 -0
  49. package/dist/tests/stream.upstream-terminated.d.ts +1 -0
  50. package/dist/tests/system-instructions-fold.d.ts +1 -0
  51. package/dist/tests/upstream-error-semantics.d.ts +1 -0
  52. package/dist/transformer/anthropic.transformer.d.ts +16 -3
  53. package/dist/transformer/claude-auth.transformer.d.ts +36 -4
  54. package/dist/transformer/cursor-sdk.transformer.d.ts +4 -2
  55. package/dist/transformer/openai.responses.transformer.d.ts +17 -1
  56. package/dist/transformer/openai.transformer.d.ts +26 -32
  57. package/dist/transformer/tooluse.transformer.d.ts +1 -1
  58. package/dist/transformer/vercel.transformer.d.ts +1 -1
  59. package/dist/transformer/vertex-claude.transformer.d.ts +1 -1
  60. package/dist/transformer/vertex-gemini.transformer.d.ts +1 -1
  61. package/dist/types/transformer.d.ts +15 -0
  62. package/dist/types/turn-intent.d.ts +26 -0
  63. package/dist/utils/claude-auth.d.ts +9 -2
  64. package/dist/utils/claude-billing.d.ts +58 -0
  65. package/dist/utils/claude-model-catalog.d.ts +49 -0
  66. package/dist/utils/headers.d.ts +10 -0
  67. package/dist/utils/mistral.util.d.ts +1 -1
  68. package/dist/utils/openai.responses.util.d.ts +53 -0
  69. package/dist/utils/redact.d.ts +18 -0
  70. package/dist/utils/request.d.ts +1 -1
  71. package/dist/utils/retry.d.ts +7 -0
  72. package/dist/utils/router.d.ts +7 -0
  73. package/dist/utils/stream.d.ts +2 -0
  74. package/dist/utils/toolCallId.d.ts +23 -0
  75. 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, enabled: boolean): boolean;
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, _context?: any): Promise<any>;
11
- transformRequestOut(request: Record<string, any>, context?: any): Promise<UnifiedChatRequest>;
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. Do not synthesise Claude Code
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
- transformResponseOut(response: Response): Promise<Response>;
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?: any): Promise<Record<string, any>>;
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
- * ## How endPoint works
7
- *
8
- * At startup, `registerApiRoutes` (see `api/routes.ts`) scans all registered
9
- * transformers for ones that define `endPoint`. For each, it registers a
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, provider?: any, context?: any): Promise<any>;
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, provider?: any, context?: any): Promise<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, provider: LLMProvider): Promise<Record<string, any>>;
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, context?: any): Promise<Record<string, any>>;
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 const CLAUDE_AUTH_FILE: string;
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
- export { OAUTH_CONFIG, CLAUDE_AUTH_FILE };
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 };