@prestyj/ai 5.6.0 → 5.8.0
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 +1 -1
- package/dist/index.cjs +334 -23
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +29 -2
- package/dist/index.d.ts +29 -2
- package/dist/index.js +329 -23
- package/dist/index.js.map +1 -1
- package/package.json +2 -1
package/dist/index.d.cts
CHANGED
|
@@ -2,7 +2,7 @@ import { z } from 'zod';
|
|
|
2
2
|
import Anthropic from '@anthropic-ai/sdk';
|
|
3
3
|
import OpenAI from 'openai';
|
|
4
4
|
|
|
5
|
-
type Provider = "anthropic" | "xiaomi" | "openai" | "gemini" | "glm" | "moonshot" | "minimax" | "deepseek" | "openrouter" | "sakana" | "palsu";
|
|
5
|
+
type Provider = "anthropic" | "xiaomi" | "openai" | "gemini" | "glm" | "moonshot" | "minimax" | "deepseek" | "openrouter" | "sakana" | "xai" | "palsu";
|
|
6
6
|
type ThinkingLevel = "low" | "medium" | "high" | "xhigh" | "max" | "ultra";
|
|
7
7
|
type CacheRetention = "none" | "short" | "long";
|
|
8
8
|
interface TextContent {
|
|
@@ -444,6 +444,27 @@ declare function formatErrorForDisplay(err: unknown): string;
|
|
|
444
444
|
*/
|
|
445
445
|
declare function classifyProviderError(message: string): string;
|
|
446
446
|
|
|
447
|
+
declare const REDACTED = "[REDACTED]";
|
|
448
|
+
interface RedactionOptions {
|
|
449
|
+
/** Exact secret values to remove in addition to high-confidence formats. */
|
|
450
|
+
secrets?: Iterable<string>;
|
|
451
|
+
/** Maximum recursive object depth before a stable truncation marker is emitted. */
|
|
452
|
+
maxDepth?: number;
|
|
453
|
+
/** Maximum total array/object entries cloned before truncation markers are emitted. */
|
|
454
|
+
maxEntries?: number;
|
|
455
|
+
/** Maximum retained string length after sanitization. */
|
|
456
|
+
maxStringLength?: number;
|
|
457
|
+
}
|
|
458
|
+
/** Collect sufficiently distinctive secrets from security-sensitive environment variables. */
|
|
459
|
+
declare function environmentSecrets(env: Record<string, string | undefined>): string[];
|
|
460
|
+
/** Redact credentials from arbitrary text without mutating its source. */
|
|
461
|
+
declare function redactText(text: string, options?: RedactionOptions): string;
|
|
462
|
+
/**
|
|
463
|
+
* Recursively clone and sanitize transport/persistence payloads.
|
|
464
|
+
* Cycles, excessive depth, and excessive collection sizes become stable markers.
|
|
465
|
+
*/
|
|
466
|
+
declare function redactValue<T>(value: T, options?: RedactionOptions): T;
|
|
467
|
+
|
|
447
468
|
/**
|
|
448
469
|
* Provider-level diagnostic hook. Mirrors the pattern used by gg-agent's
|
|
449
470
|
* setStreamDiagnostic — the host app wires a callback (typically writing to
|
|
@@ -454,6 +475,12 @@ type ProviderDiagnosticFn = (phase: string, data?: Record<string, unknown>) => v
|
|
|
454
475
|
/** Register a diagnostic callback for provider-level tracing. */
|
|
455
476
|
declare function setProviderDiagnostic(fn: ProviderDiagnosticFn | null): void;
|
|
456
477
|
|
|
478
|
+
/**
|
|
479
|
+
* Cap historical images before provider dispatch, removing the oldest first.
|
|
480
|
+
* The persisted/live conversation is never mutated; only modified messages and
|
|
481
|
+
* tool results are cloned for the outgoing request.
|
|
482
|
+
*/
|
|
483
|
+
declare function clampProviderContextImages(messages: Message[], provider: Provider, supportsImages: boolean | undefined): Message[];
|
|
457
484
|
declare function toAnthropicMessages(messages: Message[], cacheControl?: {
|
|
458
485
|
type: "ephemeral";
|
|
459
486
|
ttl?: "1h";
|
|
@@ -558,4 +585,4 @@ interface PalsuProviderConfig {
|
|
|
558
585
|
*/
|
|
559
586
|
declare function registerPalsuProvider(config?: PalsuProviderConfig): PalsuProviderHandle;
|
|
560
587
|
|
|
561
|
-
export { type AssistantMessage, type CacheRetention, type ContentPart, type DoneEvent, EZCoderAIError, type ErrorEvent, type ErrorSource, EventStream, type FormattedError, type ImageContent, type Message, type PalsuModelConfig, type PalsuModelHandle, type PalsuProviderConfig, type PalsuProviderHandle, type PalsuProviderState, type PalsuResponse, type PalsuResponseFactory, type Provider, type ProviderDiagnosticFn, type ProviderEntry, ProviderError, type ProviderStreamFn, type RawContent, type ServerToolCall, type ServerToolCallEvent, type ServerToolDefinition, type ServerToolResult, type ServerToolResultEvent, type StopReason, type StreamEvent, type StreamOptions, type StreamResponse, StreamResult, type SystemMessage, type TextContent, type TextDeltaEvent, type ThinkingContent, type ThinkingDeltaEvent, type ThinkingLevel, type Tool, type ToolCall, type ToolCallDeltaEvent, type ToolCallDoneEvent, type ToolChoice, type ToolResult, type ToolResultContent, type ToolResultMessage, type Usage, type UserMessage, type VideoContent, classifyProviderError, formatError, formatErrorForDisplay, isHardBillingMessage, isUsageLimitError, palsuAssistantMessage, palsuText, palsuThinking, palsuToolCall, prewarmAnthropicCache, providerRegistry, registerPalsuProvider, setProviderDiagnostic, stream, toAnthropicMessages, toOpenAIMessages };
|
|
588
|
+
export { type AssistantMessage, type CacheRetention, type ContentPart, type DoneEvent, EZCoderAIError, type ErrorEvent, type ErrorSource, EventStream, type FormattedError, type ImageContent, type Message, type PalsuModelConfig, type PalsuModelHandle, type PalsuProviderConfig, type PalsuProviderHandle, type PalsuProviderState, type PalsuResponse, type PalsuResponseFactory, type Provider, type ProviderDiagnosticFn, type ProviderEntry, ProviderError, type ProviderStreamFn, REDACTED as REDACTION_MARKER, type RawContent, type RedactionOptions, type ServerToolCall, type ServerToolCallEvent, type ServerToolDefinition, type ServerToolResult, type ServerToolResultEvent, type StopReason, type StreamEvent, type StreamOptions, type StreamResponse, StreamResult, type SystemMessage, type TextContent, type TextDeltaEvent, type ThinkingContent, type ThinkingDeltaEvent, type ThinkingLevel, type Tool, type ToolCall, type ToolCallDeltaEvent, type ToolCallDoneEvent, type ToolChoice, type ToolResult, type ToolResultContent, type ToolResultMessage, type Usage, type UserMessage, type VideoContent, clampProviderContextImages, classifyProviderError, environmentSecrets, formatError, formatErrorForDisplay, isHardBillingMessage, isUsageLimitError, palsuAssistantMessage, palsuText, palsuThinking, palsuToolCall, prewarmAnthropicCache, providerRegistry, redactText, redactValue, registerPalsuProvider, setProviderDiagnostic, stream, toAnthropicMessages, toOpenAIMessages };
|
package/dist/index.d.ts
CHANGED
|
@@ -2,7 +2,7 @@ import { z } from 'zod';
|
|
|
2
2
|
import Anthropic from '@anthropic-ai/sdk';
|
|
3
3
|
import OpenAI from 'openai';
|
|
4
4
|
|
|
5
|
-
type Provider = "anthropic" | "xiaomi" | "openai" | "gemini" | "glm" | "moonshot" | "minimax" | "deepseek" | "openrouter" | "sakana" | "palsu";
|
|
5
|
+
type Provider = "anthropic" | "xiaomi" | "openai" | "gemini" | "glm" | "moonshot" | "minimax" | "deepseek" | "openrouter" | "sakana" | "xai" | "palsu";
|
|
6
6
|
type ThinkingLevel = "low" | "medium" | "high" | "xhigh" | "max" | "ultra";
|
|
7
7
|
type CacheRetention = "none" | "short" | "long";
|
|
8
8
|
interface TextContent {
|
|
@@ -444,6 +444,27 @@ declare function formatErrorForDisplay(err: unknown): string;
|
|
|
444
444
|
*/
|
|
445
445
|
declare function classifyProviderError(message: string): string;
|
|
446
446
|
|
|
447
|
+
declare const REDACTED = "[REDACTED]";
|
|
448
|
+
interface RedactionOptions {
|
|
449
|
+
/** Exact secret values to remove in addition to high-confidence formats. */
|
|
450
|
+
secrets?: Iterable<string>;
|
|
451
|
+
/** Maximum recursive object depth before a stable truncation marker is emitted. */
|
|
452
|
+
maxDepth?: number;
|
|
453
|
+
/** Maximum total array/object entries cloned before truncation markers are emitted. */
|
|
454
|
+
maxEntries?: number;
|
|
455
|
+
/** Maximum retained string length after sanitization. */
|
|
456
|
+
maxStringLength?: number;
|
|
457
|
+
}
|
|
458
|
+
/** Collect sufficiently distinctive secrets from security-sensitive environment variables. */
|
|
459
|
+
declare function environmentSecrets(env: Record<string, string | undefined>): string[];
|
|
460
|
+
/** Redact credentials from arbitrary text without mutating its source. */
|
|
461
|
+
declare function redactText(text: string, options?: RedactionOptions): string;
|
|
462
|
+
/**
|
|
463
|
+
* Recursively clone and sanitize transport/persistence payloads.
|
|
464
|
+
* Cycles, excessive depth, and excessive collection sizes become stable markers.
|
|
465
|
+
*/
|
|
466
|
+
declare function redactValue<T>(value: T, options?: RedactionOptions): T;
|
|
467
|
+
|
|
447
468
|
/**
|
|
448
469
|
* Provider-level diagnostic hook. Mirrors the pattern used by gg-agent's
|
|
449
470
|
* setStreamDiagnostic — the host app wires a callback (typically writing to
|
|
@@ -454,6 +475,12 @@ type ProviderDiagnosticFn = (phase: string, data?: Record<string, unknown>) => v
|
|
|
454
475
|
/** Register a diagnostic callback for provider-level tracing. */
|
|
455
476
|
declare function setProviderDiagnostic(fn: ProviderDiagnosticFn | null): void;
|
|
456
477
|
|
|
478
|
+
/**
|
|
479
|
+
* Cap historical images before provider dispatch, removing the oldest first.
|
|
480
|
+
* The persisted/live conversation is never mutated; only modified messages and
|
|
481
|
+
* tool results are cloned for the outgoing request.
|
|
482
|
+
*/
|
|
483
|
+
declare function clampProviderContextImages(messages: Message[], provider: Provider, supportsImages: boolean | undefined): Message[];
|
|
457
484
|
declare function toAnthropicMessages(messages: Message[], cacheControl?: {
|
|
458
485
|
type: "ephemeral";
|
|
459
486
|
ttl?: "1h";
|
|
@@ -558,4 +585,4 @@ interface PalsuProviderConfig {
|
|
|
558
585
|
*/
|
|
559
586
|
declare function registerPalsuProvider(config?: PalsuProviderConfig): PalsuProviderHandle;
|
|
560
587
|
|
|
561
|
-
export { type AssistantMessage, type CacheRetention, type ContentPart, type DoneEvent, EZCoderAIError, type ErrorEvent, type ErrorSource, EventStream, type FormattedError, type ImageContent, type Message, type PalsuModelConfig, type PalsuModelHandle, type PalsuProviderConfig, type PalsuProviderHandle, type PalsuProviderState, type PalsuResponse, type PalsuResponseFactory, type Provider, type ProviderDiagnosticFn, type ProviderEntry, ProviderError, type ProviderStreamFn, type RawContent, type ServerToolCall, type ServerToolCallEvent, type ServerToolDefinition, type ServerToolResult, type ServerToolResultEvent, type StopReason, type StreamEvent, type StreamOptions, type StreamResponse, StreamResult, type SystemMessage, type TextContent, type TextDeltaEvent, type ThinkingContent, type ThinkingDeltaEvent, type ThinkingLevel, type Tool, type ToolCall, type ToolCallDeltaEvent, type ToolCallDoneEvent, type ToolChoice, type ToolResult, type ToolResultContent, type ToolResultMessage, type Usage, type UserMessage, type VideoContent, classifyProviderError, formatError, formatErrorForDisplay, isHardBillingMessage, isUsageLimitError, palsuAssistantMessage, palsuText, palsuThinking, palsuToolCall, prewarmAnthropicCache, providerRegistry, registerPalsuProvider, setProviderDiagnostic, stream, toAnthropicMessages, toOpenAIMessages };
|
|
588
|
+
export { type AssistantMessage, type CacheRetention, type ContentPart, type DoneEvent, EZCoderAIError, type ErrorEvent, type ErrorSource, EventStream, type FormattedError, type ImageContent, type Message, type PalsuModelConfig, type PalsuModelHandle, type PalsuProviderConfig, type PalsuProviderHandle, type PalsuProviderState, type PalsuResponse, type PalsuResponseFactory, type Provider, type ProviderDiagnosticFn, type ProviderEntry, ProviderError, type ProviderStreamFn, REDACTED as REDACTION_MARKER, type RawContent, type RedactionOptions, type ServerToolCall, type ServerToolCallEvent, type ServerToolDefinition, type ServerToolResult, type ServerToolResultEvent, type StopReason, type StreamEvent, type StreamOptions, type StreamResponse, StreamResult, type SystemMessage, type TextContent, type TextDeltaEvent, type ThinkingContent, type ThinkingDeltaEvent, type ThinkingLevel, type Tool, type ToolCall, type ToolCallDeltaEvent, type ToolCallDoneEvent, type ToolChoice, type ToolResult, type ToolResultContent, type ToolResultMessage, type Usage, type UserMessage, type VideoContent, clampProviderContextImages, classifyProviderError, environmentSecrets, formatError, formatErrorForDisplay, isHardBillingMessage, isUsageLimitError, palsuAssistantMessage, palsuText, palsuThinking, palsuToolCall, prewarmAnthropicCache, providerRegistry, redactText, redactValue, registerPalsuProvider, setProviderDiagnostic, stream, toAnthropicMessages, toOpenAIMessages };
|
package/dist/index.js
CHANGED
|
@@ -58,12 +58,14 @@ var PROVIDER_DISPLAY = {
|
|
|
58
58
|
deepseek: "DeepSeek",
|
|
59
59
|
openrouter: "OpenRouter",
|
|
60
60
|
sakana: "Sakana",
|
|
61
|
+
xai: "xAI (Grok)",
|
|
61
62
|
xiaomi: "Xiaomi (MiMo)",
|
|
62
63
|
minimax: "MiniMax"
|
|
63
64
|
};
|
|
64
65
|
var PROVIDER_STATUS_URL = {
|
|
65
66
|
openai: "status.openai.com",
|
|
66
|
-
anthropic: "status.anthropic.com"
|
|
67
|
+
anthropic: "status.anthropic.com",
|
|
68
|
+
xai: "status.x.ai"
|
|
67
69
|
};
|
|
68
70
|
function providerDisplayName(provider) {
|
|
69
71
|
return PROVIDER_DISPLAY[provider] ?? provider;
|
|
@@ -102,13 +104,20 @@ function isRawJsonErrorEcho(message) {
|
|
|
102
104
|
return false;
|
|
103
105
|
}
|
|
104
106
|
}
|
|
107
|
+
function isRawHtmlErrorEcho(message) {
|
|
108
|
+
const withoutStatus = message.trimStart().replace(/^\d{3}\s+/, "").trimStart();
|
|
109
|
+
return /^<!doctype\s+html(?:\s|>)/i.test(withoutStatus) || /^<html(?:\s|>)/i.test(withoutStatus);
|
|
110
|
+
}
|
|
111
|
+
function providerHtmlErrorMessage(statusCode) {
|
|
112
|
+
return statusCode ? `The provider returned an HTML error page (HTTP ${statusCode}) instead of an API response.` : "The provider returned an HTML error page instead of an API response.";
|
|
113
|
+
}
|
|
105
114
|
function emptyProviderErrorMessage(statusCode) {
|
|
106
115
|
return statusCode ? `The provider returned an empty error response (HTTP ${statusCode}), with no further detail.` : "The provider returned an empty error response, with no further detail.";
|
|
107
116
|
}
|
|
108
117
|
function formatError(err) {
|
|
109
118
|
if (err instanceof ProviderError) {
|
|
110
119
|
const name = providerDisplayName(err.provider);
|
|
111
|
-
const cleanMessage = cleanProviderMessage(err.message);
|
|
120
|
+
const cleanMessage = cleanProviderMessage(err.message, err.statusCode);
|
|
112
121
|
if (isMythosAccessError(cleanMessage)) {
|
|
113
122
|
return {
|
|
114
123
|
headline: "Claude Mythos 5 is invitation-only.",
|
|
@@ -203,8 +212,9 @@ function formatErrorForDisplay(err) {
|
|
|
203
212
|
lines.push(` \u2192 ${f.guidance}`);
|
|
204
213
|
return lines.join("\n");
|
|
205
214
|
}
|
|
206
|
-
function cleanProviderMessage(message) {
|
|
207
|
-
|
|
215
|
+
function cleanProviderMessage(message, statusCode) {
|
|
216
|
+
const clean = message.replace(/^\[[^\]]+\]\s*/, "").trim();
|
|
217
|
+
return isRawHtmlErrorEcho(clean) ? providerHtmlErrorMessage(statusCode) : clean;
|
|
208
218
|
}
|
|
209
219
|
function inferSource(err) {
|
|
210
220
|
const msg = err.message.toLowerCase();
|
|
@@ -239,6 +249,9 @@ function providerGuidance(provider, message, statusCode) {
|
|
|
239
249
|
if (statusCode === 503 || lower.includes("service unavailable")) {
|
|
240
250
|
return `${name} is temporarily unavailable. Retry shortly \u2014 not a EZ Coder issue.`;
|
|
241
251
|
}
|
|
252
|
+
if (statusCode === 507 || lower.includes("exceeded request buffer limit while retrying upstream")) {
|
|
253
|
+
return `${name}'s proxy could not retry this large request. EZ Coder already retried automatically \u2014 compact the conversation, then retry.`;
|
|
254
|
+
}
|
|
242
255
|
if (statusCode === 500 || lower.includes("server_error") || lower.includes("500") && lower.includes("internal server error")) {
|
|
243
256
|
return status ? `This is an error from ${name}, not EZ Coder. Retry \u2014 if it keeps happening, check ${status}.` : `This is an error from ${name}, not EZ Coder. Retry \u2014 if it keeps happening, try a different model via the model selector.`;
|
|
244
257
|
}
|
|
@@ -565,6 +578,66 @@ function toAnthropicAssistantContent(content, preserveThinking, idMap) {
|
|
|
565
578
|
return true;
|
|
566
579
|
}).map((part) => toAnthropicAssistantPart(part, idMap)).filter((b) => b !== null);
|
|
567
580
|
}
|
|
581
|
+
var PROVIDER_IMAGE_LIMIT_PLACEHOLDER = "[image omitted: provider image limit]";
|
|
582
|
+
var PROVIDER_IMAGE_BUDGETS = {
|
|
583
|
+
anthropic: 90,
|
|
584
|
+
minimax: 90,
|
|
585
|
+
openai: 200,
|
|
586
|
+
gemini: 200,
|
|
587
|
+
openrouter: 90
|
|
588
|
+
};
|
|
589
|
+
function countContextImages(messages) {
|
|
590
|
+
let count = 0;
|
|
591
|
+
for (const message of messages) {
|
|
592
|
+
if (message.role === "user" && Array.isArray(message.content)) {
|
|
593
|
+
count += message.content.filter((part) => part.type === "image").length;
|
|
594
|
+
} else if (message.role === "tool") {
|
|
595
|
+
for (const result of message.content) {
|
|
596
|
+
if (Array.isArray(result.content)) {
|
|
597
|
+
count += result.content.filter((part) => part.type === "image").length;
|
|
598
|
+
}
|
|
599
|
+
}
|
|
600
|
+
}
|
|
601
|
+
}
|
|
602
|
+
return count;
|
|
603
|
+
}
|
|
604
|
+
function clampProviderContextImages(messages, provider, supportsImages) {
|
|
605
|
+
if (supportsImages === false) return messages;
|
|
606
|
+
const budget = PROVIDER_IMAGE_BUDGETS[provider] ?? 5;
|
|
607
|
+
let remainingToRemove = countContextImages(messages) - budget;
|
|
608
|
+
if (remainingToRemove <= 0) return messages;
|
|
609
|
+
return messages.map((message) => {
|
|
610
|
+
if (message.role === "user" && Array.isArray(message.content)) {
|
|
611
|
+
const content = message.content.filter((part) => {
|
|
612
|
+
if (part.type !== "image" || remainingToRemove <= 0) return true;
|
|
613
|
+
remainingToRemove--;
|
|
614
|
+
return false;
|
|
615
|
+
});
|
|
616
|
+
return {
|
|
617
|
+
...message,
|
|
618
|
+
content: content.length > 0 ? content : [{ type: "text", text: PROVIDER_IMAGE_LIMIT_PLACEHOLDER }]
|
|
619
|
+
};
|
|
620
|
+
}
|
|
621
|
+
if (message.role === "tool") {
|
|
622
|
+
return {
|
|
623
|
+
...message,
|
|
624
|
+
content: message.content.map((result) => {
|
|
625
|
+
if (!Array.isArray(result.content)) return result;
|
|
626
|
+
const content = result.content.filter((part) => {
|
|
627
|
+
if (part.type !== "image" || remainingToRemove <= 0) return true;
|
|
628
|
+
remainingToRemove--;
|
|
629
|
+
return false;
|
|
630
|
+
});
|
|
631
|
+
return {
|
|
632
|
+
...result,
|
|
633
|
+
content: content.length > 0 ? content : [{ type: "text", text: PROVIDER_IMAGE_LIMIT_PLACEHOLDER }]
|
|
634
|
+
};
|
|
635
|
+
})
|
|
636
|
+
};
|
|
637
|
+
}
|
|
638
|
+
return message;
|
|
639
|
+
});
|
|
640
|
+
}
|
|
568
641
|
var NON_VISION_USER_IMAGE_PLACEHOLDER = "(image omitted: model does not support images)";
|
|
569
642
|
var NON_VISION_TOOL_IMAGE_PLACEHOLDER = "(tool image omitted: model does not support images)";
|
|
570
643
|
var NON_VIDEO_USER_PLACEHOLDER = "(video omitted: model does not support video)";
|
|
@@ -1582,7 +1655,8 @@ function toError(err) {
|
|
|
1582
1655
|
const bodyMessage = typeof nestedError?.message === "string" && nestedError.message.trim() ? nestedError.message.trim() : typeof errorBody?.message === "string" && errorBody.message.trim() ? errorBody.message.trim() : void 0;
|
|
1583
1656
|
const bodyType = typeof nestedError?.type === "string" ? nestedError.type : typeof errorBody?.type === "string" ? errorBody.type : typeof err.type === "string" ? err.type : void 0;
|
|
1584
1657
|
const fallbackMessage = isRawJsonErrorEcho(err.message) ? emptyProviderErrorMessage(err.status) : err.message;
|
|
1585
|
-
const
|
|
1658
|
+
const messageCandidate = bodyMessage ?? err.message;
|
|
1659
|
+
const message = isRawHtmlErrorEcho(messageCandidate) ? providerHtmlErrorMessage(err.status) : bodyType && bodyMessage ? `${bodyType}: ${bodyMessage}` : bodyMessage ?? fallbackMessage;
|
|
1586
1660
|
if (err.status === 429) {
|
|
1587
1661
|
const limit = readUnifiedRateLimit(err.headers);
|
|
1588
1662
|
const farOff = limit.resetsAt != null && limit.resetsAt * 1e3 - Date.now() > 6e4;
|
|
@@ -1764,7 +1838,11 @@ async function* runStream2(options) {
|
|
|
1764
1838
|
const providerName = options.provider ?? "openai";
|
|
1765
1839
|
const useStreaming = options.streaming !== false;
|
|
1766
1840
|
const client = createClient2(options);
|
|
1767
|
-
const
|
|
1841
|
+
const isKimiK3 = options.provider === "moonshot" && options.model === "kimi-k3";
|
|
1842
|
+
const isManagedKimiK3 = isKimiK3 && options.baseUrl?.replace(/\/+$/, "").endsWith("/coding/v1") === true;
|
|
1843
|
+
const isKimiK27 = options.provider === "moonshot" && options.model.startsWith("kimi-k2.7-code");
|
|
1844
|
+
const hasFixedKimiSampling = isKimiK3 || isKimiK27;
|
|
1845
|
+
const usesThinkingParam = options.provider === "glm" || options.provider === "moonshot" && !isKimiK3 && !isKimiK27 || options.provider === "xiaomi";
|
|
1768
1846
|
const downgradedImages = downgradeUnsupportedImages(options.messages, options.supportsImages);
|
|
1769
1847
|
const downgradedMessages = downgradeUnsupportedVideos(downgradedImages, options.supportsVideo);
|
|
1770
1848
|
if (options.provider === "moonshot") {
|
|
@@ -1776,7 +1854,9 @@ async function* runStream2(options) {
|
|
|
1776
1854
|
}
|
|
1777
1855
|
const messages = toOpenAIMessages(downgradedMessages, {
|
|
1778
1856
|
provider: options.provider,
|
|
1779
|
-
|
|
1857
|
+
// K3 and K2.7 preserve reasoning even when the user hides thinking in the
|
|
1858
|
+
// UI; keep assistant tool-call history wire-valid in that display mode.
|
|
1859
|
+
thinking: isKimiK3 || isKimiK27 || !!options.thinking,
|
|
1780
1860
|
supportsImages: options.supportsImages
|
|
1781
1861
|
});
|
|
1782
1862
|
const defaultTemp = options.provider === "glm" ? 0.6 : void 0;
|
|
@@ -1786,10 +1866,10 @@ async function* runStream2(options) {
|
|
|
1786
1866
|
messages,
|
|
1787
1867
|
stream: useStreaming,
|
|
1788
1868
|
...options.maxTokens ? { max_completion_tokens: options.maxTokens } : {},
|
|
1789
|
-
...effectiveTemp != null && !options.thinking ? { temperature: effectiveTemp } : {},
|
|
1790
|
-
...options.topP != null ? { top_p: options.topP } : {},
|
|
1869
|
+
...effectiveTemp != null && !options.thinking && !hasFixedKimiSampling ? { temperature: effectiveTemp } : {},
|
|
1870
|
+
...options.topP != null && !hasFixedKimiSampling ? { top_p: options.topP } : {},
|
|
1791
1871
|
...options.stop ? { stop: options.stop } : {},
|
|
1792
|
-
...options.thinking && !usesThinkingParam ? { reasoning_effort: toOpenAIReasoningEffort(options.thinking, options.model) } : {},
|
|
1872
|
+
...options.thinking && !usesThinkingParam && !isKimiK3 && !isKimiK27 ? { reasoning_effort: toOpenAIReasoningEffort(options.thinking, options.model) } : {},
|
|
1793
1873
|
...options.tools?.length ? { tools: toOpenAITools(options.tools) } : {},
|
|
1794
1874
|
...options.toolChoice && options.tools?.length ? { tool_choice: toOpenAIToolChoice(options.toolChoice) } : {},
|
|
1795
1875
|
...useStreaming ? { stream_options: { include_usage: true } } : {}
|
|
@@ -1799,13 +1879,21 @@ async function* runStream2(options) {
|
|
|
1799
1879
|
paramsAny.prompt_cache_key = normalizePromptCacheKey(options.promptCacheKey ?? "ezcoder");
|
|
1800
1880
|
if (options.provider === "openai" && options.model.startsWith("gpt-5.6")) {
|
|
1801
1881
|
paramsAny.prompt_cache_options = { mode: "implicit", ttl: "30m" };
|
|
1802
|
-
} else if ((options.cacheRetention ?? "short") === "long") {
|
|
1882
|
+
} else if (!isKimiK3 && (options.cacheRetention ?? "short") === "long") {
|
|
1803
1883
|
paramsAny.prompt_cache_retention = "24h";
|
|
1804
1884
|
}
|
|
1805
1885
|
}
|
|
1806
1886
|
if (options.provider === "openai" && options.serviceTier) {
|
|
1807
1887
|
params.service_tier = options.serviceTier;
|
|
1808
1888
|
}
|
|
1889
|
+
if (isKimiK3) {
|
|
1890
|
+
const paramsAny = params;
|
|
1891
|
+
if (isManagedKimiK3) {
|
|
1892
|
+
paramsAny.thinking = { type: "enabled", effort: "max", keep: "all" };
|
|
1893
|
+
} else {
|
|
1894
|
+
paramsAny.reasoning_effort = "max";
|
|
1895
|
+
}
|
|
1896
|
+
}
|
|
1809
1897
|
if (usesThinkingParam) {
|
|
1810
1898
|
if (options.thinking) {
|
|
1811
1899
|
params.thinking = { type: "enabled" };
|
|
@@ -2050,7 +2138,8 @@ function toError2(err, provider = "openai") {
|
|
|
2050
2138
|
const body = err.error;
|
|
2051
2139
|
const bodyMessage = typeof body?.message === "string" && body.message.trim() ? body.message.trim() : void 0;
|
|
2052
2140
|
const modelName = typeof body?.model === "string" ? body.model : "";
|
|
2053
|
-
const
|
|
2141
|
+
const messageCandidate = bodyMessage ?? err.message;
|
|
2142
|
+
const cleanMessage = isRawHtmlErrorEcho(messageCandidate) ? providerHtmlErrorMessage(err.status) : bodyMessage ? bodyMessage : isRawJsonErrorEcho(err.message) ? emptyProviderErrorMessage(err.status) : err.message;
|
|
2054
2143
|
let hint;
|
|
2055
2144
|
if (modelName === "codex-mini-latest" || cleanMessage.includes("codex-mini-latest")) {
|
|
2056
2145
|
hint = "codex-mini-latest requires an OpenAI Pro or Max subscription. Your account currently has access to GPT-5.4 and GPT-5.4 Mini.";
|
|
@@ -2100,6 +2189,7 @@ function toError2(err, provider = "openai") {
|
|
|
2100
2189
|
|
|
2101
2190
|
// src/providers/openai-codex.ts
|
|
2102
2191
|
import os from "os";
|
|
2192
|
+
import * as zstd from "@bokuweb/zstd-wasm";
|
|
2103
2193
|
|
|
2104
2194
|
// src/utils/sse.ts
|
|
2105
2195
|
function parseSseBuffer(buffer) {
|
|
@@ -2155,6 +2245,50 @@ function extractRequestIdFromMessage(message) {
|
|
|
2155
2245
|
// src/providers/openai-codex.ts
|
|
2156
2246
|
var DEFAULT_BASE_URL = "https://chatgpt.com/backend-api";
|
|
2157
2247
|
var CODEX_CLIENT_VERSION = "0.144.1";
|
|
2248
|
+
var CODEX_REQUEST_COMPRESSION_MIN_BYTES = 16 * 1024;
|
|
2249
|
+
var zstdInitPromise;
|
|
2250
|
+
async function encodeCodexRequest(body) {
|
|
2251
|
+
const json = JSON.stringify(body);
|
|
2252
|
+
const raw = new TextEncoder().encode(json);
|
|
2253
|
+
if (raw.byteLength < CODEX_REQUEST_COMPRESSION_MIN_BYTES) {
|
|
2254
|
+
return {
|
|
2255
|
+
body: json,
|
|
2256
|
+
compressed: false,
|
|
2257
|
+
rawBytes: raw.byteLength,
|
|
2258
|
+
encodedBytes: raw.byteLength
|
|
2259
|
+
};
|
|
2260
|
+
}
|
|
2261
|
+
try {
|
|
2262
|
+
zstdInitPromise ??= zstd.init();
|
|
2263
|
+
await zstdInitPromise;
|
|
2264
|
+
const compressed = Uint8Array.from(zstd.compress(raw));
|
|
2265
|
+
if (compressed.byteLength >= raw.byteLength) {
|
|
2266
|
+
return {
|
|
2267
|
+
body: json,
|
|
2268
|
+
compressed: false,
|
|
2269
|
+
rawBytes: raw.byteLength,
|
|
2270
|
+
encodedBytes: raw.byteLength
|
|
2271
|
+
};
|
|
2272
|
+
}
|
|
2273
|
+
return {
|
|
2274
|
+
body: compressed,
|
|
2275
|
+
compressed: true,
|
|
2276
|
+
rawBytes: raw.byteLength,
|
|
2277
|
+
encodedBytes: compressed.byteLength
|
|
2278
|
+
};
|
|
2279
|
+
} catch (error) {
|
|
2280
|
+
providerDiag("codex_request_compression_failed", {
|
|
2281
|
+
error: error instanceof Error ? error.message : String(error),
|
|
2282
|
+
rawBytes: raw.byteLength
|
|
2283
|
+
});
|
|
2284
|
+
return {
|
|
2285
|
+
body: json,
|
|
2286
|
+
compressed: false,
|
|
2287
|
+
rawBytes: raw.byteLength,
|
|
2288
|
+
encodedBytes: raw.byteLength
|
|
2289
|
+
};
|
|
2290
|
+
}
|
|
2291
|
+
}
|
|
2158
2292
|
function usesResponsesLite(model) {
|
|
2159
2293
|
return model.startsWith("gpt-5.6-");
|
|
2160
2294
|
}
|
|
@@ -2164,6 +2298,24 @@ function outputTextKey(itemId, contentIndex) {
|
|
|
2164
2298
|
function isVisibleOutputItem(itemType) {
|
|
2165
2299
|
return itemType === "message";
|
|
2166
2300
|
}
|
|
2301
|
+
function toCodexToolChoice(choice, tools) {
|
|
2302
|
+
const resolved = choice ?? "auto";
|
|
2303
|
+
if (typeof resolved === "object") {
|
|
2304
|
+
throw new EZCoderAIError(
|
|
2305
|
+
`OpenAI Codex does not support selecting the named tool \`${resolved.name}\`; use auto, none, or required.`,
|
|
2306
|
+
{ source: "capability" }
|
|
2307
|
+
);
|
|
2308
|
+
}
|
|
2309
|
+
if (resolved === "required" && !tools?.length) {
|
|
2310
|
+
throw new EZCoderAIError(
|
|
2311
|
+
"OpenAI Codex cannot require a tool call when no tools are configured.",
|
|
2312
|
+
{
|
|
2313
|
+
source: "capability"
|
|
2314
|
+
}
|
|
2315
|
+
);
|
|
2316
|
+
}
|
|
2317
|
+
return resolved;
|
|
2318
|
+
}
|
|
2167
2319
|
function streamOpenAICodex(options) {
|
|
2168
2320
|
return new StreamResult(runStream3(options), options.signal);
|
|
2169
2321
|
}
|
|
@@ -2180,7 +2332,7 @@ async function* runStream3(options) {
|
|
|
2180
2332
|
stream: true,
|
|
2181
2333
|
instructions: system,
|
|
2182
2334
|
input,
|
|
2183
|
-
tool_choice:
|
|
2335
|
+
tool_choice: toCodexToolChoice(options.toolChoice, options.tools),
|
|
2184
2336
|
parallel_tool_calls: !responsesLite,
|
|
2185
2337
|
include: ["reasoning.encrypted_content"]
|
|
2186
2338
|
};
|
|
@@ -2213,18 +2365,26 @@ async function* runStream3(options) {
|
|
|
2213
2365
|
headers["chatgpt-account-id"] = options.accountId;
|
|
2214
2366
|
}
|
|
2215
2367
|
if (options.transportSessionId) {
|
|
2216
|
-
|
|
2217
|
-
headers["
|
|
2218
|
-
|
|
2368
|
+
const transportSessionId = normalizePromptCacheKey(options.transportSessionId);
|
|
2369
|
+
headers["session_id"] = transportSessionId;
|
|
2370
|
+
headers["x-client-request-id"] = transportSessionId;
|
|
2371
|
+
}
|
|
2372
|
+
const encodedRequest = await encodeCodexRequest(body);
|
|
2373
|
+
if (encodedRequest.compressed) headers["Content-Encoding"] = "zstd";
|
|
2374
|
+
providerDiag("codex_request_body", {
|
|
2375
|
+
rawBytes: encodedRequest.rawBytes,
|
|
2376
|
+
encodedBytes: encodedRequest.encodedBytes,
|
|
2377
|
+
compressed: encodedRequest.compressed
|
|
2378
|
+
});
|
|
2219
2379
|
const response = await fetch(url, {
|
|
2220
2380
|
method: "POST",
|
|
2221
2381
|
headers,
|
|
2222
|
-
body:
|
|
2382
|
+
body: encodedRequest.body,
|
|
2223
2383
|
signal: options.signal
|
|
2224
2384
|
});
|
|
2225
2385
|
if (!response.ok) {
|
|
2226
2386
|
const text = await response.text().catch(() => "");
|
|
2227
|
-
const parsed = parseCodexErrorBody(text);
|
|
2387
|
+
const parsed = parseCodexErrorBody(text, response.status);
|
|
2228
2388
|
const message = parsed.message ?? `Codex API returned HTTP ${response.status}.`;
|
|
2229
2389
|
const requestId = parsed.requestId ?? readHeader(response.headers, "x-request-id", "openai-request-id", "x-oai-request-id");
|
|
2230
2390
|
const usageLimit = codexUsageLimitError(parsed.errorObj, response.status, requestId);
|
|
@@ -2618,13 +2778,14 @@ function toCodexTools(tools) {
|
|
|
2618
2778
|
strict: null
|
|
2619
2779
|
}));
|
|
2620
2780
|
}
|
|
2621
|
-
function parseCodexErrorBody(text) {
|
|
2781
|
+
function parseCodexErrorBody(text, statusCode) {
|
|
2622
2782
|
if (!text) return {};
|
|
2623
2783
|
try {
|
|
2624
2784
|
const parsed = JSON.parse(text);
|
|
2625
2785
|
const error = parsed.error;
|
|
2626
2786
|
const detail = parsed.detail;
|
|
2627
|
-
const
|
|
2787
|
+
const rawMessage = error?.message ?? parsed.message ?? (typeof detail === "string" ? detail : void 0);
|
|
2788
|
+
const message = rawMessage && isRawHtmlErrorEcho(rawMessage) ? providerHtmlErrorMessage(statusCode) : rawMessage;
|
|
2628
2789
|
const requestId = parsed.request_id ?? error?.request_id ?? (message ? extractRequestIdFromMessage(message) : void 0);
|
|
2629
2790
|
const errorObj = error ?? parsed;
|
|
2630
2791
|
return {
|
|
@@ -2633,8 +2794,12 @@ function parseCodexErrorBody(text) {
|
|
|
2633
2794
|
...errorObj ? { errorObj } : {}
|
|
2634
2795
|
};
|
|
2635
2796
|
} catch {
|
|
2636
|
-
const trimmed = text.trim()
|
|
2637
|
-
|
|
2797
|
+
const trimmed = text.trim();
|
|
2798
|
+
if (isRawHtmlErrorEcho(trimmed)) {
|
|
2799
|
+
return { message: providerHtmlErrorMessage(statusCode) };
|
|
2800
|
+
}
|
|
2801
|
+
const bounded = trimmed.slice(0, 240);
|
|
2802
|
+
return bounded ? { message: bounded } : {};
|
|
2638
2803
|
}
|
|
2639
2804
|
}
|
|
2640
2805
|
var CODEX_USAGE_LIMIT_CODE = /usage_limit_reached|usage_not_included/i;
|
|
@@ -3253,6 +3418,18 @@ providerRegistry.register("sakana", {
|
|
|
3253
3418
|
baseUrl: options.baseUrl ?? "https://api.sakana.ai/v1"
|
|
3254
3419
|
})
|
|
3255
3420
|
});
|
|
3421
|
+
providerRegistry.register("xai", {
|
|
3422
|
+
// xAI's public API (console.x.ai key) is OpenAI-compatible — ride the Chat
|
|
3423
|
+
// Completions transport like Moonshot/DeepSeek. Grok reasoning models take
|
|
3424
|
+
// top-level `reasoning_effort` (low/medium/high), which the shared thinking
|
|
3425
|
+
// path already sends. xAI's OAuth path exists but only via the Grok CLI's
|
|
3426
|
+
// private Responses proxy (cli-chat-proxy.grok.com) with reverse-engineered
|
|
3427
|
+
// attribution headers and account-tier gating — intentionally not wired.
|
|
3428
|
+
stream: (options) => streamOpenAI({
|
|
3429
|
+
...options,
|
|
3430
|
+
baseUrl: options.baseUrl ?? "https://api.x.ai/v1"
|
|
3431
|
+
})
|
|
3432
|
+
});
|
|
3256
3433
|
providerRegistry.register("minimax", {
|
|
3257
3434
|
stream: (options) => streamAnthropic({
|
|
3258
3435
|
...options,
|
|
@@ -3275,7 +3452,12 @@ function stream(options) {
|
|
|
3275
3452
|
if (options.supportsVideo !== true && messagesContainVideo(options.messages)) {
|
|
3276
3453
|
throw new VideoUnsupportedError();
|
|
3277
3454
|
}
|
|
3278
|
-
|
|
3455
|
+
const messages = clampProviderContextImages(
|
|
3456
|
+
options.messages,
|
|
3457
|
+
options.provider,
|
|
3458
|
+
options.supportsImages
|
|
3459
|
+
);
|
|
3460
|
+
return entry.stream(messages === options.messages ? options : { ...options, messages });
|
|
3279
3461
|
}
|
|
3280
3462
|
function messagesContainVideo(messages) {
|
|
3281
3463
|
for (const msg of messages) {
|
|
@@ -3380,6 +3562,125 @@ Original: ${message}`;
|
|
|
3380
3562
|
return message;
|
|
3381
3563
|
}
|
|
3382
3564
|
|
|
3565
|
+
// src/redaction.ts
|
|
3566
|
+
var REDACTED = "[REDACTED]";
|
|
3567
|
+
var TRUNCATED = "[TRUNCATED]";
|
|
3568
|
+
var CIRCULAR = "[CIRCULAR]";
|
|
3569
|
+
var SENSITIVE_NAME = /(?:^|[_-])(?:api[_-]?key|access[_-]?token|refresh[_-]?token|token|key|auth(?:orization)?|bearer|cookie|credential|private[_-]?key|password|passwd|secret)(?:$|[_-])/i;
|
|
3570
|
+
var SENSITIVE_ASSIGNMENT = /\b((?:api[_-]?key|access[_-]?token|refresh[_-]?token|token|key|auth(?:orization)?|bearer|cookie|credential|private[_-]?key|password|passwd|secret))\b(\s*[=:]\s*)(["']?)([^\s,"';}]+)\3/gi;
|
|
3571
|
+
function escaped(value) {
|
|
3572
|
+
return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
3573
|
+
}
|
|
3574
|
+
function normalizedSecrets(secrets) {
|
|
3575
|
+
if (!secrets) return [];
|
|
3576
|
+
return [...new Set([...secrets].filter((value) => value.length >= 8 && value !== REDACTED))].sort(
|
|
3577
|
+
(a, b) => b.length - a.length
|
|
3578
|
+
);
|
|
3579
|
+
}
|
|
3580
|
+
function environmentSecrets(env) {
|
|
3581
|
+
const values = /* @__PURE__ */ new Set();
|
|
3582
|
+
for (const [name, value] of Object.entries(env)) {
|
|
3583
|
+
if (!value || value.length < 8 || value === REDACTED || !SENSITIVE_NAME.test(name)) continue;
|
|
3584
|
+
values.add(value);
|
|
3585
|
+
}
|
|
3586
|
+
return [...values].sort((a, b) => b.length - a.length);
|
|
3587
|
+
}
|
|
3588
|
+
function redactText(text, options = {}) {
|
|
3589
|
+
let result = text;
|
|
3590
|
+
result = result.replace(
|
|
3591
|
+
/-----BEGIN (?:[A-Z0-9 ]+ )?PRIVATE KEY-----[\s\S]*?-----END (?:[A-Z0-9 ]+ )?PRIVATE KEY-----/g,
|
|
3592
|
+
REDACTED
|
|
3593
|
+
);
|
|
3594
|
+
result = result.replace(/\b([a-z][a-z0-9+.-]*:\/\/)[^\s/@:]+:[^\s/@]+@/gi, `$1${REDACTED}@`);
|
|
3595
|
+
result = result.replace(
|
|
3596
|
+
/\b(authorization\s*[:=]\s*)(?:bearer|basic)\s+[^\s,;]+/gi,
|
|
3597
|
+
`$1${REDACTED}`
|
|
3598
|
+
);
|
|
3599
|
+
result = result.replace(/\b(bearer|basic)\s+[A-Za-z0-9+/_.=-]{8,}/gi, `$1 ${REDACTED}`);
|
|
3600
|
+
result = result.replace(/\b(cookie|set-cookie)(\s*[:=]\s*)[^\r\n]+/gi, `$1$2${REDACTED}`);
|
|
3601
|
+
result = result.replace(
|
|
3602
|
+
/\beyJ[A-Za-z0-9_-]{6,}\.[A-Za-z0-9_-]{6,}\.[A-Za-z0-9_-]{6,}\b/g,
|
|
3603
|
+
REDACTED
|
|
3604
|
+
);
|
|
3605
|
+
result = result.replace(
|
|
3606
|
+
/\b(?:sk-(?:ant-|proj-)?|xox[baprs]-|gh[pousr]_|github_pat_|AIza)[A-Za-z0-9_-]{12,}\b/g,
|
|
3607
|
+
REDACTED
|
|
3608
|
+
);
|
|
3609
|
+
result = result.replace(
|
|
3610
|
+
SENSITIVE_ASSIGNMENT,
|
|
3611
|
+
(_match, name, separator) => `${name}${separator}${REDACTED}`
|
|
3612
|
+
);
|
|
3613
|
+
for (const secret of normalizedSecrets(options.secrets)) {
|
|
3614
|
+
result = result.replace(new RegExp(escaped(secret), "g"), REDACTED);
|
|
3615
|
+
}
|
|
3616
|
+
const maxStringLength = options.maxStringLength ?? 1e6;
|
|
3617
|
+
if (result.length > maxStringLength) {
|
|
3618
|
+
result = `${result.slice(0, maxStringLength)}${TRUNCATED}`;
|
|
3619
|
+
}
|
|
3620
|
+
return result;
|
|
3621
|
+
}
|
|
3622
|
+
function isBinary(value) {
|
|
3623
|
+
return value instanceof ArrayBuffer || ArrayBuffer.isView(value) || typeof Blob !== "undefined" && value instanceof Blob;
|
|
3624
|
+
}
|
|
3625
|
+
function isMediaObject(value) {
|
|
3626
|
+
return (value.type === "image" || value.type === "video") && (typeof value.data === "string" || typeof value.url === "string");
|
|
3627
|
+
}
|
|
3628
|
+
function redactValue(value, options = {}) {
|
|
3629
|
+
const maxDepth = options.maxDepth ?? 20;
|
|
3630
|
+
const maxEntries = options.maxEntries ?? 1e4;
|
|
3631
|
+
const seen = /* @__PURE__ */ new WeakSet();
|
|
3632
|
+
let entries = 0;
|
|
3633
|
+
const visit = (current, depth, sensitive = false) => {
|
|
3634
|
+
if (typeof current === "string") {
|
|
3635
|
+
if (sensitive && current.length > 0 && current !== REDACTED) return REDACTED;
|
|
3636
|
+
return redactText(current, options);
|
|
3637
|
+
}
|
|
3638
|
+
if (current === null || current === void 0 || typeof current === "number" || typeof current === "boolean" || typeof current === "bigint") {
|
|
3639
|
+
return current;
|
|
3640
|
+
}
|
|
3641
|
+
if (typeof current !== "object") return current;
|
|
3642
|
+
if (isBinary(current)) return current;
|
|
3643
|
+
if (current instanceof Date) return new Date(current.getTime());
|
|
3644
|
+
if (depth >= maxDepth) return TRUNCATED;
|
|
3645
|
+
if (seen.has(current)) return CIRCULAR;
|
|
3646
|
+
seen.add(current);
|
|
3647
|
+
if (current instanceof Error) {
|
|
3648
|
+
const error = {
|
|
3649
|
+
name: current.name,
|
|
3650
|
+
message: visit(current.message, depth + 1),
|
|
3651
|
+
stack: visit(current.stack, depth + 1)
|
|
3652
|
+
};
|
|
3653
|
+
for (const [key, child] of Object.entries(current)) {
|
|
3654
|
+
error[key] = visit(child, depth + 1, SENSITIVE_NAME.test(key));
|
|
3655
|
+
}
|
|
3656
|
+
return error;
|
|
3657
|
+
}
|
|
3658
|
+
if (Array.isArray(current)) {
|
|
3659
|
+
const clone2 = [];
|
|
3660
|
+
for (const child of current) {
|
|
3661
|
+
if (++entries > maxEntries) {
|
|
3662
|
+
clone2.push(TRUNCATED);
|
|
3663
|
+
break;
|
|
3664
|
+
}
|
|
3665
|
+
clone2.push(visit(child, depth + 1));
|
|
3666
|
+
}
|
|
3667
|
+
return clone2;
|
|
3668
|
+
}
|
|
3669
|
+
const record = current;
|
|
3670
|
+
if (isMediaObject(record)) return { ...record };
|
|
3671
|
+
const clone = {};
|
|
3672
|
+
for (const [key, child] of Object.entries(record)) {
|
|
3673
|
+
if (++entries > maxEntries) {
|
|
3674
|
+
clone[TRUNCATED] = true;
|
|
3675
|
+
break;
|
|
3676
|
+
}
|
|
3677
|
+
clone[key] = visit(child, depth + 1, SENSITIVE_NAME.test(key));
|
|
3678
|
+
}
|
|
3679
|
+
return clone;
|
|
3680
|
+
};
|
|
3681
|
+
return visit(value, 0);
|
|
3682
|
+
}
|
|
3683
|
+
|
|
3383
3684
|
// src/providers/palsu.ts
|
|
3384
3685
|
function palsuText(text) {
|
|
3385
3686
|
return { role: "assistant", content: text ? [{ type: "text", text }] : [] };
|
|
@@ -3535,8 +3836,11 @@ export {
|
|
|
3535
3836
|
EZCoderAIError,
|
|
3536
3837
|
EventStream,
|
|
3537
3838
|
ProviderError,
|
|
3839
|
+
REDACTED as REDACTION_MARKER,
|
|
3538
3840
|
StreamResult,
|
|
3841
|
+
clampProviderContextImages,
|
|
3539
3842
|
classifyProviderError,
|
|
3843
|
+
environmentSecrets,
|
|
3540
3844
|
formatError,
|
|
3541
3845
|
formatErrorForDisplay,
|
|
3542
3846
|
isHardBillingMessage,
|
|
@@ -3547,6 +3851,8 @@ export {
|
|
|
3547
3851
|
palsuToolCall,
|
|
3548
3852
|
prewarmAnthropicCache,
|
|
3549
3853
|
providerRegistry,
|
|
3854
|
+
redactText,
|
|
3855
|
+
redactValue,
|
|
3550
3856
|
registerPalsuProvider,
|
|
3551
3857
|
setProviderDiagnostic,
|
|
3552
3858
|
stream,
|