@caeliq/llms 1.0.55 → 1.0.57
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +102 -12
- package/dist/api/middleware.d.ts +9 -0
- package/dist/api/routes.d.ts +15 -0
- package/dist/cjs/server.cjs +238 -230
- package/dist/cjs/server.cjs.map +4 -4
- package/dist/cursor-sdk/events-to-sse.d.ts +113 -0
- package/dist/cursor-sdk/hooks-template.d.ts +1 -0
- package/dist/cursor-sdk/prompt.d.ts +29 -0
- package/dist/cursor-sdk/runner.d.ts +11 -0
- package/dist/cursor-sdk/send.d.ts +9 -0
- package/dist/cursor-sdk/session.d.ts +146 -0
- package/dist/cursor-sdk/shared.d.ts +14 -0
- package/dist/cursor-sdk/tools.d.ts +4 -0
- package/dist/cursor-sdk/usage.d.ts +28 -0
- package/dist/esm/server.mjs +233 -225
- package/dist/esm/server.mjs.map +4 -4
- package/dist/index.d.ts +2 -0
- package/dist/plugins/index.d.ts +4 -0
- package/dist/plugins/output/console-handler.d.ts +23 -0
- package/dist/plugins/output/index.d.ts +29 -0
- package/dist/plugins/output/output-manager.d.ts +110 -0
- package/dist/plugins/output/temp-file-handler.d.ts +53 -0
- package/dist/plugins/output/types.d.ts +157 -0
- package/dist/plugins/output/webhook-handler.d.ts +37 -0
- package/dist/plugins/plugin-manager.d.ts +62 -0
- package/dist/plugins/token-speed.d.ts +22 -0
- package/dist/plugins/types.d.ts +25 -0
- package/dist/server.d.ts +60 -0
- package/dist/services/config.d.ts +32 -0
- package/dist/services/provider.d.ts +34 -0
- package/dist/services/tokenizer.d.ts +44 -0
- package/dist/services/transformer.d.ts +28 -0
- package/dist/tests/anthropic.stream-boundaries.d.ts +1 -0
- package/dist/tests/anthropic.stream-cancel.d.ts +1 -0
- package/dist/tests/antigravity.claude-tool-schema.d.ts +1 -0
- package/dist/tests/antigravity.endpoint-fallback.d.ts +1 -0
- package/dist/tests/cache-control.strip.d.ts +1 -0
- package/dist/tests/cache-paths.integration.d.ts +1 -0
- package/dist/tests/claude-auth.beta-headers.d.ts +1 -0
- package/dist/tests/codex-auth.reliability.d.ts +1 -0
- package/dist/tests/cursor-sdk.cancel.d.ts +1 -0
- package/dist/tests/cursor-sdk.on-delta-thinking.d.ts +1 -0
- package/dist/tests/cursor-sdk.progress-only.d.ts +1 -0
- package/dist/tests/cursor-sdk.runner-recovery.d.ts +1 -0
- package/dist/tests/cursor-sdk.send.d.ts +1 -0
- package/dist/tests/cursor-sdk.stream-error.d.ts +1 -0
- package/dist/tests/cursor-sdk.thinking-signature.d.ts +1 -0
- package/dist/tests/cursor-sdk.usage.d.ts +1 -0
- package/dist/tests/deepseek.reasoning.d.ts +1 -0
- package/dist/tests/gemini.abnormal-finish.d.ts +1 -0
- package/dist/tests/gemini.dual-dialect-request.d.ts +1 -0
- package/dist/tests/gemini.function-call-signatures.d.ts +1 -0
- package/dist/tests/gemini.parity.d.ts +1 -0
- package/dist/tests/gemini.thinking-effort.d.ts +1 -0
- package/dist/tests/gemini.thought-signature-roundtrip.d.ts +1 -0
- package/dist/tests/opencode-headers.no-provider-retry.d.ts +1 -0
- package/dist/tests/thinking-sequencer.dual-dialect.d.ts +1 -0
- package/dist/tests/transformer-service.endpoints.d.ts +1 -0
- package/dist/tests/upstream-ports.smoke.d.ts +1 -0
- package/dist/tokenizer/api-tokenizer.d.ts +45 -0
- package/dist/tokenizer/huggingface-tokenizer.d.ts +52 -0
- package/dist/tokenizer/tiktoken-tokenizer.d.ts +20 -0
- package/dist/transformer/anthropic.transformer.d.ts +22 -0
- package/dist/transformer/antigravity-auth.transformer.d.ts +15 -0
- package/dist/transformer/cerebras.transformer.d.ts +16 -0
- package/dist/transformer/chrome-on-device.transformer.d.ts +7 -0
- package/dist/transformer/claude-auth.transformer.d.ts +25 -0
- package/dist/transformer/cleancache.transformer.d.ts +6 -0
- package/dist/transformer/codex.transformer.d.ts +61 -0
- package/dist/transformer/cursor-sdk.transformer.d.ts +23 -0
- package/dist/transformer/customparams.transformer.d.ts +30 -0
- package/dist/transformer/deepseek.transformer.d.ts +7 -0
- package/dist/transformer/enhancetool.transformer.d.ts +6 -0
- package/dist/transformer/extrathinktag.transformer.d.ts +10 -0
- package/dist/transformer/forcereasoning.transformer.d.ts +8 -0
- package/dist/transformer/gemini.transformer.d.ts +15 -0
- package/dist/transformer/groq.transformer.d.ts +7 -0
- package/dist/transformer/index.d.ts +65 -0
- package/dist/transformer/maxcompletiontokens.transformer.d.ts +6 -0
- package/dist/transformer/maxtoken.transformer.d.ts +9 -0
- package/dist/transformer/mistral.transformer.d.ts +25 -0
- package/dist/transformer/openai.responses.transformer.d.ts +13 -0
- package/dist/transformer/openai.transformer.d.ts +52 -0
- package/dist/transformer/opencode-headers.transformer.d.ts +30 -0
- package/dist/transformer/openrouter.transformer.d.ts +10 -0
- package/dist/transformer/qwen-auth.transformer.d.ts +9 -0
- package/dist/transformer/reasoning.transformer.d.ts +10 -0
- package/dist/transformer/sampling.transformer.d.ts +13 -0
- package/dist/transformer/streamoptions.transformer.d.ts +6 -0
- package/dist/transformer/tooluse.transformer.d.ts +7 -0
- package/dist/transformer/vercel.transformer.d.ts +11 -0
- package/dist/transformer/vertex-claude.transformer.d.ts +9 -0
- package/dist/transformer/vertex-gemini.transformer.d.ts +12 -0
- package/dist/transformer/vertex-openai.transformer.d.ts +19 -0
- package/dist/types/llm.d.ts +255 -0
- package/dist/types/transformer.d.ts +23 -0
- package/dist/utils/antigravity-auth.d.ts +75 -0
- package/dist/utils/auth-recovery.d.ts +2 -0
- package/dist/utils/cache.d.ts +14 -0
- package/dist/utils/cacheControl.d.ts +44 -0
- package/dist/utils/claude-auth.d.ts +22 -0
- package/dist/utils/codex-auth.d.ts +33 -0
- package/dist/utils/converter.d.ts +11 -0
- package/dist/utils/cursor-auth.d.ts +3 -0
- package/dist/utils/deepseek.util.d.ts +28 -0
- package/dist/utils/gemini-cache.d.ts +8 -0
- package/dist/utils/gemini-thinking.d.ts +66 -0
- package/dist/utils/gemini.util.d.ts +43 -0
- package/dist/utils/google.util.d.ts +160 -0
- package/dist/utils/image.d.ts +1 -0
- package/dist/utils/mistral.util.d.ts +14 -0
- package/dist/utils/openai.util.d.ts +17 -0
- package/dist/utils/qwen-auth.d.ts +13 -0
- package/dist/utils/redact.d.ts +30 -0
- package/dist/utils/request.d.ts +4 -0
- package/dist/utils/retry.d.ts +27 -0
- package/dist/utils/router.d.ts +42 -0
- package/dist/utils/schema.d.ts +46 -0
- package/dist/utils/sse/SSEParser.transform.d.ts +6 -0
- package/dist/utils/sse/SSESerializer.transform.d.ts +3 -0
- package/dist/utils/sse/index.d.ts +3 -0
- package/dist/utils/sse/rewriteStream.d.ts +9 -0
- package/dist/utils/stream.d.ts +11 -0
- package/dist/utils/thinking.d.ts +33 -0
- package/dist/utils/thought-signature-cache.d.ts +34 -0
- package/dist/utils/toolArgumentsParser.d.ts +8 -0
- package/dist/utils/vertex-claude.util.d.ts +47 -0
- package/package.json +3 -3
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { UnifiedChatRequest, UnifiedMessage, UnifiedTool } from "../types/llm";
|
|
2
|
+
type CacheableLocation = {
|
|
3
|
+
kind: "message";
|
|
4
|
+
messageIndex: number;
|
|
5
|
+
} | {
|
|
6
|
+
kind: "content";
|
|
7
|
+
messageIndex: number;
|
|
8
|
+
contentIndex: number;
|
|
9
|
+
} | {
|
|
10
|
+
kind: "tool";
|
|
11
|
+
toolIndex: number;
|
|
12
|
+
};
|
|
13
|
+
export interface CacheIntent {
|
|
14
|
+
sessionKey?: string;
|
|
15
|
+
breakpoints: CacheableLocation[];
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Strip cache_control from a single object (shallow clone).
|
|
19
|
+
*/
|
|
20
|
+
export declare function stripCacheControl<T extends Record<string, any>>(obj: T): T;
|
|
21
|
+
/**
|
|
22
|
+
* Strip cache_control from all messages and their content items.
|
|
23
|
+
*/
|
|
24
|
+
export declare function stripMessagesCacheControl(messages: UnifiedMessage[]): UnifiedMessage[];
|
|
25
|
+
/**
|
|
26
|
+
* Strip cache_control from tool definitions. Anthropic → Unified preserves
|
|
27
|
+
* cache_control on tools so the Anthropic round-trip keeps prompt-cache hits,
|
|
28
|
+
* but non-Anthropic providers reject it on tool definitions.
|
|
29
|
+
*/
|
|
30
|
+
export declare function stripToolsCacheControl(tools: UnifiedTool[] | undefined): UnifiedTool[] | undefined;
|
|
31
|
+
export declare function deriveCacheSessionKey(context: any, request: UnifiedChatRequest): string | undefined;
|
|
32
|
+
export declare function selectCacheBreakpoints(request: UnifiedChatRequest, options: {
|
|
33
|
+
maxBreakpoints: number;
|
|
34
|
+
includeTools?: boolean;
|
|
35
|
+
}): CacheIntent;
|
|
36
|
+
export declare function applyAnthropicPromptCaching(request: UnifiedChatRequest, options?: {
|
|
37
|
+
maxBreakpoints?: number;
|
|
38
|
+
includeTools?: boolean;
|
|
39
|
+
}): UnifiedChatRequest;
|
|
40
|
+
export declare function applyRawAnthropicPromptCaching<T extends Record<string, any>>(request: T, options?: {
|
|
41
|
+
maxBreakpoints?: number;
|
|
42
|
+
}): T;
|
|
43
|
+
export declare function applyQwenPromptCaching(request: UnifiedChatRequest): UnifiedChatRequest;
|
|
44
|
+
export {};
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
declare const CLAUDE_AUTH_FILE: string;
|
|
2
|
+
declare const OAUTH_CONFIG: {
|
|
3
|
+
client_id: string;
|
|
4
|
+
authorization_endpoint: string;
|
|
5
|
+
token_endpoint: string;
|
|
6
|
+
scope: string;
|
|
7
|
+
};
|
|
8
|
+
export interface ClaudeTokens {
|
|
9
|
+
access_token: string;
|
|
10
|
+
refresh_token?: string;
|
|
11
|
+
id_token?: string;
|
|
12
|
+
token_type: string;
|
|
13
|
+
scope?: string;
|
|
14
|
+
expires_at: number;
|
|
15
|
+
last_refresh?: number;
|
|
16
|
+
}
|
|
17
|
+
export declare function loadTokens(): ClaudeTokens | null;
|
|
18
|
+
export declare function saveTokens(tokens: ClaudeTokens): void;
|
|
19
|
+
export declare function isTokenExpired(tokens: ClaudeTokens, leewaySeconds?: number): boolean;
|
|
20
|
+
export declare function refreshTokens(refreshToken: string): Promise<ClaudeTokens>;
|
|
21
|
+
export declare function getValidAccessToken(): Promise<ClaudeTokens>;
|
|
22
|
+
export { OAUTH_CONFIG, CLAUDE_AUTH_FILE };
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
declare const OAUTH_CONFIG: {
|
|
2
|
+
client_id: string;
|
|
3
|
+
token_endpoint: string;
|
|
4
|
+
};
|
|
5
|
+
export interface CodexTokens {
|
|
6
|
+
access_token: string;
|
|
7
|
+
refresh_token?: string;
|
|
8
|
+
id_token?: string;
|
|
9
|
+
token_type: string;
|
|
10
|
+
scope?: string;
|
|
11
|
+
expires_at: number;
|
|
12
|
+
account_id?: string;
|
|
13
|
+
last_refresh?: number;
|
|
14
|
+
}
|
|
15
|
+
export interface CodexOAuthAuth {
|
|
16
|
+
mode: "oauth";
|
|
17
|
+
token: string;
|
|
18
|
+
accountId?: string;
|
|
19
|
+
isFedramp: boolean;
|
|
20
|
+
}
|
|
21
|
+
export interface RefreshOptions {
|
|
22
|
+
force?: boolean;
|
|
23
|
+
previousAccessToken?: string;
|
|
24
|
+
expectedAccountId?: string;
|
|
25
|
+
}
|
|
26
|
+
declare function getAuthFilePath(): string;
|
|
27
|
+
export declare function loadTokens(): CodexTokens | null;
|
|
28
|
+
export declare function saveTokens(tokens: CodexTokens): void;
|
|
29
|
+
export declare function isTokenExpired(tokens: CodexTokens, leewaySeconds?: number): boolean;
|
|
30
|
+
export declare function refreshTokens(refreshToken: string): Promise<CodexTokens>;
|
|
31
|
+
export declare function getValidAccessToken(options?: RefreshOptions): Promise<CodexTokens>;
|
|
32
|
+
export declare function toCodexOAuthAuth(tokens: CodexTokens): CodexOAuthAuth;
|
|
33
|
+
export { getAuthFilePath, OAUTH_CONFIG };
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { ChatCompletionTool } from "openai/resources/chat/completions";
|
|
2
|
+
import type { Tool as AnthropicTool } from "@anthropic-ai/sdk/resources/messages";
|
|
3
|
+
import { UnifiedChatRequest, UnifiedTool, OpenAIChatRequest, AnthropicChatRequest, ConversionOptions } from "../types/llm";
|
|
4
|
+
export declare function convertToolsToOpenAI(tools: UnifiedTool[]): ChatCompletionTool[];
|
|
5
|
+
export declare function convertToolsToAnthropic(tools: UnifiedTool[]): AnthropicTool[];
|
|
6
|
+
export declare function convertToolsFromOpenAI(tools: ChatCompletionTool[]): UnifiedTool[];
|
|
7
|
+
export declare function convertToolsFromAnthropic(tools: AnthropicTool[]): UnifiedTool[];
|
|
8
|
+
export declare function convertToOpenAI(request: UnifiedChatRequest): OpenAIChatRequest;
|
|
9
|
+
export declare function convertFromOpenAI(request: OpenAIChatRequest): UnifiedChatRequest;
|
|
10
|
+
export declare function convertFromAnthropic(request: AnthropicChatRequest): UnifiedChatRequest;
|
|
11
|
+
export declare function convertRequest(request: OpenAIChatRequest | AnthropicChatRequest | UnifiedChatRequest, options: ConversionOptions): OpenAIChatRequest | AnthropicChatRequest;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { LLMProvider, UnifiedChatRequest, UnifiedMessage } from "../types/llm";
|
|
2
|
+
import { TransformerContext } from "../types/transformer";
|
|
3
|
+
type ToolCallLike = NonNullable<UnifiedMessage["tool_calls"]>[number];
|
|
4
|
+
type MessageLike = Pick<UnifiedMessage, "role" | "content" | "thinking" | "tool_calls" | "tool_call_id" | "reasoning_content"> & {
|
|
5
|
+
name?: string;
|
|
6
|
+
};
|
|
7
|
+
type AssistantResponseRecorder = {
|
|
8
|
+
content: string;
|
|
9
|
+
reasoning: string;
|
|
10
|
+
toolCalls: Map<number, ToolCallLike>;
|
|
11
|
+
};
|
|
12
|
+
export declare function assistantNeedsReasoningForToolContext(message: MessageLike, priorMessages: MessageLike[]): boolean;
|
|
13
|
+
export declare function isDeepSeekThinkingRequest(request: Pick<UnifiedChatRequest, "model" | "thinking" | "enable_thinking" | "reasoning">, provider?: Pick<LLMProvider, "name" | "baseUrl">): boolean;
|
|
14
|
+
export declare function buildReasoningCacheNamespace(request: Pick<UnifiedChatRequest, "model" | "thinking" | "enable_thinking" | "reasoning">, provider?: Pick<LLMProvider, "name" | "baseUrl">): string;
|
|
15
|
+
export declare function prepareReasoningReplay(request: UnifiedChatRequest, provider: Pick<LLMProvider, "name" | "baseUrl"> | undefined, context?: TransformerContext): {
|
|
16
|
+
restoredFromCache: number;
|
|
17
|
+
restoredFromThinking: number;
|
|
18
|
+
};
|
|
19
|
+
export declare function hasDeepSeekReasoningContext(context?: TransformerContext): boolean;
|
|
20
|
+
export declare function recordReasoningResponseMessage(message: MessageLike | null | undefined, context?: TransformerContext): number;
|
|
21
|
+
export declare function createAssistantResponseRecorder(): AssistantResponseRecorder;
|
|
22
|
+
export declare function appendAssistantResponseDelta(recorder: AssistantResponseRecorder, delta: {
|
|
23
|
+
content?: unknown;
|
|
24
|
+
reasoning_content?: unknown;
|
|
25
|
+
tool_calls?: Array<Record<string, any>>;
|
|
26
|
+
}): void;
|
|
27
|
+
export declare function buildAssistantResponseMessage(recorder: AssistantResponseRecorder): MessageLike | null;
|
|
28
|
+
export {};
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export declare function attachGeminiCachedContent(options: {
|
|
2
|
+
body: Record<string, any>;
|
|
3
|
+
modelResource: string;
|
|
4
|
+
createUrl: string | URL;
|
|
5
|
+
headers: Record<string, string | undefined>;
|
|
6
|
+
logger?: any;
|
|
7
|
+
}): Promise<Record<string, any>>;
|
|
8
|
+
export declare function clearGeminiCachedContentForTests(): void;
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { UnifiedChatRequest } from "../types/llm";
|
|
2
|
+
/**
|
|
3
|
+
* Translate Claude Code's effort setting into the thinking dialect each Gemini
|
|
4
|
+
* family expects.
|
|
5
|
+
*
|
|
6
|
+
* Claude Code is authoritative: the effort it sends (`output_config.effort`,
|
|
7
|
+
* surfaced as `reasoning.effort`) decides how much the model thinks. The model
|
|
8
|
+
* id is never rewritten — a user who configured `gemini-3-pro-low` keeps talking
|
|
9
|
+
* to `gemini-3-pro-low`; only the request's thinkingConfig changes. Antigravity
|
|
10
|
+
* tier-suffixed ids accept the whole level set for their family, so the suffix
|
|
11
|
+
* caps nothing here (it does still select the upstream quota bucket).
|
|
12
|
+
*
|
|
13
|
+
* Two upstream dialects, never mixed — sending thinkingLevel and thinkingBudget
|
|
14
|
+
* in one request is a documented 400:
|
|
15
|
+
*
|
|
16
|
+
* - level (Gemini 3+): thinkingLevel, per-family value set
|
|
17
|
+
* - budget (Gemini 2.5, Claude served through Antigravity): thinkingBudget in tokens
|
|
18
|
+
*/
|
|
19
|
+
/** Upstream `thinkingLevel` values, ascending. */
|
|
20
|
+
type GeminiThinkingLevel = "minimal" | "low" | "medium" | "high";
|
|
21
|
+
type ThinkingDialect = {
|
|
22
|
+
kind: "level";
|
|
23
|
+
levels: GeminiThinkingLevel[];
|
|
24
|
+
} | {
|
|
25
|
+
kind: "budget";
|
|
26
|
+
min: number;
|
|
27
|
+
max: number;
|
|
28
|
+
requireMin?: boolean;
|
|
29
|
+
}
|
|
30
|
+
/** Unknown family: only ask for thought parts, never guess a level or budget. */
|
|
31
|
+
| {
|
|
32
|
+
kind: "includeOnly";
|
|
33
|
+
}
|
|
34
|
+
/** Image models must not carry thinking config at all. */
|
|
35
|
+
| {
|
|
36
|
+
kind: "none";
|
|
37
|
+
};
|
|
38
|
+
export type GeminiThinkingConfig = {
|
|
39
|
+
includeThoughts?: boolean;
|
|
40
|
+
thinkingLevel?: GeminiThinkingLevel;
|
|
41
|
+
thinkingBudget?: number;
|
|
42
|
+
};
|
|
43
|
+
/**
|
|
44
|
+
* Which thinking dialect a model speaks. Matching is by family prefix so tier
|
|
45
|
+
* and preview suffixes (`-low`, `-high`, `-tiered`, `-preview`, `-agent`) all
|
|
46
|
+
* resolve to their family.
|
|
47
|
+
*/
|
|
48
|
+
export declare function resolveThinkingDialect(model: string): ThinkingDialect;
|
|
49
|
+
/**
|
|
50
|
+
* Clamp a requested effort onto the levels a family accepts.
|
|
51
|
+
*
|
|
52
|
+
* Rounds *up* when the exact level is missing so a request never silently loses
|
|
53
|
+
* reasoning depth: `medium` on Gemini 3 Pro (low|high) becomes `high`, and
|
|
54
|
+
* Claude's `xhigh`/`max` — which are not Gemini enum values — become `high`.
|
|
55
|
+
*/
|
|
56
|
+
export declare function translateThinkingLevel(effort: string, levels: GeminiThinkingLevel[]): GeminiThinkingLevel;
|
|
57
|
+
/**
|
|
58
|
+
* Build the `generationConfig.thinkingConfig` for a request.
|
|
59
|
+
*
|
|
60
|
+
* Returns undefined when the request asks for no thinking at all, or when the
|
|
61
|
+
* model cannot carry the config.
|
|
62
|
+
*/
|
|
63
|
+
export declare function buildGeminiThinkingConfig(request: Pick<UnifiedChatRequest, "model" | "reasoning" | "max_tokens"> & {
|
|
64
|
+
thinking?: UnifiedChatRequest["thinking"];
|
|
65
|
+
}): GeminiThinkingConfig | undefined;
|
|
66
|
+
export {};
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { UnifiedChatRequest } from "../types/llm";
|
|
2
|
+
/**
|
|
3
|
+
* Transform a tool object
|
|
4
|
+
* @param {Object} tool - The tool object to transform
|
|
5
|
+
* @returns {Object} - The transformed tool object
|
|
6
|
+
*/
|
|
7
|
+
export declare function tTool(tool: any, opts?: {
|
|
8
|
+
collapseUnions?: boolean;
|
|
9
|
+
}): any;
|
|
10
|
+
export declare const SKIP_THOUGHT_SIGNATURE = "skip_thought_signature_validator";
|
|
11
|
+
export type GeminiBuildOptions = {
|
|
12
|
+
/**
|
|
13
|
+
* How to replay functionCall parts whose thought signature is missing (Claude
|
|
14
|
+
* Code strips the field from tool_use blocks).
|
|
15
|
+
*
|
|
16
|
+
* - "skip" (default): stamp the documented `skip_thought_signature_validator`
|
|
17
|
+
* sentinel on the first functionCall part of the turn. Gemini 3 and
|
|
18
|
+
* Antigravity return 400 without it.
|
|
19
|
+
* - "none": never stamp the sentinel — escape hatch for endpoints that reject
|
|
20
|
+
* it, at the cost of 400s on unsigned tool replays.
|
|
21
|
+
*
|
|
22
|
+
* The sentinel is only reached when the real signature is unavailable: CCR
|
|
23
|
+
* caches signatures per tool-call id (see thought-signature-cache) precisely
|
|
24
|
+
* so that unsigned replays stop degrading the model.
|
|
25
|
+
*/
|
|
26
|
+
thoughtSignatureFallback?: "skip" | "none";
|
|
27
|
+
/**
|
|
28
|
+
* Cache scope for remembered thought signatures — the provider name. A
|
|
29
|
+
* signature is only valid at the upstream that minted it, so a mismatch must
|
|
30
|
+
* miss the cache and fall back to the sentinel.
|
|
31
|
+
*/
|
|
32
|
+
signatureScope?: string;
|
|
33
|
+
};
|
|
34
|
+
/**
|
|
35
|
+
* Build a Gemini generateContent body from UnifiedChatRequest.
|
|
36
|
+
*
|
|
37
|
+
* Whitelist-by-construction: messages/tools/system are rebuilt from named fields,
|
|
38
|
+
* so Anthropic `cache_control` markers never reach upstream. Do not refactor toward
|
|
39
|
+
* pass-through of content objects without stripping cache_control first.
|
|
40
|
+
*/
|
|
41
|
+
export declare function buildRequestBody(request: UnifiedChatRequest, opts?: GeminiBuildOptions): Record<string, any>;
|
|
42
|
+
export declare function transformRequestOut(request: Record<string, any>): UnifiedChatRequest;
|
|
43
|
+
export declare function transformResponseOut(response: Response, providerName: string, logger?: any, signatureScope?: string): Promise<Response>;
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
import { MessageContent } from "../types/llm";
|
|
2
|
+
/** Marker that prefixes CCR's upstream-failure notice; used to strip it on replay. */
|
|
3
|
+
export declare const UPSTREAM_STOP_NOTICE = "\u26A0\uFE0F Upstream ended the turn without a reply";
|
|
4
|
+
export declare function normalizeGoogleFinishReason(raw?: string | null): string | null;
|
|
5
|
+
/**
|
|
6
|
+
* Text to show when the upstream ends a turn abnormally with nothing to show:
|
|
7
|
+
* no text, no tool calls. Returns null for normal completions.
|
|
8
|
+
*
|
|
9
|
+
* Gemini 3 / Antigravity return e.g. `MALFORMED_FUNCTION_CALL` ("Function call
|
|
10
|
+
* is empty - no input to parse") after streaming only thinking. Without this the
|
|
11
|
+
* turn reached Claude Code as a silent, successful `end_turn`, so the user saw
|
|
12
|
+
* an assistant turn that said nothing and had to prompt again.
|
|
13
|
+
*/
|
|
14
|
+
export declare function buildAbnormalFinishNotice(candidate?: any): string | null;
|
|
15
|
+
/**
|
|
16
|
+
* Callbacks used by ThinkingSequencer to emit SSE chunks.
|
|
17
|
+
* The caller provides implementations that handle actual SSE serialization.
|
|
18
|
+
*/
|
|
19
|
+
export interface ThinkingSequencerEmit {
|
|
20
|
+
thinking: (content: string, chunk?: any) => void;
|
|
21
|
+
signature: (sig: string, chunk?: any) => void;
|
|
22
|
+
content: (text: string, meta?: {
|
|
23
|
+
chunk?: any;
|
|
24
|
+
candidate?: any;
|
|
25
|
+
mode?: "direct" | "buffered" | "placeholder" | "finish";
|
|
26
|
+
finishReason?: string | null;
|
|
27
|
+
}) => void;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* State machine that enforces Anthropic-safe emission order for Gemini thinking:
|
|
31
|
+
* Thinking Content → Thinking Signature → Final Content
|
|
32
|
+
*
|
|
33
|
+
* Supports two upstream stream dialects:
|
|
34
|
+
*
|
|
35
|
+
* 1) Public Gemini API (and Vertex):
|
|
36
|
+
* - Happy path: thought:true → thoughtSignature → text
|
|
37
|
+
* - Gemini 3 out-of-order: thought:true → text (buffer) → signature (flush)
|
|
38
|
+
* - Empty thinking: signature first → emit "(no content)" thinking → text
|
|
39
|
+
*
|
|
40
|
+
* 2) Antigravity:
|
|
41
|
+
* - Visible text first (often with no thought:true parts)
|
|
42
|
+
* - Final event: thoughtSignature + empty text + STOP
|
|
43
|
+
* - Must NOT open a late thinking block after text (Claude Code drops the turn)
|
|
44
|
+
*
|
|
45
|
+
* Rule: if visible content was already emitted when a signature arrives, record
|
|
46
|
+
* the signature as handled and skip thinking/signature emission.
|
|
47
|
+
*/
|
|
48
|
+
export declare class ThinkingSequencer {
|
|
49
|
+
private emit;
|
|
50
|
+
private _hasThinking;
|
|
51
|
+
private _sigSent;
|
|
52
|
+
private _contentSent;
|
|
53
|
+
private _buffer;
|
|
54
|
+
constructor(emit: ThinkingSequencerEmit);
|
|
55
|
+
/** Called when thinking text arrives. Emits immediately. */
|
|
56
|
+
processThinking(text: string, chunk?: any): void;
|
|
57
|
+
/**
|
|
58
|
+
* Called when a signature arrives.
|
|
59
|
+
* - Public Gemini: emit thinking placeholder if needed, emit signature, flush buffer
|
|
60
|
+
* - Antigravity trailer after content: no-op emission (see class docs)
|
|
61
|
+
*/
|
|
62
|
+
processSignature(sig: string, chunk?: any): void;
|
|
63
|
+
processSignatureWithMeta(sig: string, chunk?: any, meta?: {
|
|
64
|
+
beforeFlush?: () => void;
|
|
65
|
+
flushMeta?: {
|
|
66
|
+
chunk?: any;
|
|
67
|
+
candidate?: any;
|
|
68
|
+
mode?: "direct" | "buffered" | "placeholder" | "finish";
|
|
69
|
+
finishReason?: string | null;
|
|
70
|
+
};
|
|
71
|
+
}): void;
|
|
72
|
+
/**
|
|
73
|
+
* Called when content text arrives.
|
|
74
|
+
* - Signature already sent or no thinking at all: emit immediately
|
|
75
|
+
* - Thinking seen but no signature yet: buffer (public Gemini / Gemini 3)
|
|
76
|
+
*/
|
|
77
|
+
processContent(text: string, chunk?: any, candidate?: any): void;
|
|
78
|
+
emitContentPlaceholder(text: string, meta?: {
|
|
79
|
+
chunk?: any;
|
|
80
|
+
candidate?: any;
|
|
81
|
+
finishReason?: string | null;
|
|
82
|
+
}): void;
|
|
83
|
+
/** Explicitly buffer content (for Gemini 3 out-of-order delivery). */
|
|
84
|
+
bufferContent(text: string): void;
|
|
85
|
+
/**
|
|
86
|
+
* Finalize the stream:
|
|
87
|
+
* - Emits fallback signature if thinking was seen but no signature arrived
|
|
88
|
+
* - Flushes any remaining buffered content
|
|
89
|
+
*/
|
|
90
|
+
finalize(chunk?: any, candidate?: any, options?: {
|
|
91
|
+
beforeFlush?: () => void;
|
|
92
|
+
}): void;
|
|
93
|
+
flushBufferedContent(meta?: {
|
|
94
|
+
chunk?: any;
|
|
95
|
+
candidate?: any;
|
|
96
|
+
mode?: "direct" | "buffered" | "placeholder" | "finish";
|
|
97
|
+
finishReason?: string | null;
|
|
98
|
+
}): void;
|
|
99
|
+
/**
|
|
100
|
+
* Whether Gemini 3 content should be deferred (signature not yet seen,
|
|
101
|
+
* not finishing, no tool calls). Public Gemini 3 out-of-order path.
|
|
102
|
+
*/
|
|
103
|
+
shouldDeferContent(isFinish: boolean, hasToolCalls: boolean): boolean;
|
|
104
|
+
get hasBufferedContent(): boolean;
|
|
105
|
+
get hasThinkingContent(): boolean;
|
|
106
|
+
get signatureSent(): boolean;
|
|
107
|
+
get contentSent(): boolean;
|
|
108
|
+
get needsContentPlaceholder(): boolean;
|
|
109
|
+
/**
|
|
110
|
+
* Mark a thoughtSignature as handled without emitting thinking/signature/content.
|
|
111
|
+
* Used when the signature belongs on functionCall parts (tool turns) and must
|
|
112
|
+
* not invent "(no content)" thinking/text placeholders.
|
|
113
|
+
*/
|
|
114
|
+
acknowledgeSignature(): void;
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* Interface for normalized image data before provider-specific wrapping
|
|
118
|
+
*/
|
|
119
|
+
export interface NormalizedImage {
|
|
120
|
+
url: string;
|
|
121
|
+
mediaType: string;
|
|
122
|
+
isBase64: boolean;
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Maps a role based on a provided mapping object.
|
|
126
|
+
* Example mapping: { assistant: 'model' }
|
|
127
|
+
*/
|
|
128
|
+
export declare function mapRole(role: string, mapping: Record<string, string>): string;
|
|
129
|
+
/**
|
|
130
|
+
* Identifies image_url content and normalizes it into a consistent format.
|
|
131
|
+
* Returns an array of NormalizedImage for any images found in the content.
|
|
132
|
+
*/
|
|
133
|
+
export declare function extractImageParts(content: string | null | MessageContent[]): NormalizedImage[];
|
|
134
|
+
/**
|
|
135
|
+
* Merges consecutive messages with the same role into a single message
|
|
136
|
+
* by combining their contents in the specified field.
|
|
137
|
+
*/
|
|
138
|
+
export declare function consolidateMessages<T extends {
|
|
139
|
+
role: string;
|
|
140
|
+
[key: string]: any;
|
|
141
|
+
}>(messages: T[], contentField: keyof T): T[];
|
|
142
|
+
/**
|
|
143
|
+
* Normalizes a tool definition to a standard { name, description, parameters } shape.
|
|
144
|
+
* Handles both OpenAI-style and Anthropic-style tool definitions.
|
|
145
|
+
*/
|
|
146
|
+
export declare function normalizeTool(tool: any): {
|
|
147
|
+
name: string;
|
|
148
|
+
description: string;
|
|
149
|
+
parameters: any;
|
|
150
|
+
};
|
|
151
|
+
/**
|
|
152
|
+
* Wraps normalized image data into provider-specific JSON structures.
|
|
153
|
+
*/
|
|
154
|
+
export declare function processImageContent(normalizedImage: NormalizedImage, provider: "gemini" | "claude"): any;
|
|
155
|
+
export declare function replaceLatexSymbols(text: string): string;
|
|
156
|
+
/**
|
|
157
|
+
* Sanitize a function name for Gemini's naming rules:
|
|
158
|
+
* Must start with a letter or underscore, contain only [a-zA-Z0-9_.:\-], max 128 chars
|
|
159
|
+
*/
|
|
160
|
+
export declare function sanitizeGeminiFunctionName(name: string): string;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const formatBase64: (data: string, media_type: string) => string;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { UnifiedChatRequest } from "../types/llm";
|
|
2
|
+
/**
|
|
3
|
+
* Transform incoming request to Mistral-compatible format
|
|
4
|
+
*/
|
|
5
|
+
export declare function buildRequestBody(request: UnifiedChatRequest, context?: any, provider?: any): Record<string, any>;
|
|
6
|
+
/**
|
|
7
|
+
* Transform a Mistral provider request back into a UnifiedChatRequest
|
|
8
|
+
*/
|
|
9
|
+
export declare function transformRequestOut(request: any): Promise<UnifiedChatRequest>;
|
|
10
|
+
/**
|
|
11
|
+
* Transform response back — convert Mistral's content-array thinking format
|
|
12
|
+
* to the delta.thinking / delta.content shape expected by @caeliq/llms.
|
|
13
|
+
*/
|
|
14
|
+
export declare function transformResponseOut(response: Response, providerName: string, logger?: any): Promise<Response>;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { UnifiedChatRequest } from "../types/llm";
|
|
2
|
+
/**
|
|
3
|
+
* Validates OpenAI format messages to ensure complete tool_calls/tool message pairing.
|
|
4
|
+
* Requires tool messages to immediately follow assistant messages with tool_calls.
|
|
5
|
+
* Enforces strict immediate following sequence between tool_calls and tool messages.
|
|
6
|
+
*/
|
|
7
|
+
export declare function validateOpenAIToolCalls(messages: any[]): any[];
|
|
8
|
+
/**
|
|
9
|
+
* Injects prompt caching hints into messages for Anthropic models.
|
|
10
|
+
* Adds cache_control: { type: "ephemeral" } to system messages when model is Claude.
|
|
11
|
+
*/
|
|
12
|
+
export declare function injectPromptCaching(messages: any[], model: string): any[];
|
|
13
|
+
export declare function supportsOpenAIExplicitPromptCache(model: string): boolean;
|
|
14
|
+
export declare function applyOpenAIChatCaching(request: UnifiedChatRequest, _provider?: any, context?: any): UnifiedChatRequest;
|
|
15
|
+
export declare function openAIContentCacheBreakpoint(content: any, model: string): any;
|
|
16
|
+
export declare function applyRequestCacheKey(request: UnifiedChatRequest, context?: any): UnifiedChatRequest;
|
|
17
|
+
export declare function applyProviderNativeChatCaching(request: UnifiedChatRequest, provider?: any, context?: any): UnifiedChatRequest;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
interface QwenTokens {
|
|
2
|
+
token: string;
|
|
3
|
+
expiresAt: number | null;
|
|
4
|
+
updatedAt: number;
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* Load a valid (non-expired) Qwen access token, transparently refreshing it
|
|
8
|
+
* via the upstream rotation endpoint when the token is within 6 hours of
|
|
9
|
+
* expiry. Throws with an actionable message if no token is configured or if
|
|
10
|
+
* the refresh attempt fails.
|
|
11
|
+
*/
|
|
12
|
+
export declare function getValidAccessToken(): Promise<QwenTokens>;
|
|
13
|
+
export {};
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Privacy-safe redaction for upstream errors and debug logs.
|
|
3
|
+
* Keep enough diagnostic signal (status, error type) without leaking secrets.
|
|
4
|
+
*/
|
|
5
|
+
export declare function sanitizeUpstreamErrorText(value: string): string;
|
|
6
|
+
export declare function sanitizeErrorForLog(error: unknown): {
|
|
7
|
+
message: string;
|
|
8
|
+
code?: string;
|
|
9
|
+
name?: string;
|
|
10
|
+
statusCode?: number;
|
|
11
|
+
stack?: string;
|
|
12
|
+
cause?: string;
|
|
13
|
+
};
|
|
14
|
+
/** Flatten Fastify/Node header values to a single string for logging. */
|
|
15
|
+
export declare function normalizeHeaderValue(value: unknown): string | undefined;
|
|
16
|
+
/** Strip auth headers from a headers object for debug logging. */
|
|
17
|
+
export declare function sanitizeHeadersForLog(headers: Headers | Record<string, unknown> | undefined): Record<string, string>;
|
|
18
|
+
/**
|
|
19
|
+
* Compare two header maps (case-insensitive names).
|
|
20
|
+
* Values are sanitized the same way as sanitizeHeadersForLog.
|
|
21
|
+
*/
|
|
22
|
+
export declare function diffHeadersForLog(left: Headers | Record<string, unknown> | undefined, right: Headers | Record<string, unknown> | undefined): {
|
|
23
|
+
onlyInLeft: Record<string, string>;
|
|
24
|
+
onlyInRight: Record<string, string>;
|
|
25
|
+
changed: Record<string, {
|
|
26
|
+
from: string;
|
|
27
|
+
to: string;
|
|
28
|
+
}>;
|
|
29
|
+
sameCount: number;
|
|
30
|
+
};
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { UnifiedChatRequest } from "../types/llm";
|
|
2
|
+
/** Loopback and NO_PROXY/no_proxy hosts should not go through HTTPS_PROXY. */
|
|
3
|
+
export declare function shouldBypassProxy(target: URL | string): boolean;
|
|
4
|
+
export declare function sendUnifiedRequest(url: URL | string, request: UnifiedChatRequest, config: any, context: any, logger?: any): Promise<Response>;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { FastifyReply, FastifyRequest } from "fastify";
|
|
2
|
+
export declare const CLIENT_DISCONNECT_REASON = "client disconnected";
|
|
3
|
+
export type ClientDisconnectHandle = {
|
|
4
|
+
signal: AbortSignal;
|
|
5
|
+
/** Attach response close/error listeners for the full upstream lifecycle. */
|
|
6
|
+
arm: () => void;
|
|
7
|
+
};
|
|
8
|
+
export declare function delay(ms: number, signal?: AbortSignal): Promise<void>;
|
|
9
|
+
/**
|
|
10
|
+
* AbortSignal that fires when the HTTP client disconnects mid-response.
|
|
11
|
+
* Used to cancel upstream provider fetches and tear down streams.
|
|
12
|
+
*
|
|
13
|
+
* Important: never treat request close/destroyed state as a disconnect after
|
|
14
|
+
* Fastify has parsed the body. A response `close` event is also insufficient by
|
|
15
|
+
* itself: only abort when the response or its socket is actually gone.
|
|
16
|
+
*/
|
|
17
|
+
export declare function createClientDisconnectSignal(_req: FastifyRequest, reply?: FastifyReply): ClientDisconnectHandle;
|
|
18
|
+
export declare function parseRetryAfterHeaderMs(value: string | null | undefined): number | undefined;
|
|
19
|
+
export declare function exponentialRetryBackoffMs(failedAttemptIndex: number): number;
|
|
20
|
+
/** Prefer Retry-After when present; otherwise exponential backoff. */
|
|
21
|
+
export declare function retryDelayAfterFailure(failedAttemptIndex: number, retryAfterHeader?: string | null): number;
|
|
22
|
+
export declare function selectFallbackModels(fallbackConfig: Record<string, unknown> | undefined, scenarioType: string): string[] | undefined;
|
|
23
|
+
export declare function toClientAbortError(reason?: unknown): Error;
|
|
24
|
+
export declare function isClientAbortError(error: unknown): boolean;
|
|
25
|
+
export declare function isResponseSocketGone(reply: FastifyReply): boolean;
|
|
26
|
+
export declare function isProviderNetworkError(error: unknown): boolean;
|
|
27
|
+
export declare function isFallbackEligibleError(error: unknown): boolean;
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { ConfigService } from "../services/config";
|
|
2
|
+
import { TokenizerService } from "../services/tokenizer";
|
|
3
|
+
interface Tool {
|
|
4
|
+
name: string;
|
|
5
|
+
description?: string;
|
|
6
|
+
input_schema: object;
|
|
7
|
+
}
|
|
8
|
+
interface ContentBlockParam {
|
|
9
|
+
type: string;
|
|
10
|
+
[key: string]: any;
|
|
11
|
+
}
|
|
12
|
+
interface MessageParam {
|
|
13
|
+
role: string;
|
|
14
|
+
content: string | ContentBlockParam[];
|
|
15
|
+
}
|
|
16
|
+
/** Normalize `provider/model` or `provider,model` into our `provider,model` form. */
|
|
17
|
+
export declare function normalizeModelSelector(value: string | undefined | null): string | undefined;
|
|
18
|
+
/**
|
|
19
|
+
* Strip Claude Code's billing helper system block.
|
|
20
|
+
* Returns true when that block marks the request as a subagent.
|
|
21
|
+
*/
|
|
22
|
+
export declare function removeClaudeCodeBillingSystemHeader(body: any): boolean;
|
|
23
|
+
/** Prefer system tag, then early user-message tag; strip whichever matched. */
|
|
24
|
+
export declare function extractAndRemoveClaudeCodeSubagentModelTag(body: any): string | undefined;
|
|
25
|
+
export declare const calculateTokenCount: (messages: MessageParam[], system: any, tools: Tool[]) => number;
|
|
26
|
+
export interface RouterContext {
|
|
27
|
+
configService: ConfigService;
|
|
28
|
+
tokenizerService?: TokenizerService;
|
|
29
|
+
event?: any;
|
|
30
|
+
}
|
|
31
|
+
export type RouterScenarioType = 'default' | 'background' | 'think' | 'longContext' | 'webSearch' | 'subagent';
|
|
32
|
+
export interface RouterFallbackConfig {
|
|
33
|
+
default?: string[];
|
|
34
|
+
background?: string[];
|
|
35
|
+
think?: string[];
|
|
36
|
+
longContext?: string[];
|
|
37
|
+
webSearch?: string[];
|
|
38
|
+
subagent?: string[];
|
|
39
|
+
}
|
|
40
|
+
export declare const router: (req: any, _res: any, context: RouterContext) => Promise<void>;
|
|
41
|
+
export declare const searchProjectBySession: (sessionId: string, logger?: any) => Promise<string | null>;
|
|
42
|
+
export {};
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Recursively sanitizes a JSON schema by:
|
|
3
|
+
* 1. Stripping unknown fields (not in VALID_SCHEMA_FIELDS)
|
|
4
|
+
* 2. Removing enum from non-string types
|
|
5
|
+
* 3. Removing format from string types (except "enum" and "date-time")
|
|
6
|
+
* 4. Removing format: 'uri' from any type
|
|
7
|
+
* 5. Removing $schema field
|
|
8
|
+
*
|
|
9
|
+
* This is a superset of normalizeJsonSchema that also handles
|
|
10
|
+
* field whitelisting and enum/format cleanup needed by providers
|
|
11
|
+
* like Gemini and Mistral.
|
|
12
|
+
*/
|
|
13
|
+
export declare function sanitizeJsonSchema(schema: any, parentKey?: string): any;
|
|
14
|
+
/**
|
|
15
|
+
* Collapse union subschemas that carry no `type` of their own.
|
|
16
|
+
*
|
|
17
|
+
* Antigravity serves Claude models by parsing our Gemini `generateContent` body
|
|
18
|
+
* into the Gemini Schema proto and re-emitting it as an Anthropic tool schema. A
|
|
19
|
+
* subschema with `anyOf` and no sibling `type` has no proto type to carry, and
|
|
20
|
+
* what comes out the far side fails Anthropic's draft 2020-12 validation:
|
|
21
|
+
*
|
|
22
|
+
* tools.18.custom.input_schema: JSON schema is invalid.
|
|
23
|
+
*
|
|
24
|
+
* Adding a sibling `type` is not an option — Gemini rejects that outright with
|
|
25
|
+
* "type and anyOf cannot be both populated" — so the union is collapsed onto its
|
|
26
|
+
* first typed branch instead, and the alternatives are recorded in the
|
|
27
|
+
* description so the model still knows they exist. Lossy, but the alternative is
|
|
28
|
+
* that every request carrying such a tool fails.
|
|
29
|
+
*
|
|
30
|
+
* Gemini itself handles typeless unions fine, so this is only for backends
|
|
31
|
+
* reached through the Gemini wire format.
|
|
32
|
+
*/
|
|
33
|
+
export declare function collapseTypelessUnions(schema: any): any;
|
|
34
|
+
/**
|
|
35
|
+
* Normalizes a JSON schema by removing fields that may cause API rejections:
|
|
36
|
+
* - format: 'uri' from string types
|
|
37
|
+
* - $schema field
|
|
38
|
+
*
|
|
39
|
+
* For full sanitization (field whitelist, enum/format cleanup), use sanitizeJsonSchema instead.
|
|
40
|
+
*/
|
|
41
|
+
export declare function normalizeJsonSchema(schema: any): any;
|
|
42
|
+
/**
|
|
43
|
+
* Normalizes tool function parameters by removing problematic fields.
|
|
44
|
+
* Uses sanitizeJsonSchema for thorough cleanup.
|
|
45
|
+
*/
|
|
46
|
+
export declare function normalizeToolParameters(parameters: any): any;
|