@caeliq/llms 1.0.71 → 1.0.73
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/dist/cjs/server.cjs +235 -233
- package/dist/cjs/server.cjs.map +4 -4
- package/dist/cursor-sdk/inbound-session.d.ts +21 -0
- package/dist/cursor-sdk/model-selection.d.ts +23 -0
- package/dist/cursor-sdk/session.d.ts +16 -5
- package/dist/cursor-sdk/shared.d.ts +10 -1
- package/dist/cursor-sdk/turn-output.d.ts +2 -0
- package/dist/esm/server.mjs +239 -237
- package/dist/esm/server.mjs.map +4 -4
- package/dist/routing/protocol-endpoints.d.ts +33 -0
- package/dist/services/provider.d.ts +8 -2
- package/dist/session-registry.d.ts +30 -3
- package/dist/tests/anthropic.third-party-tool-names.d.ts +1 -0
- package/dist/tests/codex.bootstrap-buffer.d.ts +1 -0
- package/dist/tests/codex.model-catalog.d.ts +1 -0
- package/dist/tests/cursor-sdk.inbound-session.d.ts +1 -0
- package/dist/tests/cursor-sdk.interrupt-reentry.d.ts +1 -1
- package/dist/tests/cursor-sdk.model-remint.d.ts +1 -0
- package/dist/tests/cursor-sdk.model-selection.d.ts +1 -0
- package/dist/tests/cursor-sdk.on-delta-thinking.d.ts +1 -1
- package/dist/tests/cursor-sdk.runner-recovery.d.ts +1 -1
- package/dist/tests/cursor-sdk.scratch-report.d.ts +1 -1
- package/dist/tests/cursor-sdk.turn-coordination.d.ts +1 -1
- package/dist/tests/fallback.request-context.routes.d.ts +1 -0
- package/dist/tests/path-alias.build.d.ts +1 -0
- package/dist/tests/request-scoped-errors.d.ts +1 -0
- package/dist/tests/request-scoped-errors.routes.d.ts +1 -0
- package/dist/tests/responses.multi-agent.routes.d.ts +1 -0
- package/dist/tests/responses.orphan-delegation.d.ts +1 -0
- package/dist/tests/support/isolate-session-registry.d.ts +1 -0
- package/dist/tests/web-search.cross-protocol.d.ts +1 -0
- package/dist/transformer/claude-auth.transformer.d.ts +11 -2
- package/dist/transformer/codex.transformer.d.ts +18 -0
- package/dist/types/llm.d.ts +39 -2
- package/dist/utils/anthropic-client-policy.d.ts +8 -0
- package/dist/utils/claude-billing.d.ts +20 -5
- package/dist/utils/codex-bootstrap.d.ts +68 -0
- package/dist/utils/codex-model-catalog.d.ts +63 -0
- package/dist/utils/nested-agent.d.ts +4 -0
- package/dist/utils/openai.responses.util.d.ts +56 -1
- package/dist/utils/reasoning-effort.d.ts +3 -20
- package/dist/utils/request-scoped-errors.d.ts +92 -0
- package/package.json +3 -3
|
@@ -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. */
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { LLMProvider, RegisterProviderRequest, ModelRoute, RequestRouteInfo } from "../types/llm";
|
|
1
|
+
import { LLMProvider, RegisterProviderRequest, ModelRoute, ProviderUpdate, RequestRouteInfo } from "../types/llm";
|
|
2
2
|
import { ConfigService } from "./config";
|
|
3
3
|
import { TransformerService } from "./transformer";
|
|
4
4
|
export declare class ProviderService {
|
|
@@ -12,10 +12,16 @@ export declare class ProviderService {
|
|
|
12
12
|
private initializeFromProvidersArray;
|
|
13
13
|
/** Match TransformerService: instances used in provider use[] need the service logger. */
|
|
14
14
|
private attachTransformerLogger;
|
|
15
|
+
/**
|
|
16
|
+
* Store request-scoped error rules under the canonical key only, so an
|
|
17
|
+
* update under any spelling cannot be shadowed by a stale alias. Rules are
|
|
18
|
+
* validated here to surface config mistakes at registration time.
|
|
19
|
+
*/
|
|
20
|
+
private withCanonicalScopedErrorRules;
|
|
15
21
|
registerProvider(request: RegisterProviderRequest): LLMProvider;
|
|
16
22
|
getProviders(): LLMProvider[];
|
|
17
23
|
getProvider(name: string): LLMProvider | undefined;
|
|
18
|
-
updateProvider(id: string, updates:
|
|
24
|
+
updateProvider(id: string, updates: ProviderUpdate): LLMProvider | null;
|
|
19
25
|
deleteProvider(id: string): boolean;
|
|
20
26
|
toggleProvider(name: string, _enabled: boolean): boolean;
|
|
21
27
|
resolveModelRoute(modelName: string): RequestRouteInfo | null;
|
|
@@ -1,26 +1,42 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Persistent registry for every session identity CCR mints.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
4
|
+
* Several families, one mechanism — the stable lookup key already exists in each
|
|
5
5
|
* case (Zen conversation id, cursor buildSessionKey hash); only the minted
|
|
6
6
|
* value used to live in process memory and died on restart:
|
|
7
7
|
*
|
|
8
8
|
* - "zen": conversationKey -> x-opencode-session (ses_…)
|
|
9
9
|
* - "cursor": sessionKey -> { agentId, workspaceDir, model }
|
|
10
|
+
* - "cursor-inbound": hashed protocol conversation key -> internal Cursor id
|
|
11
|
+
* (cursor-sdk/inbound-session.ts; written on mint, claim, new user text,
|
|
12
|
+
* and at most hourly as a TTL refresh)
|
|
10
13
|
*
|
|
11
14
|
* The file lives under CCR_HOME (the mounted ~/.claude-code-router volume),
|
|
12
15
|
* so bindings survive both restarts and image rebuilds. Plain JSON: values
|
|
13
16
|
* are short strings, not blobs (unlike cursor-opencode-provider's pb.gz,
|
|
14
17
|
* which persists raw Cursor protocol state we never see — the SDK owns that).
|
|
15
18
|
*
|
|
16
|
-
* Synchronous API, tiny file (capped
|
|
17
|
-
* only — never on the
|
|
19
|
+
* Synchronous API, tiny file (entries capped per family), persistence on
|
|
20
|
+
* writes only — never on the read path.
|
|
18
21
|
*/
|
|
19
22
|
export type PersistedSession = {
|
|
20
23
|
/** The fixed CCR-minted id (ses_… for zen; SDK agentId for cursor). */
|
|
21
24
|
sessionId: string;
|
|
22
25
|
workspaceDir?: string;
|
|
23
26
|
model?: string;
|
|
27
|
+
/** `id|sorted params` from cursorModelFingerprint. Missing means pre-variant binding. */
|
|
28
|
+
modelFingerprint?: string;
|
|
29
|
+
/**
|
|
30
|
+
* Cursor inbound opening row: a follow-up turn claimed it. A repeated
|
|
31
|
+
* opening then needs a fresh id.
|
|
32
|
+
*/
|
|
33
|
+
progressed?: boolean;
|
|
34
|
+
/**
|
|
35
|
+
* Cursor inbound opening row that replaced an unclaimed opening of an
|
|
36
|
+
* identical earlier conversation. A follow-up cannot tell the two apart,
|
|
37
|
+
* so it gets a fresh agent instead of claiming this one.
|
|
38
|
+
*/
|
|
39
|
+
contested?: boolean;
|
|
24
40
|
updatedAt: number;
|
|
25
41
|
};
|
|
26
42
|
export declare const SESSION_REGISTRY_TTL_MS: number;
|
|
@@ -28,6 +44,17 @@ export declare const SESSION_REGISTRY_TTL_MS: number;
|
|
|
28
44
|
export declare function getPersistedSession(family: string, key: string, now?: number): PersistedSession | undefined;
|
|
29
45
|
/** Record a newly minted fixed id. Overwrites any prior binding. */
|
|
30
46
|
export declare function putPersistedSession(family: string, key: string, value: Omit<PersistedSession, "updatedAt">, now?: number): PersistedSession;
|
|
47
|
+
/**
|
|
48
|
+
* Apply several writes to one family with a single file rewrite: `put`
|
|
49
|
+
* entries are stored (overwriting), then `remove` keys are dropped.
|
|
50
|
+
*/
|
|
51
|
+
export declare function updatePersistedSessions(family: string, changes: {
|
|
52
|
+
put?: Array<{
|
|
53
|
+
key: string;
|
|
54
|
+
value: Omit<PersistedSession, "updatedAt">;
|
|
55
|
+
}>;
|
|
56
|
+
remove?: string[];
|
|
57
|
+
}, now?: number): void;
|
|
31
58
|
/** Forget a binding (session retire, Zen bucket re-roll). */
|
|
32
59
|
export declare function deletePersistedSession(family: string, key: string): void;
|
|
33
60
|
/** Drop expired bindings; returns the number pruned. */
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import "./support/isolate-session-registry";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
import "./support/isolate-session-registry";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import "./support/isolate-session-registry";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
import "./support/isolate-session-registry";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
import "./support/isolate-session-registry";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
import "./support/isolate-session-registry";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
import "./support/isolate-session-registry";
|
|
@@ -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 {};
|
|
@@ -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
|
|
71
|
-
*
|
|
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
|
/**
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { Transformer } from "../types/transformer";
|
|
2
|
+
import { type CodexBootstrapOptions } from "../utils/codex-bootstrap";
|
|
2
3
|
/**
|
|
3
4
|
* ChatGPT/Codex backend auth + Responses-wire constraints.
|
|
4
5
|
*
|
|
@@ -8,10 +9,26 @@ import { Transformer } from "../types/transformer";
|
|
|
8
9
|
* this transformer only stamps auth, Codex headers, `store: false`, and
|
|
9
10
|
* `stream: true`.
|
|
10
11
|
*/
|
|
12
|
+
export interface CodexTransformerOptions extends CodexBootstrapOptions {
|
|
13
|
+
streamBootstrapMaxFrames?: number;
|
|
14
|
+
streamBootstrapMaxBytes?: number;
|
|
15
|
+
streamBootstrapTimeoutMs?: number;
|
|
16
|
+
/**
|
|
17
|
+
* Hold pre-generation SSE frames uncommitted so an in-stream
|
|
18
|
+
* `server_is_overloaded` / quota rejection throws a fallback-eligible
|
|
19
|
+
* error *before* downstream headers commit, instead of reaching the
|
|
20
|
+
* client as a failed stream. Default false (opt-in).
|
|
21
|
+
*/
|
|
22
|
+
streamBootstrapBuffering?: boolean;
|
|
23
|
+
}
|
|
11
24
|
export declare class CodexTransformer implements Transformer {
|
|
25
|
+
static TransformerName: string;
|
|
12
26
|
name: string;
|
|
13
27
|
requestPhase: "headers";
|
|
14
28
|
logger?: any;
|
|
29
|
+
private readonly bootstrapOptions;
|
|
30
|
+
constructor(options?: CodexTransformerOptions);
|
|
31
|
+
private get bootstrapEnabled();
|
|
15
32
|
private streamIntent;
|
|
16
33
|
transformRequestIn(request: any, provider: any, context?: any): Promise<Record<string, any>>;
|
|
17
34
|
auth(request: any, provider: any): Promise<any>;
|
|
@@ -29,6 +46,7 @@ export declare class CodexTransformer implements Transformer {
|
|
|
29
46
|
req?: {
|
|
30
47
|
id?: string;
|
|
31
48
|
};
|
|
49
|
+
signal?: AbortSignal;
|
|
32
50
|
}): Promise<Response>;
|
|
33
51
|
private normalizeCodexTransport;
|
|
34
52
|
private ensureSseContentType;
|
package/dist/types/llm.d.ts
CHANGED
|
@@ -6,6 +6,7 @@ import type { ChatCompletionTool } from "openai/resources/chat/completions";
|
|
|
6
6
|
import type { Tool as AnthropicTool } from "@anthropic-ai/sdk/resources/messages";
|
|
7
7
|
import { Transformer } from "./transformer";
|
|
8
8
|
import type { ProviderTokenizerConfig } from "./tokenizer";
|
|
9
|
+
import type { RequestScopedErrorRule } from "../utils/request-scoped-errors";
|
|
9
10
|
export type TransformerConfigEntry = string | [string, Record<string, any>?];
|
|
10
11
|
export interface UrlCitation {
|
|
11
12
|
url: string;
|
|
@@ -18,6 +19,16 @@ export interface Annotation {
|
|
|
18
19
|
type: "url_citation";
|
|
19
20
|
url_citation?: UrlCitation;
|
|
20
21
|
}
|
|
22
|
+
/**
|
|
23
|
+
* A provider-executed web search (e.g. Anthropic's server `web_search`),
|
|
24
|
+
* surfaced so clients can render the call itself (Responses `web_search_call`).
|
|
25
|
+
* Internal: Chat Completions clients never receive it.
|
|
26
|
+
*/
|
|
27
|
+
export interface WebSearchCall {
|
|
28
|
+
id: string;
|
|
29
|
+
query: string;
|
|
30
|
+
status: "completed" | "failed";
|
|
31
|
+
}
|
|
21
32
|
export interface TextContent {
|
|
22
33
|
type: "text";
|
|
23
34
|
text: string;
|
|
@@ -137,6 +148,12 @@ export interface UnifiedChatRequest {
|
|
|
137
148
|
anthropic_output_config?: Record<string, any>;
|
|
138
149
|
anthropic_metadata?: Record<string, any>;
|
|
139
150
|
anthropic_stop_sequences?: string[];
|
|
151
|
+
/**
|
|
152
|
+
* Anthropic-defined (typed) tools for legacy direct claude-auth callers,
|
|
153
|
+
* like the other anthropic_* fields. Routed requests carry them in
|
|
154
|
+
* `protocolContext.anthropicSource.tools` so no other provider sees them.
|
|
155
|
+
*/
|
|
156
|
+
anthropic_tools?: Record<string, any>[];
|
|
140
157
|
reasoning_effort?: string;
|
|
141
158
|
/**
|
|
142
159
|
* Responses opaque `include` list (e.g. `reasoning.encrypted_content`).
|
|
@@ -168,6 +185,7 @@ export interface UnifiedChatResponse {
|
|
|
168
185
|
};
|
|
169
186
|
}>;
|
|
170
187
|
annotations?: Annotation[];
|
|
188
|
+
web_search_calls?: WebSearchCall[];
|
|
171
189
|
}
|
|
172
190
|
export interface StreamChunk {
|
|
173
191
|
id: string;
|
|
@@ -195,6 +213,7 @@ export interface StreamChunk {
|
|
|
195
213
|
thought_signature?: string;
|
|
196
214
|
}>;
|
|
197
215
|
annotations?: Annotation[];
|
|
216
|
+
web_search_calls?: WebSearchCall[];
|
|
198
217
|
};
|
|
199
218
|
finish_reason?: string | null;
|
|
200
219
|
}>;
|
|
@@ -241,6 +260,12 @@ export interface LLMProvider {
|
|
|
241
260
|
models: string[];
|
|
242
261
|
/** Optional GCP / Antigravity project id (provider-specific). */
|
|
243
262
|
project_id?: string;
|
|
263
|
+
/**
|
|
264
|
+
* Request-scoped error rules for this provider (CLIProxyAPI port).
|
|
265
|
+
* Evaluated before global rules; first match decides stop vs continue.
|
|
266
|
+
* The provider service stores rules only under this canonical key.
|
|
267
|
+
*/
|
|
268
|
+
request_scoped_errors?: RequestScopedErrorRule[];
|
|
244
269
|
transformer?: {
|
|
245
270
|
[key: string]: {
|
|
246
271
|
use?: Transformer[];
|
|
@@ -250,7 +275,18 @@ export interface LLMProvider {
|
|
|
250
275
|
passthrough?: any;
|
|
251
276
|
};
|
|
252
277
|
}
|
|
253
|
-
|
|
278
|
+
/**
|
|
279
|
+
* Accepted input spellings of the request-scoped error rule list. The
|
|
280
|
+
* provider service folds them into `request_scoped_errors`.
|
|
281
|
+
*/
|
|
282
|
+
export interface RequestScopedErrorsCarrier {
|
|
283
|
+
request_scoped_errors?: RequestScopedErrorRule[];
|
|
284
|
+
requestScopedErrors?: RequestScopedErrorRule[];
|
|
285
|
+
"request-scoped-errors"?: RequestScopedErrorRule[];
|
|
286
|
+
}
|
|
287
|
+
export type RegisterProviderRequest = LLMProvider & RequestScopedErrorsCarrier;
|
|
288
|
+
/** Provider update payload; any rule-list spelling replaces the stored rules. */
|
|
289
|
+
export type ProviderUpdate = Partial<LLMProvider> & RequestScopedErrorsCarrier;
|
|
254
290
|
export interface ModelRoute {
|
|
255
291
|
provider: string;
|
|
256
292
|
model: string;
|
|
@@ -261,7 +297,8 @@ export interface RequestRouteInfo {
|
|
|
261
297
|
originalModel: string;
|
|
262
298
|
targetModel: string;
|
|
263
299
|
}
|
|
264
|
-
|
|
300
|
+
/** Request-scoped error rules use any RequestScopedErrorsCarrier spelling. */
|
|
301
|
+
export interface ConfigProvider extends RequestScopedErrorsCarrier {
|
|
265
302
|
name: string;
|
|
266
303
|
api_base_url: string;
|
|
267
304
|
api_key: string;
|
|
@@ -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
|
/**
|
|
@@ -55,3 +58,8 @@ export declare function applyNativeClaudeOAuthCacheTtl(body: any, context: Anthr
|
|
|
55
58
|
* before the provider's Anthropic body builder runs.
|
|
56
59
|
*/
|
|
57
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[];
|
|
@@ -71,8 +71,23 @@ export declare function prefixClaudeToolName(name: string): string;
|
|
|
71
71
|
/** Restore a Claude Code tool name to the caller's original spelling. */
|
|
72
72
|
export declare function unprefixClaudeToolName(name: string): string;
|
|
73
73
|
/** Rewrite tool names in a Unified request in place for the OAuth wire path. */
|
|
74
|
-
export declare function prefixClaudeToolNames(request: UnifiedChatRequest, nameMap?: Map<string, string>): void;
|
|
75
|
-
/**
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
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>;
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Codex stream bootstrap buffering (CLIProxyAPI `stream-bootstrap-buffering` port).
|
|
3
|
+
*
|
|
4
|
+
* The ChatGPT backend smuggles overload/quota rejections *inside* an HTTP 200
|
|
5
|
+
* SSE stream — right after the handshake events — instead of returning a
|
|
6
|
+
* retryable status on the wire. Once downstream headers are committed that
|
|
7
|
+
* failure can only be delivered to the client; holding the pre-generation
|
|
8
|
+
* bootstrap frames uncommitted keeps the window open for a transparent
|
|
9
|
+
* fallback to the next model.
|
|
10
|
+
*
|
|
11
|
+
* Held (never released on their own): handshake frames
|
|
12
|
+
* (`response.created`, `response.in_progress`, `response.queued`), `*.added`
|
|
13
|
+
* announcements, empty `output_text.delta` heartbeats, SSE comments, `event:`
|
|
14
|
+
* lines and blank separators. Anything else — text deltas, tool-call deltas,
|
|
15
|
+
* `*.done` / `*.completed` / `*.failed` / `error` frames, or an unparsable
|
|
16
|
+
* `data:` line — releases the buffer immediately. The hold is bounded by a
|
|
17
|
+
* frame budget and a byte budget, never by nothing.
|
|
18
|
+
*/
|
|
19
|
+
export interface CodexBootstrapOptions {
|
|
20
|
+
/** Max held `data:` lines before release. Default 48. */
|
|
21
|
+
maxFrames?: number;
|
|
22
|
+
/** Max held bytes before release. Default 1 MiB. */
|
|
23
|
+
maxBytes?: number;
|
|
24
|
+
/**
|
|
25
|
+
* Max hold time in ms before release. Default 0 (unlimited — the budget
|
|
26
|
+
* bounds what is held, not how long). Evaluated between reads; a peer that
|
|
27
|
+
* stops mid-line is still bounded by the request context, not this timer.
|
|
28
|
+
*/
|
|
29
|
+
timeoutMs?: number;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Capacity failure classes, as Codex CLI distinguishes them: the server is
|
|
33
|
+
* overloaded (503), the request rate is limited (429), or the account's quota
|
|
34
|
+
* or plan does not cover it (429). Each is worth another model; a request
|
|
35
|
+
* failure is not.
|
|
36
|
+
*/
|
|
37
|
+
export type CodexOverloadKind = "overload" | "rate_limit" | "quota";
|
|
38
|
+
export type CodexBootstrapRelease = "generated" | "budget" | "timeout" | "ended" | "overload";
|
|
39
|
+
export interface CodexBootstrapResult {
|
|
40
|
+
/** Replayable response: held bytes followed by the live remainder. */
|
|
41
|
+
response: Response;
|
|
42
|
+
overloaded: boolean;
|
|
43
|
+
overloadKind?: CodexOverloadKind;
|
|
44
|
+
/** Raw bootstrap text that carried the overload signal (truncated). */
|
|
45
|
+
overloadText?: string;
|
|
46
|
+
/** Structured error fields retained for internal request-scoped matching. */
|
|
47
|
+
overloadErrorText?: string;
|
|
48
|
+
/** Retry-After value (seconds or HTTP date) the failed event advised. */
|
|
49
|
+
overloadRetryAfter?: string;
|
|
50
|
+
heldBytes: number;
|
|
51
|
+
heldFrames: number;
|
|
52
|
+
releasedBy: CodexBootstrapRelease;
|
|
53
|
+
}
|
|
54
|
+
export declare const DEFAULT_BOOTSTRAP_MAX_FRAMES = 48;
|
|
55
|
+
export declare const DEFAULT_BOOTSTRAP_MAX_BYTES: number;
|
|
56
|
+
/** Capacity class of a structured Responses error; `message` is ignored. */
|
|
57
|
+
export declare function classifyCodexError(error: {
|
|
58
|
+
code?: unknown;
|
|
59
|
+
type?: unknown;
|
|
60
|
+
message?: unknown;
|
|
61
|
+
}): CodexOverloadKind | undefined;
|
|
62
|
+
/**
|
|
63
|
+
* Buffer the Codex SSE bootstrap. Never throws on upstream content: overload
|
|
64
|
+
* is reported on the result so the caller can raise a fallback-eligible error
|
|
65
|
+
* *before* downstream headers commit. The returned response replays held
|
|
66
|
+
* bytes first, then the untouched remainder of the original stream.
|
|
67
|
+
*/
|
|
68
|
+
export declare function bufferCodexBootstrapStream(response: Response, options?: CodexBootstrapOptions, signal?: AbortSignal): Promise<CodexBootstrapResult>;
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OpenAI model metadata imported from Codex CLI's bundled catalog
|
|
3
|
+
* (codex-rs `models-manager/models.json`), so CCR sends what Codex sends:
|
|
4
|
+
*
|
|
5
|
+
* - reasoning effort: only the model's supported levels. `ultra` is a picker
|
|
6
|
+
* alias and never reaches the wire (`ModelInfo::resolve_reasoning_effort`).
|
|
7
|
+
* - Responses Lite: the request shape Codex uses for `use_responses_lite`
|
|
8
|
+
* models (`core/src/client.rs::build_responses_request`).
|
|
9
|
+
* - verbosity: only models with `support_verbosity`.
|
|
10
|
+
*
|
|
11
|
+
* Refresh the table when Codex adds or retires catalog models.
|
|
12
|
+
*/
|
|
13
|
+
import { type ReasoningSummaryLevel } from "./reasoning-effort";
|
|
14
|
+
import type { ThinkLevel } from "../types/llm";
|
|
15
|
+
export type CodexTextVerbosity = "low" | "medium" | "high";
|
|
16
|
+
export interface CodexModelSpec {
|
|
17
|
+
/** `supported_reasoning_levels`, lowest first. */
|
|
18
|
+
efforts: readonly ThinkLevel[];
|
|
19
|
+
/** `multi_agent_reasoning_effort`: what `ultra` resolves to, when set. */
|
|
20
|
+
ultraEffort?: ThinkLevel;
|
|
21
|
+
/** `use_responses_lite`. */
|
|
22
|
+
responsesLite: boolean;
|
|
23
|
+
/** `support_verbosity`. */
|
|
24
|
+
verbosity: boolean;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* GPT-6 Luna slugs (`gpt-6-luna`, `gpt-6.1-luna`, `openai/gpt-6-luna`,
|
|
28
|
+
* `codex,gpt-6.1-luna`). Anchored so `gpt-6-sol` / `gpt-6-astra` /
|
|
29
|
+
* `gpt-5.6-luna` do not match.
|
|
30
|
+
*/
|
|
31
|
+
export declare function isGpt6LunaModel(model: unknown): boolean;
|
|
32
|
+
/**
|
|
33
|
+
* Catalog metadata for a model id, or undefined for models Codex does not
|
|
34
|
+
* list. GPT-6 slugs newer than the table get the family's shape (Luna tops
|
|
35
|
+
* out at `max`), so a new minor release keeps working before a refresh.
|
|
36
|
+
*/
|
|
37
|
+
export declare function codexModelSpec(model: unknown): CodexModelSpec | undefined;
|
|
38
|
+
/**
|
|
39
|
+
* The effort a catalog model is sent. `ultra` follows Codex: the model's
|
|
40
|
+
* multi-agent effort, else `max`, else the highest level below `ultra`. Any
|
|
41
|
+
* other unsupported level moves to the nearest end of the supported range
|
|
42
|
+
* (`none` / `minimal` → the lowest). Unknown tokens and unlisted models pass
|
|
43
|
+
* through unchanged.
|
|
44
|
+
*/
|
|
45
|
+
export declare function resolveCodexReasoningEffort(model: unknown, effort: ThinkLevel | undefined): ThinkLevel | undefined;
|
|
46
|
+
/**
|
|
47
|
+
* Apply `resolveCodexReasoningEffort` to a Responses/Unified request in
|
|
48
|
+
* place. Covers convert (`openai-responses`) and same-protocol wire-keep
|
|
49
|
+
* (`codex`). A disabled-reasoning request raised to a supported level is
|
|
50
|
+
* re-enabled, since the model cannot run without reasoning.
|
|
51
|
+
*/
|
|
52
|
+
export declare function applyCodexReasoningEffort(request: {
|
|
53
|
+
model?: unknown;
|
|
54
|
+
reasoning?: {
|
|
55
|
+
effort?: unknown;
|
|
56
|
+
enabled?: boolean;
|
|
57
|
+
} | null;
|
|
58
|
+
}): void;
|
|
59
|
+
/**
|
|
60
|
+
* `text.verbosity` implied by `REASONING_AUTO_SUMMARY`: detailed thinking
|
|
61
|
+
* pairs with verbose answers, concise with terse ones.
|
|
62
|
+
*/
|
|
63
|
+
export declare function verbosityForReasoningSummary(summary: ReasoningSummaryLevel | undefined): CodexTextVerbosity | undefined;
|
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
export declare function firstUserText(request: unknown): string;
|
|
3
3
|
export declare function isHarnessUserNoise(text: string): boolean;
|
|
4
4
|
export declare function userMessageTextParts(content: unknown): string[];
|
|
5
|
+
/** Substantive user turns, in order. Reminders and caveats are not identity. */
|
|
6
|
+
export declare function substantiveUserTexts(request: unknown): string[];
|
|
5
7
|
/**
|
|
6
8
|
* First user text that distinguishes a worker transcript.
|
|
7
9
|
* Shared reminder/caveat preambles are skipped so parallel Tasks do not collide.
|
|
@@ -9,6 +11,8 @@ export declare function userMessageTextParts(content: unknown): string[];
|
|
|
9
11
|
export declare function firstSubstantiveUserText(request: unknown): string;
|
|
10
12
|
/** Statusline / spinner polls — must not supersede or become a cache baseline. */
|
|
11
13
|
export declare function isStatuslinePollTurn(request: unknown): boolean;
|
|
14
|
+
/** Explicit worker-fork boundary, including inside inherited history. */
|
|
15
|
+
export declare function isForkOpeningText(text: string): boolean;
|
|
12
16
|
/**
|
|
13
17
|
* Nested/worker agent on any inbound protocol.
|
|
14
18
|
*
|