@prestyj/ai 5.6.0 → 5.7.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/dist/index.cjs +242 -14
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +28 -1
- package/dist/index.d.ts +28 -1
- package/dist/index.js +237 -14
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -33,8 +33,11 @@ __export(index_exports, {
|
|
|
33
33
|
EZCoderAIError: () => EZCoderAIError,
|
|
34
34
|
EventStream: () => EventStream,
|
|
35
35
|
ProviderError: () => ProviderError,
|
|
36
|
+
REDACTION_MARKER: () => REDACTED,
|
|
36
37
|
StreamResult: () => StreamResult,
|
|
38
|
+
clampProviderContextImages: () => clampProviderContextImages,
|
|
37
39
|
classifyProviderError: () => classifyProviderError,
|
|
40
|
+
environmentSecrets: () => environmentSecrets,
|
|
38
41
|
formatError: () => formatError,
|
|
39
42
|
formatErrorForDisplay: () => formatErrorForDisplay,
|
|
40
43
|
isHardBillingMessage: () => isHardBillingMessage,
|
|
@@ -45,6 +48,8 @@ __export(index_exports, {
|
|
|
45
48
|
palsuToolCall: () => palsuToolCall,
|
|
46
49
|
prewarmAnthropicCache: () => prewarmAnthropicCache,
|
|
47
50
|
providerRegistry: () => providerRegistry,
|
|
51
|
+
redactText: () => redactText,
|
|
52
|
+
redactValue: () => redactValue,
|
|
48
53
|
registerPalsuProvider: () => registerPalsuProvider,
|
|
49
54
|
setProviderDiagnostic: () => setProviderDiagnostic,
|
|
50
55
|
stream: () => stream,
|
|
@@ -157,13 +162,20 @@ function isRawJsonErrorEcho(message) {
|
|
|
157
162
|
return false;
|
|
158
163
|
}
|
|
159
164
|
}
|
|
165
|
+
function isRawHtmlErrorEcho(message) {
|
|
166
|
+
const withoutStatus = message.trimStart().replace(/^\d{3}\s+/, "").trimStart();
|
|
167
|
+
return /^<!doctype\s+html(?:\s|>)/i.test(withoutStatus) || /^<html(?:\s|>)/i.test(withoutStatus);
|
|
168
|
+
}
|
|
169
|
+
function providerHtmlErrorMessage(statusCode) {
|
|
170
|
+
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.";
|
|
171
|
+
}
|
|
160
172
|
function emptyProviderErrorMessage(statusCode) {
|
|
161
173
|
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.";
|
|
162
174
|
}
|
|
163
175
|
function formatError(err) {
|
|
164
176
|
if (err instanceof ProviderError) {
|
|
165
177
|
const name = providerDisplayName(err.provider);
|
|
166
|
-
const cleanMessage = cleanProviderMessage(err.message);
|
|
178
|
+
const cleanMessage = cleanProviderMessage(err.message, err.statusCode);
|
|
167
179
|
if (isMythosAccessError(cleanMessage)) {
|
|
168
180
|
return {
|
|
169
181
|
headline: "Claude Mythos 5 is invitation-only.",
|
|
@@ -258,8 +270,9 @@ function formatErrorForDisplay(err) {
|
|
|
258
270
|
lines.push(` \u2192 ${f.guidance}`);
|
|
259
271
|
return lines.join("\n");
|
|
260
272
|
}
|
|
261
|
-
function cleanProviderMessage(message) {
|
|
262
|
-
|
|
273
|
+
function cleanProviderMessage(message, statusCode) {
|
|
274
|
+
const clean = message.replace(/^\[[^\]]+\]\s*/, "").trim();
|
|
275
|
+
return isRawHtmlErrorEcho(clean) ? providerHtmlErrorMessage(statusCode) : clean;
|
|
263
276
|
}
|
|
264
277
|
function inferSource(err) {
|
|
265
278
|
const msg = err.message.toLowerCase();
|
|
@@ -620,6 +633,66 @@ function toAnthropicAssistantContent(content, preserveThinking, idMap) {
|
|
|
620
633
|
return true;
|
|
621
634
|
}).map((part) => toAnthropicAssistantPart(part, idMap)).filter((b) => b !== null);
|
|
622
635
|
}
|
|
636
|
+
var PROVIDER_IMAGE_LIMIT_PLACEHOLDER = "[image omitted: provider image limit]";
|
|
637
|
+
var PROVIDER_IMAGE_BUDGETS = {
|
|
638
|
+
anthropic: 90,
|
|
639
|
+
minimax: 90,
|
|
640
|
+
openai: 200,
|
|
641
|
+
gemini: 200,
|
|
642
|
+
openrouter: 90
|
|
643
|
+
};
|
|
644
|
+
function countContextImages(messages) {
|
|
645
|
+
let count = 0;
|
|
646
|
+
for (const message of messages) {
|
|
647
|
+
if (message.role === "user" && Array.isArray(message.content)) {
|
|
648
|
+
count += message.content.filter((part) => part.type === "image").length;
|
|
649
|
+
} else if (message.role === "tool") {
|
|
650
|
+
for (const result of message.content) {
|
|
651
|
+
if (Array.isArray(result.content)) {
|
|
652
|
+
count += result.content.filter((part) => part.type === "image").length;
|
|
653
|
+
}
|
|
654
|
+
}
|
|
655
|
+
}
|
|
656
|
+
}
|
|
657
|
+
return count;
|
|
658
|
+
}
|
|
659
|
+
function clampProviderContextImages(messages, provider, supportsImages) {
|
|
660
|
+
if (supportsImages === false) return messages;
|
|
661
|
+
const budget = PROVIDER_IMAGE_BUDGETS[provider] ?? 5;
|
|
662
|
+
let remainingToRemove = countContextImages(messages) - budget;
|
|
663
|
+
if (remainingToRemove <= 0) return messages;
|
|
664
|
+
return messages.map((message) => {
|
|
665
|
+
if (message.role === "user" && Array.isArray(message.content)) {
|
|
666
|
+
const content = message.content.filter((part) => {
|
|
667
|
+
if (part.type !== "image" || remainingToRemove <= 0) return true;
|
|
668
|
+
remainingToRemove--;
|
|
669
|
+
return false;
|
|
670
|
+
});
|
|
671
|
+
return {
|
|
672
|
+
...message,
|
|
673
|
+
content: content.length > 0 ? content : [{ type: "text", text: PROVIDER_IMAGE_LIMIT_PLACEHOLDER }]
|
|
674
|
+
};
|
|
675
|
+
}
|
|
676
|
+
if (message.role === "tool") {
|
|
677
|
+
return {
|
|
678
|
+
...message,
|
|
679
|
+
content: message.content.map((result) => {
|
|
680
|
+
if (!Array.isArray(result.content)) return result;
|
|
681
|
+
const content = result.content.filter((part) => {
|
|
682
|
+
if (part.type !== "image" || remainingToRemove <= 0) return true;
|
|
683
|
+
remainingToRemove--;
|
|
684
|
+
return false;
|
|
685
|
+
});
|
|
686
|
+
return {
|
|
687
|
+
...result,
|
|
688
|
+
content: content.length > 0 ? content : [{ type: "text", text: PROVIDER_IMAGE_LIMIT_PLACEHOLDER }]
|
|
689
|
+
};
|
|
690
|
+
})
|
|
691
|
+
};
|
|
692
|
+
}
|
|
693
|
+
return message;
|
|
694
|
+
});
|
|
695
|
+
}
|
|
623
696
|
var NON_VISION_USER_IMAGE_PLACEHOLDER = "(image omitted: model does not support images)";
|
|
624
697
|
var NON_VISION_TOOL_IMAGE_PLACEHOLDER = "(tool image omitted: model does not support images)";
|
|
625
698
|
var NON_VIDEO_USER_PLACEHOLDER = "(video omitted: model does not support video)";
|
|
@@ -1637,7 +1710,8 @@ function toError(err) {
|
|
|
1637
1710
|
const bodyMessage = typeof nestedError?.message === "string" && nestedError.message.trim() ? nestedError.message.trim() : typeof errorBody?.message === "string" && errorBody.message.trim() ? errorBody.message.trim() : void 0;
|
|
1638
1711
|
const bodyType = typeof nestedError?.type === "string" ? nestedError.type : typeof errorBody?.type === "string" ? errorBody.type : typeof err.type === "string" ? err.type : void 0;
|
|
1639
1712
|
const fallbackMessage = isRawJsonErrorEcho(err.message) ? emptyProviderErrorMessage(err.status) : err.message;
|
|
1640
|
-
const
|
|
1713
|
+
const messageCandidate = bodyMessage ?? err.message;
|
|
1714
|
+
const message = isRawHtmlErrorEcho(messageCandidate) ? providerHtmlErrorMessage(err.status) : bodyType && bodyMessage ? `${bodyType}: ${bodyMessage}` : bodyMessage ?? fallbackMessage;
|
|
1641
1715
|
if (err.status === 429) {
|
|
1642
1716
|
const limit = readUnifiedRateLimit(err.headers);
|
|
1643
1717
|
const farOff = limit.resetsAt != null && limit.resetsAt * 1e3 - Date.now() > 6e4;
|
|
@@ -2105,7 +2179,8 @@ function toError2(err, provider = "openai") {
|
|
|
2105
2179
|
const body = err.error;
|
|
2106
2180
|
const bodyMessage = typeof body?.message === "string" && body.message.trim() ? body.message.trim() : void 0;
|
|
2107
2181
|
const modelName = typeof body?.model === "string" ? body.model : "";
|
|
2108
|
-
const
|
|
2182
|
+
const messageCandidate = bodyMessage ?? err.message;
|
|
2183
|
+
const cleanMessage = isRawHtmlErrorEcho(messageCandidate) ? providerHtmlErrorMessage(err.status) : bodyMessage ? bodyMessage : isRawJsonErrorEcho(err.message) ? emptyProviderErrorMessage(err.status) : err.message;
|
|
2109
2184
|
let hint;
|
|
2110
2185
|
if (modelName === "codex-mini-latest" || cleanMessage.includes("codex-mini-latest")) {
|
|
2111
2186
|
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.";
|
|
@@ -2219,6 +2294,24 @@ function outputTextKey(itemId, contentIndex) {
|
|
|
2219
2294
|
function isVisibleOutputItem(itemType) {
|
|
2220
2295
|
return itemType === "message";
|
|
2221
2296
|
}
|
|
2297
|
+
function toCodexToolChoice(choice, tools) {
|
|
2298
|
+
const resolved = choice ?? "auto";
|
|
2299
|
+
if (typeof resolved === "object") {
|
|
2300
|
+
throw new EZCoderAIError(
|
|
2301
|
+
`OpenAI Codex does not support selecting the named tool \`${resolved.name}\`; use auto, none, or required.`,
|
|
2302
|
+
{ source: "capability" }
|
|
2303
|
+
);
|
|
2304
|
+
}
|
|
2305
|
+
if (resolved === "required" && !tools?.length) {
|
|
2306
|
+
throw new EZCoderAIError(
|
|
2307
|
+
"OpenAI Codex cannot require a tool call when no tools are configured.",
|
|
2308
|
+
{
|
|
2309
|
+
source: "capability"
|
|
2310
|
+
}
|
|
2311
|
+
);
|
|
2312
|
+
}
|
|
2313
|
+
return resolved;
|
|
2314
|
+
}
|
|
2222
2315
|
function streamOpenAICodex(options) {
|
|
2223
2316
|
return new StreamResult(runStream3(options), options.signal);
|
|
2224
2317
|
}
|
|
@@ -2235,7 +2328,7 @@ async function* runStream3(options) {
|
|
|
2235
2328
|
stream: true,
|
|
2236
2329
|
instructions: system,
|
|
2237
2330
|
input,
|
|
2238
|
-
tool_choice:
|
|
2331
|
+
tool_choice: toCodexToolChoice(options.toolChoice, options.tools),
|
|
2239
2332
|
parallel_tool_calls: !responsesLite,
|
|
2240
2333
|
include: ["reasoning.encrypted_content"]
|
|
2241
2334
|
};
|
|
@@ -2268,8 +2361,9 @@ async function* runStream3(options) {
|
|
|
2268
2361
|
headers["chatgpt-account-id"] = options.accountId;
|
|
2269
2362
|
}
|
|
2270
2363
|
if (options.transportSessionId) {
|
|
2271
|
-
|
|
2272
|
-
headers["
|
|
2364
|
+
const transportSessionId = normalizePromptCacheKey(options.transportSessionId);
|
|
2365
|
+
headers["session_id"] = transportSessionId;
|
|
2366
|
+
headers["x-client-request-id"] = transportSessionId;
|
|
2273
2367
|
}
|
|
2274
2368
|
const response = await fetch(url, {
|
|
2275
2369
|
method: "POST",
|
|
@@ -2279,7 +2373,7 @@ async function* runStream3(options) {
|
|
|
2279
2373
|
});
|
|
2280
2374
|
if (!response.ok) {
|
|
2281
2375
|
const text = await response.text().catch(() => "");
|
|
2282
|
-
const parsed = parseCodexErrorBody(text);
|
|
2376
|
+
const parsed = parseCodexErrorBody(text, response.status);
|
|
2283
2377
|
const message = parsed.message ?? `Codex API returned HTTP ${response.status}.`;
|
|
2284
2378
|
const requestId = parsed.requestId ?? readHeader(response.headers, "x-request-id", "openai-request-id", "x-oai-request-id");
|
|
2285
2379
|
const usageLimit = codexUsageLimitError(parsed.errorObj, response.status, requestId);
|
|
@@ -2673,13 +2767,14 @@ function toCodexTools(tools) {
|
|
|
2673
2767
|
strict: null
|
|
2674
2768
|
}));
|
|
2675
2769
|
}
|
|
2676
|
-
function parseCodexErrorBody(text) {
|
|
2770
|
+
function parseCodexErrorBody(text, statusCode) {
|
|
2677
2771
|
if (!text) return {};
|
|
2678
2772
|
try {
|
|
2679
2773
|
const parsed = JSON.parse(text);
|
|
2680
2774
|
const error = parsed.error;
|
|
2681
2775
|
const detail = parsed.detail;
|
|
2682
|
-
const
|
|
2776
|
+
const rawMessage = error?.message ?? parsed.message ?? (typeof detail === "string" ? detail : void 0);
|
|
2777
|
+
const message = rawMessage && isRawHtmlErrorEcho(rawMessage) ? providerHtmlErrorMessage(statusCode) : rawMessage;
|
|
2683
2778
|
const requestId = parsed.request_id ?? error?.request_id ?? (message ? extractRequestIdFromMessage(message) : void 0);
|
|
2684
2779
|
const errorObj = error ?? parsed;
|
|
2685
2780
|
return {
|
|
@@ -2688,8 +2783,12 @@ function parseCodexErrorBody(text) {
|
|
|
2688
2783
|
...errorObj ? { errorObj } : {}
|
|
2689
2784
|
};
|
|
2690
2785
|
} catch {
|
|
2691
|
-
const trimmed = text.trim()
|
|
2692
|
-
|
|
2786
|
+
const trimmed = text.trim();
|
|
2787
|
+
if (isRawHtmlErrorEcho(trimmed)) {
|
|
2788
|
+
return { message: providerHtmlErrorMessage(statusCode) };
|
|
2789
|
+
}
|
|
2790
|
+
const bounded = trimmed.slice(0, 240);
|
|
2791
|
+
return bounded ? { message: bounded } : {};
|
|
2693
2792
|
}
|
|
2694
2793
|
}
|
|
2695
2794
|
var CODEX_USAGE_LIMIT_CODE = /usage_limit_reached|usage_not_included/i;
|
|
@@ -3330,7 +3429,12 @@ function stream(options) {
|
|
|
3330
3429
|
if (options.supportsVideo !== true && messagesContainVideo(options.messages)) {
|
|
3331
3430
|
throw new VideoUnsupportedError();
|
|
3332
3431
|
}
|
|
3333
|
-
|
|
3432
|
+
const messages = clampProviderContextImages(
|
|
3433
|
+
options.messages,
|
|
3434
|
+
options.provider,
|
|
3435
|
+
options.supportsImages
|
|
3436
|
+
);
|
|
3437
|
+
return entry.stream(messages === options.messages ? options : { ...options, messages });
|
|
3334
3438
|
}
|
|
3335
3439
|
function messagesContainVideo(messages) {
|
|
3336
3440
|
for (const msg of messages) {
|
|
@@ -3435,6 +3539,125 @@ Original: ${message}`;
|
|
|
3435
3539
|
return message;
|
|
3436
3540
|
}
|
|
3437
3541
|
|
|
3542
|
+
// src/redaction.ts
|
|
3543
|
+
var REDACTED = "[REDACTED]";
|
|
3544
|
+
var TRUNCATED = "[TRUNCATED]";
|
|
3545
|
+
var CIRCULAR = "[CIRCULAR]";
|
|
3546
|
+
var SENSITIVE_NAME = /(?:^|[_-])(?:api[_-]?key|access[_-]?token|refresh[_-]?token|token|key|auth(?:orization)?|bearer|cookie|credential|private[_-]?key|password|passwd|secret)(?:$|[_-])/i;
|
|
3547
|
+
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;
|
|
3548
|
+
function escaped(value) {
|
|
3549
|
+
return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
3550
|
+
}
|
|
3551
|
+
function normalizedSecrets(secrets) {
|
|
3552
|
+
if (!secrets) return [];
|
|
3553
|
+
return [...new Set([...secrets].filter((value) => value.length >= 8 && value !== REDACTED))].sort(
|
|
3554
|
+
(a, b) => b.length - a.length
|
|
3555
|
+
);
|
|
3556
|
+
}
|
|
3557
|
+
function environmentSecrets(env) {
|
|
3558
|
+
const values = /* @__PURE__ */ new Set();
|
|
3559
|
+
for (const [name, value] of Object.entries(env)) {
|
|
3560
|
+
if (!value || value.length < 8 || value === REDACTED || !SENSITIVE_NAME.test(name)) continue;
|
|
3561
|
+
values.add(value);
|
|
3562
|
+
}
|
|
3563
|
+
return [...values].sort((a, b) => b.length - a.length);
|
|
3564
|
+
}
|
|
3565
|
+
function redactText(text, options = {}) {
|
|
3566
|
+
let result = text;
|
|
3567
|
+
result = result.replace(
|
|
3568
|
+
/-----BEGIN (?:[A-Z0-9 ]+ )?PRIVATE KEY-----[\s\S]*?-----END (?:[A-Z0-9 ]+ )?PRIVATE KEY-----/g,
|
|
3569
|
+
REDACTED
|
|
3570
|
+
);
|
|
3571
|
+
result = result.replace(/\b([a-z][a-z0-9+.-]*:\/\/)[^\s/@:]+:[^\s/@]+@/gi, `$1${REDACTED}@`);
|
|
3572
|
+
result = result.replace(
|
|
3573
|
+
/\b(authorization\s*[:=]\s*)(?:bearer|basic)\s+[^\s,;]+/gi,
|
|
3574
|
+
`$1${REDACTED}`
|
|
3575
|
+
);
|
|
3576
|
+
result = result.replace(/\b(bearer|basic)\s+[A-Za-z0-9+/_.=-]{8,}/gi, `$1 ${REDACTED}`);
|
|
3577
|
+
result = result.replace(/\b(cookie|set-cookie)(\s*[:=]\s*)[^\r\n]+/gi, `$1$2${REDACTED}`);
|
|
3578
|
+
result = result.replace(
|
|
3579
|
+
/\beyJ[A-Za-z0-9_-]{6,}\.[A-Za-z0-9_-]{6,}\.[A-Za-z0-9_-]{6,}\b/g,
|
|
3580
|
+
REDACTED
|
|
3581
|
+
);
|
|
3582
|
+
result = result.replace(
|
|
3583
|
+
/\b(?:sk-(?:ant-|proj-)?|xox[baprs]-|gh[pousr]_|github_pat_|AIza)[A-Za-z0-9_-]{12,}\b/g,
|
|
3584
|
+
REDACTED
|
|
3585
|
+
);
|
|
3586
|
+
result = result.replace(
|
|
3587
|
+
SENSITIVE_ASSIGNMENT,
|
|
3588
|
+
(_match, name, separator) => `${name}${separator}${REDACTED}`
|
|
3589
|
+
);
|
|
3590
|
+
for (const secret of normalizedSecrets(options.secrets)) {
|
|
3591
|
+
result = result.replace(new RegExp(escaped(secret), "g"), REDACTED);
|
|
3592
|
+
}
|
|
3593
|
+
const maxStringLength = options.maxStringLength ?? 1e6;
|
|
3594
|
+
if (result.length > maxStringLength) {
|
|
3595
|
+
result = `${result.slice(0, maxStringLength)}${TRUNCATED}`;
|
|
3596
|
+
}
|
|
3597
|
+
return result;
|
|
3598
|
+
}
|
|
3599
|
+
function isBinary(value) {
|
|
3600
|
+
return value instanceof ArrayBuffer || ArrayBuffer.isView(value) || typeof Blob !== "undefined" && value instanceof Blob;
|
|
3601
|
+
}
|
|
3602
|
+
function isMediaObject(value) {
|
|
3603
|
+
return (value.type === "image" || value.type === "video") && (typeof value.data === "string" || typeof value.url === "string");
|
|
3604
|
+
}
|
|
3605
|
+
function redactValue(value, options = {}) {
|
|
3606
|
+
const maxDepth = options.maxDepth ?? 20;
|
|
3607
|
+
const maxEntries = options.maxEntries ?? 1e4;
|
|
3608
|
+
const seen = /* @__PURE__ */ new WeakSet();
|
|
3609
|
+
let entries = 0;
|
|
3610
|
+
const visit = (current, depth, sensitive = false) => {
|
|
3611
|
+
if (typeof current === "string") {
|
|
3612
|
+
if (sensitive && current.length > 0 && current !== REDACTED) return REDACTED;
|
|
3613
|
+
return redactText(current, options);
|
|
3614
|
+
}
|
|
3615
|
+
if (current === null || current === void 0 || typeof current === "number" || typeof current === "boolean" || typeof current === "bigint") {
|
|
3616
|
+
return current;
|
|
3617
|
+
}
|
|
3618
|
+
if (typeof current !== "object") return current;
|
|
3619
|
+
if (isBinary(current)) return current;
|
|
3620
|
+
if (current instanceof Date) return new Date(current.getTime());
|
|
3621
|
+
if (depth >= maxDepth) return TRUNCATED;
|
|
3622
|
+
if (seen.has(current)) return CIRCULAR;
|
|
3623
|
+
seen.add(current);
|
|
3624
|
+
if (current instanceof Error) {
|
|
3625
|
+
const error = {
|
|
3626
|
+
name: current.name,
|
|
3627
|
+
message: visit(current.message, depth + 1),
|
|
3628
|
+
stack: visit(current.stack, depth + 1)
|
|
3629
|
+
};
|
|
3630
|
+
for (const [key, child] of Object.entries(current)) {
|
|
3631
|
+
error[key] = visit(child, depth + 1, SENSITIVE_NAME.test(key));
|
|
3632
|
+
}
|
|
3633
|
+
return error;
|
|
3634
|
+
}
|
|
3635
|
+
if (Array.isArray(current)) {
|
|
3636
|
+
const clone2 = [];
|
|
3637
|
+
for (const child of current) {
|
|
3638
|
+
if (++entries > maxEntries) {
|
|
3639
|
+
clone2.push(TRUNCATED);
|
|
3640
|
+
break;
|
|
3641
|
+
}
|
|
3642
|
+
clone2.push(visit(child, depth + 1));
|
|
3643
|
+
}
|
|
3644
|
+
return clone2;
|
|
3645
|
+
}
|
|
3646
|
+
const record = current;
|
|
3647
|
+
if (isMediaObject(record)) return { ...record };
|
|
3648
|
+
const clone = {};
|
|
3649
|
+
for (const [key, child] of Object.entries(record)) {
|
|
3650
|
+
if (++entries > maxEntries) {
|
|
3651
|
+
clone[TRUNCATED] = true;
|
|
3652
|
+
break;
|
|
3653
|
+
}
|
|
3654
|
+
clone[key] = visit(child, depth + 1, SENSITIVE_NAME.test(key));
|
|
3655
|
+
}
|
|
3656
|
+
return clone;
|
|
3657
|
+
};
|
|
3658
|
+
return visit(value, 0);
|
|
3659
|
+
}
|
|
3660
|
+
|
|
3438
3661
|
// src/providers/palsu.ts
|
|
3439
3662
|
function palsuText(text) {
|
|
3440
3663
|
return { role: "assistant", content: text ? [{ type: "text", text }] : [] };
|
|
@@ -3591,8 +3814,11 @@ function registerPalsuProvider(config) {
|
|
|
3591
3814
|
EZCoderAIError,
|
|
3592
3815
|
EventStream,
|
|
3593
3816
|
ProviderError,
|
|
3817
|
+
REDACTION_MARKER,
|
|
3594
3818
|
StreamResult,
|
|
3819
|
+
clampProviderContextImages,
|
|
3595
3820
|
classifyProviderError,
|
|
3821
|
+
environmentSecrets,
|
|
3596
3822
|
formatError,
|
|
3597
3823
|
formatErrorForDisplay,
|
|
3598
3824
|
isHardBillingMessage,
|
|
@@ -3603,6 +3829,8 @@ function registerPalsuProvider(config) {
|
|
|
3603
3829
|
palsuToolCall,
|
|
3604
3830
|
prewarmAnthropicCache,
|
|
3605
3831
|
providerRegistry,
|
|
3832
|
+
redactText,
|
|
3833
|
+
redactValue,
|
|
3606
3834
|
registerPalsuProvider,
|
|
3607
3835
|
setProviderDiagnostic,
|
|
3608
3836
|
stream,
|