@caeliq/llms 1.0.70 → 1.0.72

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.
@@ -10,6 +10,33 @@ export interface AnthropicSourceRequestFields {
10
10
  thinking?: Record<string, unknown>;
11
11
  outputConfig?: Record<string, unknown>;
12
12
  stopSequences?: string[];
13
+ /**
14
+ * Anthropic-defined (typed) tools such as `web_search_20250305` or
15
+ * `bash_20250124`, exactly as the client sent them. Unified `tools[]` keeps
16
+ * their function projection (by name) for routing and other providers.
17
+ */
18
+ tools?: Record<string, any>[];
19
+ /**
20
+ * Server tool blocks (`server_tool_use`, `web_search_tool_result`) of each
21
+ * assistant turn, indexed by assistant-turn ordinal, with that turn's
22
+ * joined text so the builder only re-attaches them to the same turn.
23
+ */
24
+ assistantServerBlocks?: Array<{
25
+ text: string;
26
+ blocks: any[];
27
+ } | undefined>;
28
+ }
29
+ /** Client asked for provider-hosted web search (any inbound protocol). */
30
+ export interface HostedWebSearchRequest {
31
+ allowedDomains?: string[];
32
+ /** Per-request search cap from `WEB_SEARCH_MAX_USES` (none by default). */
33
+ maxUses?: number;
34
+ userLocation?: {
35
+ city?: string;
36
+ region?: string;
37
+ country?: string;
38
+ timezone?: string;
39
+ };
13
40
  }
14
41
  export interface ClientProtocolContext {
15
42
  protocol: ClientProtocol;
@@ -25,6 +52,12 @@ export interface ClientProtocolContext {
25
52
  scenarioType?: RouterScenarioType;
26
53
  /** Source-only Anthropic semantics retained before destination routing. */
27
54
  anthropicSource?: AnthropicSourceRequestFields;
55
+ /**
56
+ * Hosted web search requested by an Anthropic `web_search_*` tool, a
57
+ * Responses `web_search` tool or Chat `web_search_options`; Unified carries
58
+ * the `web_search` function projection.
59
+ */
60
+ hostedWebSearch?: HostedWebSearchRequest;
28
61
  /** Client fingerprint captured before Anthropic normalization. */
29
62
  anthropicClientKind?: AnthropicClientKind;
30
63
  /** In-scope Anthropic destination/auth variant selected after routing. */
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1 @@
1
+ export {};
@@ -5,6 +5,14 @@ import { ClaudeModelCatalogEntry } from "../utils/claude-model-catalog";
5
5
  /** Anthropic beta required for Claude subscription / Claude Code OAuth Bearer auth. */
6
6
  export declare const CLAUDE_OAUTH_REQUIRED_BETA = "oauth-2025-04-20";
7
7
  export declare function mergeAnthropicBetaValues(...values: Array<string | undefined | null>): string;
8
+ /**
9
+ * Beta tokens a third-party client sent for its Anthropic-defined computer use
10
+ * tool (e.g. `computer-use-2025-11-24` for `computer_20251124`). The emulated
11
+ * profile otherwise ignores client betas; the client already chose the one
12
+ * matching its tool version, so only that family is carried over, and only
13
+ * when the request actually declares a `computer_*` tool.
14
+ */
15
+ export declare function clientComputerUseBetas(clientBeta: string | undefined, typedTools: Array<Record<string, any>> | undefined): string | undefined;
8
16
  /** Read a named header value from a Fastify/Node headers object (case-insensitive). */
9
17
  export declare function readHeaderValue(headers: Record<string, unknown> | undefined, name: string): string | undefined;
10
18
  /** True when the client's User-Agent identifies it as the genuine Claude Code CLI. */
@@ -67,8 +75,9 @@ export declare class ClaudeAuthTransformer implements Transformer {
67
75
  /**
68
76
  * Body/URL/wire-format conversion belong to AnthropicTransformer's
69
77
  * provider pair, which already ran (response-side order is reversed, so
70
- * it runs before this stage). This stage only inspects the resulting
71
- * response for subscription-specific overage observability.
78
+ * it runs before this stage). This stage inspects the resulting response
79
+ * for subscription-specific overage observability and restores tool names
80
+ * its own legacy branch renamed.
72
81
  */
73
82
  transformResponseOut(response: Response, context?: TransformerContext): Promise<Response>;
74
83
  /**
@@ -18,6 +18,16 @@ export interface Annotation {
18
18
  type: "url_citation";
19
19
  url_citation?: UrlCitation;
20
20
  }
21
+ /**
22
+ * A provider-executed web search (e.g. Anthropic's server `web_search`),
23
+ * surfaced so clients can render the call itself (Responses `web_search_call`).
24
+ * Internal: Chat Completions clients never receive it.
25
+ */
26
+ export interface WebSearchCall {
27
+ id: string;
28
+ query: string;
29
+ status: "completed" | "failed";
30
+ }
21
31
  export interface TextContent {
22
32
  type: "text";
23
33
  text: string;
@@ -137,6 +147,12 @@ export interface UnifiedChatRequest {
137
147
  anthropic_output_config?: Record<string, any>;
138
148
  anthropic_metadata?: Record<string, any>;
139
149
  anthropic_stop_sequences?: string[];
150
+ /**
151
+ * Anthropic-defined (typed) tools for legacy direct claude-auth callers,
152
+ * like the other anthropic_* fields. Routed requests carry them in
153
+ * `protocolContext.anthropicSource.tools` so no other provider sees them.
154
+ */
155
+ anthropic_tools?: Record<string, any>[];
140
156
  reasoning_effort?: string;
141
157
  /**
142
158
  * Responses opaque `include` list (e.g. `reasoning.encrypted_content`).
@@ -168,6 +184,7 @@ export interface UnifiedChatResponse {
168
184
  };
169
185
  }>;
170
186
  annotations?: Annotation[];
187
+ web_search_calls?: WebSearchCall[];
171
188
  }
172
189
  export interface StreamChunk {
173
190
  id: string;
@@ -195,6 +212,7 @@ export interface StreamChunk {
195
212
  thought_signature?: string;
196
213
  }>;
197
214
  annotations?: Annotation[];
215
+ web_search_calls?: WebSearchCall[];
198
216
  };
199
217
  finish_reason?: string | null;
200
218
  }>;
@@ -1,4 +1,5 @@
1
1
  import { UnifiedChatRequest } from "../types/llm";
2
+ import type { AnthropicSourceRequestFields, HostedWebSearchRequest } from "../routing/protocol-endpoints";
2
3
  export type AnthropicClientKind = "claude_desktop" | "claude_code" | "other";
3
4
  export type AnthropicProviderMode = "api_key" | "claude_oauth" | "out_of_scope";
4
5
  export interface AnthropicClientFingerprintSignals {
@@ -20,6 +21,8 @@ export interface AnthropicClientPolicyContext {
20
21
  anthropicPolicyApplied?: boolean;
21
22
  anthropicSystemTransformed?: boolean;
22
23
  claudeAuthToolNameMap?: Map<string, string>;
24
+ anthropicSource?: AnthropicSourceRequestFields;
25
+ hostedWebSearch?: HostedWebSearchRequest;
23
26
  }
24
27
  export declare function readHeaderValue(headers: Record<string, unknown> | undefined, name: string): string | undefined;
25
28
  /**
@@ -37,9 +40,26 @@ export declare function inspectAnthropicClientFingerprint(headers: Record<string
37
40
  */
38
41
  export declare function getAnthropicProviderMode(provider: any, endpointTransformerName?: string): AnthropicProviderMode;
39
42
  export declare function isNativeAnthropicClient(kind: AnthropicClientKind): boolean;
43
+ /** `CLAUDE_AUTH_NATIVE_CACHE_TTL` values: `1h` (default) or `client`. */
44
+ export type NativeClaudeOAuthCacheTtlMode = "1h" | "client";
45
+ export declare function resolveNativeClaudeOAuthCacheTtlMode(value: unknown): NativeClaudeOAuthCacheTtlMode;
46
+ /**
47
+ * Native Desktop/CLI on claude-auth OAuth: extend the client's default-TTL
48
+ * (5m) ephemeral breakpoints to 1h, the TTL the third-party profile already
49
+ * uses on this route. Breakpoint placement is untouched. A body that already
50
+ * sets a TTL on any breakpoint is left exactly as sent (an explicit client
51
+ * choice), as is every body when the mode is `client`. Returns whether the
52
+ * body changed.
53
+ */
54
+ export declare function applyNativeClaudeOAuthCacheTtl(body: any, context: AnthropicClientPolicyContext | undefined, mode?: NativeClaudeOAuthCacheTtlMode): boolean;
40
55
  /**
41
56
  * Apply the one and only system transformation allowed by the gateway policy.
42
57
  * This runs after routing has identified an in-scope Anthropic destination and
43
58
  * before the provider's Anthropic body builder runs.
44
59
  */
45
60
  export declare function applyThirdPartyAnthropicPolicy(request: UnifiedChatRequest, context: AnthropicClientPolicyContext, configService: any): Promise<void>;
61
+ /**
62
+ * Names of Anthropic-defined tools in this request: typed tools sent by an
63
+ * Anthropic client, and hosted web search requested over another protocol.
64
+ */
65
+ export declare function anthropicFixedToolNames(context: AnthropicClientPolicyContext): string[];
@@ -5,10 +5,14 @@
5
5
  * transformer chain without a bisect.
6
6
  */
7
7
  export type CachePrefixStage = "client" | "wire";
8
+ /**
9
+ * Routing headers that pin prompt-cache affinity. `x-client-request-id` is
10
+ * deliberately absent: claude-auth mints a fresh one per request (as Claude
11
+ * Code does), and Codex sets it equal to `thread-id`, which is tracked here.
12
+ */
8
13
  export type CacheAffinityHeaders = {
9
14
  sessionId?: string;
10
15
  threadId?: string;
11
- clientRequestId?: string;
12
16
  };
13
17
  export type CachePrefixSegment = {
14
18
  path: string;
@@ -25,6 +25,15 @@ export declare function buildClaudeBillingHeaderValue(messages: UnifiedMessage[]
25
25
  export declare function normalizeSystemToArray(request: UnifiedChatRequest): TextContent[];
26
26
  /** Drop any existing billing entry (dedupe) and prepend a fresh one at system[0]. */
27
27
  export declare function applyClaudeBillingSystemBlock(system: TextContent[], messages: UnifiedMessage[] | undefined): void;
28
+ /**
29
+ * Drop any existing billing entry (dedupe) and reserve system[0] for a fresh
30
+ * one, so applyClaudeSystemIdentity places identity right after it. The value
31
+ * samples the first user text as sent, which relocation may still change, so
32
+ * fill it afterwards with fillClaudeBillingSystemBlock.
33
+ */
34
+ export declare function reserveClaudeBillingSystemBlock(system: TextContent[]): TextContent;
35
+ /** Fill a reserved billing block; remove it when attribution is disabled. */
36
+ export declare function fillClaudeBillingSystemBlock(system: TextContent[], block: TextContent, messages: UnifiedMessage[] | undefined): void;
28
37
  /**
29
38
  * Insert SYSTEM_IDENTITY after the billing block (normally system[1], or
30
39
  * system[0] when attribution is disabled). Any remaining caller system
@@ -45,8 +54,13 @@ export declare function applyClaudeSystemIdentity(system: TextContent[]): void;
45
54
  * A no-op when there is no user message to attach the content to, so nothing
46
55
  * is silently dropped — the caller's system content stays in `system[]`
47
56
  * instead.
57
+ *
58
+ * Returns the inserted block unless the first user message has non-empty
59
+ * string content (the relocated text is then a standalone block a cache
60
+ * breakpoint can end on); non-empty string content is prefixed in place and
61
+ * returns undefined.
48
62
  */
49
- export declare function relocateForeignSystemContent(system: TextContent[], messages: UnifiedMessage[] | undefined): void;
63
+ export declare function relocateForeignSystemContent(system: TextContent[], messages: UnifiedMessage[] | undefined): TextContent | undefined;
50
64
  /**
51
65
  * Claude Code's OAuth validator expects tool names in the mcp_PascalCase
52
66
  * spelling used by the official CLI. Non-Claude-Code clients commonly send
@@ -57,8 +71,23 @@ export declare function prefixClaudeToolName(name: string): string;
57
71
  /** Restore a Claude Code tool name to the caller's original spelling. */
58
72
  export declare function unprefixClaudeToolName(name: string): string;
59
73
  /** Rewrite tool names in a Unified request in place for the OAuth wire path. */
60
- export declare function prefixClaudeToolNames(request: UnifiedChatRequest, nameMap?: Map<string, string>): void;
61
- /** Rewrite tool names in a Unified/OpenAI-shaped response in place. */
62
- export declare function unprefixClaudeToolNames(value: any, nameMap?: Map<string, string>): void;
63
- /** Rewrite one OpenAI SSE data payload's tool names. */
64
- export declare function unprefixClaudeToolNamesInSseData(value: any, nameMap?: Map<string, string>): void;
74
+ export declare function prefixClaudeToolNames(request: UnifiedChatRequest, nameMap?: Map<string, string>, fixedNames?: Iterable<string>): void;
75
+ /**
76
+ * Rewrite tool names in a response payload in place and report whether any
77
+ * name changed. Accepts both shapes a response takes after the provider leg:
78
+ * Unified/OpenAI (`choices[].message|delta.tool_calls`) and Anthropic
79
+ * Messages wire (`content[]` tool_use blocks of a message, or the
80
+ * `content_block_start` stream event that carries a tool_use block's name).
81
+ *
82
+ * With a request-local `nameMap`, only names CCR itself prefixed are restored,
83
+ * which keeps the operation idempotent: a caller's own `mcp__server__tool`
84
+ * name is never stripped a second time. Without one, fall back to the
85
+ * spelling heuristic.
86
+ */
87
+ export declare function unprefixClaudeToolNames(value: any, nameMap?: Map<string, string>): boolean;
88
+ /**
89
+ * Restore CCR-prefixed tool names in a JSON or SSE response. SSE events and
90
+ * JSON bodies without a renamed tool are forwarded byte-identical, so
91
+ * exact-protocol responses keep the provider's usage and framing untouched.
92
+ */
93
+ export declare function restoreClaudeToolNamesInResponse(response: Response, nameMap: Map<string, string>, logger?: any): Promise<Response>;
@@ -1,4 +1,5 @@
1
1
  import { UnifiedChatRequest } from "../types/llm";
2
+ import type { HostedWebSearchRequest } from "../routing/protocol-endpoints";
2
3
  export interface ResponsesCallIdMap {
3
4
  /** Original client call_id → sanitized id (and reverse). */
4
5
  forward: Map<string, string>;
@@ -170,6 +171,14 @@ export interface CodexIsolateConventionsOptions {
170
171
  * apply the exec/patch normalizers in one place so stream finalize, the
171
172
  * completed skeleton, and the non-stream JSON path cannot drift. */
172
173
  export declare function normalizeClientCustomToolInput(name: string | undefined, rawArguments: string, options?: CodexIsolateConventionsOptions): string;
174
+ /**
175
+ * Hosted web search options from a Responses `web_search` tool. Unified keeps
176
+ * only the `web_search` function projection, so destinations that run the
177
+ * search themselves (Anthropic server tools) read these request-locally.
178
+ */
179
+ export declare function hostedWebSearchFromResponsesTools(tools: unknown): HostedWebSearchRequest | undefined;
180
+ /** Approximate location fields shared by Responses and Chat search options. */
181
+ export declare function hostedUserLocation(location: any): Pick<HostedWebSearchRequest, "userLocation">;
173
182
  /** Unified Chat JSON → Responses API non-stream response. */
174
183
  export declare function unifiedResponseToResponses(chat: any, options?: {
175
184
  originalModel?: string;
@@ -185,10 +194,20 @@ export interface ResponsesStreamState {
185
194
  textClosed: boolean;
186
195
  textOutputIndex?: number;
187
196
  textContent: string;
197
+ /** Unified text length before the current text item (annotation offsets). */
198
+ textBase: number;
199
+ /** Unified text length emitted so far across all text items. */
200
+ totalTextLength: number;
201
+ textAnnotations: any[];
188
202
  closedTextItems: Array<{
189
203
  id: string;
190
204
  outputIndex: number;
191
205
  content: string;
206
+ annotations: any[];
207
+ }>;
208
+ webSearchCalls: Array<{
209
+ item: any;
210
+ outputIndex: number;
192
211
  }>;
193
212
  toolCalls: Map<number, {
194
213
  id: string;
@@ -39,6 +39,12 @@ export declare function unifiedToolTextOnly(content: unknown): string;
39
39
  export declare function unifiedToolHasMedia(content: unknown): boolean;
40
40
  /** Anthropic tool_result.content: string or (text|image|document)[]. */
41
41
  export declare function unifiedToolContentToAnthropic(content: unknown): string | any[];
42
+ /**
43
+ * Anthropic blocks for one Unified user content part. Empty when the part is
44
+ * not sent (empty text, image without URL, file without data or URL, unknown
45
+ * type), so callers placing cache breakpoints can skip it.
46
+ */
47
+ export declare function unifiedUserPartToAnthropic(part: any): any[];
42
48
  /**
43
49
  * Anthropic inbound tool_result.content → Unified tool content
44
50
  * (string or text/image_url/file parts).
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@caeliq/llms",
3
- "version": "1.0.70",
3
+ "version": "1.0.72",
4
4
  "description": "A universal LLM API transformation server",
5
5
  "main": "dist/cjs/server.cjs",
6
6
  "module": "dist/esm/server.mjs",
@@ -30,7 +30,7 @@
30
30
  ],
31
31
  "dependencies": {
32
32
  "@anthropic-ai/sdk": "^0.120.0",
33
- "@caeliq/ccr-shared": "^2.1.12",
33
+ "@caeliq/ccr-shared": "^2.1.14",
34
34
  "@cursor/sdk": "^1.0.32",
35
35
  "@fastify/cors": "^11.3.0",
36
36
  "@fastify/rate-limit": "^11.2.0",