@kenkaiiii/gg-ai 5.16.0 → 5.18.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 +259 -20
- 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 +254 -20
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -43,7 +43,7 @@ Tool parameters are Zod schemas. Converted to JSON Schema at the provider bounda
|
|
|
43
43
|
| `anthropic` | Claude Opus 4.8, Sonnet 5, Haiku 4.5 | Extended thinking, prompt caching, server-side compaction |
|
|
44
44
|
| `openai` | GPT-4.1, o3, o4-mini | Supports OAuth (codex endpoint) and API keys |
|
|
45
45
|
| `glm` | GLM-5.1, GLM-4.7 | Z.AI platform, OpenAI-compatible |
|
|
46
|
-
| `moonshot` | Kimi K2.7 | Moonshot platform, OpenAI-compatible |
|
|
46
|
+
| `moonshot` | Kimi K3, Kimi K2.7 Code | Moonshot platform, OpenAI-compatible |
|
|
47
47
|
|
|
48
48
|
---
|
|
49
49
|
|
package/dist/index.cjs
CHANGED
|
@@ -33,8 +33,11 @@ __export(index_exports, {
|
|
|
33
33
|
EventStream: () => EventStream,
|
|
34
34
|
GGAIError: () => GGAIError,
|
|
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)";
|
|
@@ -1636,7 +1709,8 @@ function toError(err) {
|
|
|
1636
1709
|
const bodyMessage = typeof nestedError?.message === "string" && nestedError.message.trim() ? nestedError.message.trim() : typeof errorBody?.message === "string" && errorBody.message.trim() ? errorBody.message.trim() : void 0;
|
|
1637
1710
|
const bodyType = typeof nestedError?.type === "string" ? nestedError.type : typeof errorBody?.type === "string" ? errorBody.type : typeof err.type === "string" ? err.type : void 0;
|
|
1638
1711
|
const fallbackMessage = isRawJsonErrorEcho(err.message) ? emptyProviderErrorMessage(err.status) : err.message;
|
|
1639
|
-
const
|
|
1712
|
+
const messageCandidate = bodyMessage ?? err.message;
|
|
1713
|
+
const message = isRawHtmlErrorEcho(messageCandidate) ? providerHtmlErrorMessage(err.status) : bodyType && bodyMessage ? `${bodyType}: ${bodyMessage}` : bodyMessage ?? fallbackMessage;
|
|
1640
1714
|
if (err.status === 429) {
|
|
1641
1715
|
const limit = readUnifiedRateLimit(err.headers);
|
|
1642
1716
|
const farOff = limit.resetsAt != null && limit.resetsAt * 1e3 - Date.now() > 6e4;
|
|
@@ -1818,7 +1892,11 @@ async function* runStream2(options) {
|
|
|
1818
1892
|
const providerName = options.provider ?? "openai";
|
|
1819
1893
|
const useStreaming = options.streaming !== false;
|
|
1820
1894
|
const client = createClient2(options);
|
|
1821
|
-
const
|
|
1895
|
+
const isKimiK3 = options.provider === "moonshot" && options.model === "kimi-k3";
|
|
1896
|
+
const isManagedKimiK3 = isKimiK3 && options.baseUrl?.replace(/\/+$/, "").endsWith("/coding/v1") === true;
|
|
1897
|
+
const isKimiK27 = options.provider === "moonshot" && options.model.startsWith("kimi-k2.7-code");
|
|
1898
|
+
const hasFixedKimiSampling = isKimiK3 || isKimiK27;
|
|
1899
|
+
const usesThinkingParam = options.provider === "glm" || options.provider === "moonshot" && !isKimiK3 && !isKimiK27 || options.provider === "xiaomi";
|
|
1822
1900
|
const downgradedImages = downgradeUnsupportedImages(options.messages, options.supportsImages);
|
|
1823
1901
|
const downgradedMessages = downgradeUnsupportedVideos(downgradedImages, options.supportsVideo);
|
|
1824
1902
|
if (options.provider === "moonshot") {
|
|
@@ -1830,7 +1908,9 @@ async function* runStream2(options) {
|
|
|
1830
1908
|
}
|
|
1831
1909
|
const messages = toOpenAIMessages(downgradedMessages, {
|
|
1832
1910
|
provider: options.provider,
|
|
1833
|
-
|
|
1911
|
+
// K3 and K2.7 preserve reasoning even when the user hides thinking in the
|
|
1912
|
+
// UI; keep assistant tool-call history wire-valid in that display mode.
|
|
1913
|
+
thinking: isKimiK3 || isKimiK27 || !!options.thinking,
|
|
1834
1914
|
supportsImages: options.supportsImages
|
|
1835
1915
|
});
|
|
1836
1916
|
const defaultTemp = options.provider === "glm" ? 0.6 : void 0;
|
|
@@ -1840,10 +1920,10 @@ async function* runStream2(options) {
|
|
|
1840
1920
|
messages,
|
|
1841
1921
|
stream: useStreaming,
|
|
1842
1922
|
...options.maxTokens ? { max_completion_tokens: options.maxTokens } : {},
|
|
1843
|
-
...effectiveTemp != null && !options.thinking ? { temperature: effectiveTemp } : {},
|
|
1844
|
-
...options.topP != null ? { top_p: options.topP } : {},
|
|
1923
|
+
...effectiveTemp != null && !options.thinking && !hasFixedKimiSampling ? { temperature: effectiveTemp } : {},
|
|
1924
|
+
...options.topP != null && !hasFixedKimiSampling ? { top_p: options.topP } : {},
|
|
1845
1925
|
...options.stop ? { stop: options.stop } : {},
|
|
1846
|
-
...options.thinking && !usesThinkingParam ? { reasoning_effort: toOpenAIReasoningEffort(options.thinking, options.model) } : {},
|
|
1926
|
+
...options.thinking && !usesThinkingParam && !isKimiK3 && !isKimiK27 ? { reasoning_effort: toOpenAIReasoningEffort(options.thinking, options.model) } : {},
|
|
1847
1927
|
...options.tools?.length ? { tools: toOpenAITools(options.tools) } : {},
|
|
1848
1928
|
...options.toolChoice && options.tools?.length ? { tool_choice: toOpenAIToolChoice(options.toolChoice) } : {},
|
|
1849
1929
|
...useStreaming ? { stream_options: { include_usage: true } } : {}
|
|
@@ -1853,13 +1933,21 @@ async function* runStream2(options) {
|
|
|
1853
1933
|
paramsAny.prompt_cache_key = normalizePromptCacheKey(options.promptCacheKey ?? "ggcoder");
|
|
1854
1934
|
if (options.provider === "openai" && options.model.startsWith("gpt-5.6")) {
|
|
1855
1935
|
paramsAny.prompt_cache_options = { mode: "implicit", ttl: "30m" };
|
|
1856
|
-
} else if ((options.cacheRetention ?? "short") === "long") {
|
|
1936
|
+
} else if (!isKimiK3 && (options.cacheRetention ?? "short") === "long") {
|
|
1857
1937
|
paramsAny.prompt_cache_retention = "24h";
|
|
1858
1938
|
}
|
|
1859
1939
|
}
|
|
1860
1940
|
if (options.provider === "openai" && options.serviceTier) {
|
|
1861
1941
|
params.service_tier = options.serviceTier;
|
|
1862
1942
|
}
|
|
1943
|
+
if (isKimiK3) {
|
|
1944
|
+
const paramsAny = params;
|
|
1945
|
+
if (isManagedKimiK3) {
|
|
1946
|
+
paramsAny.thinking = { type: "enabled", effort: "max", keep: "all" };
|
|
1947
|
+
} else {
|
|
1948
|
+
paramsAny.reasoning_effort = "max";
|
|
1949
|
+
}
|
|
1950
|
+
}
|
|
1863
1951
|
if (usesThinkingParam) {
|
|
1864
1952
|
if (options.thinking) {
|
|
1865
1953
|
params.thinking = { type: "enabled" };
|
|
@@ -2104,7 +2192,8 @@ function toError2(err, provider = "openai") {
|
|
|
2104
2192
|
const body = err.error;
|
|
2105
2193
|
const bodyMessage = typeof body?.message === "string" && body.message.trim() ? body.message.trim() : void 0;
|
|
2106
2194
|
const modelName = typeof body?.model === "string" ? body.model : "";
|
|
2107
|
-
const
|
|
2195
|
+
const messageCandidate = bodyMessage ?? err.message;
|
|
2196
|
+
const cleanMessage = isRawHtmlErrorEcho(messageCandidate) ? providerHtmlErrorMessage(err.status) : bodyMessage ? bodyMessage : isRawJsonErrorEcho(err.message) ? emptyProviderErrorMessage(err.status) : err.message;
|
|
2108
2197
|
let hint;
|
|
2109
2198
|
if (modelName === "codex-mini-latest" || cleanMessage.includes("codex-mini-latest")) {
|
|
2110
2199
|
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.";
|
|
@@ -2218,6 +2307,21 @@ function outputTextKey(itemId, contentIndex) {
|
|
|
2218
2307
|
function isVisibleOutputItem(itemType) {
|
|
2219
2308
|
return itemType === "message";
|
|
2220
2309
|
}
|
|
2310
|
+
function toCodexToolChoice(choice, tools) {
|
|
2311
|
+
const resolved = choice ?? "auto";
|
|
2312
|
+
if (typeof resolved === "object") {
|
|
2313
|
+
throw new GGAIError(
|
|
2314
|
+
`OpenAI Codex does not support selecting the named tool \`${resolved.name}\`; use auto, none, or required.`,
|
|
2315
|
+
{ source: "capability" }
|
|
2316
|
+
);
|
|
2317
|
+
}
|
|
2318
|
+
if (resolved === "required" && !tools?.length) {
|
|
2319
|
+
throw new GGAIError("OpenAI Codex cannot require a tool call when no tools are configured.", {
|
|
2320
|
+
source: "capability"
|
|
2321
|
+
});
|
|
2322
|
+
}
|
|
2323
|
+
return resolved;
|
|
2324
|
+
}
|
|
2221
2325
|
function streamOpenAICodex(options) {
|
|
2222
2326
|
return new StreamResult(runStream3(options), options.signal);
|
|
2223
2327
|
}
|
|
@@ -2234,7 +2338,7 @@ async function* runStream3(options) {
|
|
|
2234
2338
|
stream: true,
|
|
2235
2339
|
instructions: system,
|
|
2236
2340
|
input,
|
|
2237
|
-
tool_choice:
|
|
2341
|
+
tool_choice: toCodexToolChoice(options.toolChoice, options.tools),
|
|
2238
2342
|
parallel_tool_calls: !responsesLite,
|
|
2239
2343
|
include: ["reasoning.encrypted_content"]
|
|
2240
2344
|
};
|
|
@@ -2267,8 +2371,9 @@ async function* runStream3(options) {
|
|
|
2267
2371
|
headers["chatgpt-account-id"] = options.accountId;
|
|
2268
2372
|
}
|
|
2269
2373
|
if (options.transportSessionId) {
|
|
2270
|
-
|
|
2271
|
-
headers["
|
|
2374
|
+
const transportSessionId = normalizePromptCacheKey(options.transportSessionId);
|
|
2375
|
+
headers["session_id"] = transportSessionId;
|
|
2376
|
+
headers["x-client-request-id"] = transportSessionId;
|
|
2272
2377
|
}
|
|
2273
2378
|
const response = await fetch(url, {
|
|
2274
2379
|
method: "POST",
|
|
@@ -2278,7 +2383,7 @@ async function* runStream3(options) {
|
|
|
2278
2383
|
});
|
|
2279
2384
|
if (!response.ok) {
|
|
2280
2385
|
const text = await response.text().catch(() => "");
|
|
2281
|
-
const parsed = parseCodexErrorBody(text);
|
|
2386
|
+
const parsed = parseCodexErrorBody(text, response.status);
|
|
2282
2387
|
const message = parsed.message ?? `Codex API returned HTTP ${response.status}.`;
|
|
2283
2388
|
const requestId = parsed.requestId ?? readHeader(response.headers, "x-request-id", "openai-request-id", "x-oai-request-id");
|
|
2284
2389
|
const usageLimit = codexUsageLimitError(parsed.errorObj, response.status, requestId);
|
|
@@ -2672,13 +2777,14 @@ function toCodexTools(tools) {
|
|
|
2672
2777
|
strict: null
|
|
2673
2778
|
}));
|
|
2674
2779
|
}
|
|
2675
|
-
function parseCodexErrorBody(text) {
|
|
2780
|
+
function parseCodexErrorBody(text, statusCode) {
|
|
2676
2781
|
if (!text) return {};
|
|
2677
2782
|
try {
|
|
2678
2783
|
const parsed = JSON.parse(text);
|
|
2679
2784
|
const error = parsed.error;
|
|
2680
2785
|
const detail = parsed.detail;
|
|
2681
|
-
const
|
|
2786
|
+
const rawMessage = error?.message ?? parsed.message ?? (typeof detail === "string" ? detail : void 0);
|
|
2787
|
+
const message = rawMessage && isRawHtmlErrorEcho(rawMessage) ? providerHtmlErrorMessage(statusCode) : rawMessage;
|
|
2682
2788
|
const requestId = parsed.request_id ?? error?.request_id ?? (message ? extractRequestIdFromMessage(message) : void 0);
|
|
2683
2789
|
const errorObj = error ?? parsed;
|
|
2684
2790
|
return {
|
|
@@ -2687,8 +2793,12 @@ function parseCodexErrorBody(text) {
|
|
|
2687
2793
|
...errorObj ? { errorObj } : {}
|
|
2688
2794
|
};
|
|
2689
2795
|
} catch {
|
|
2690
|
-
const trimmed = text.trim()
|
|
2691
|
-
|
|
2796
|
+
const trimmed = text.trim();
|
|
2797
|
+
if (isRawHtmlErrorEcho(trimmed)) {
|
|
2798
|
+
return { message: providerHtmlErrorMessage(statusCode) };
|
|
2799
|
+
}
|
|
2800
|
+
const bounded = trimmed.slice(0, 240);
|
|
2801
|
+
return bounded ? { message: bounded } : {};
|
|
2692
2802
|
}
|
|
2693
2803
|
}
|
|
2694
2804
|
var CODEX_USAGE_LIMIT_CODE = /usage_limit_reached|usage_not_included/i;
|
|
@@ -3323,7 +3433,12 @@ function stream(options) {
|
|
|
3323
3433
|
if (options.supportsVideo !== true && messagesContainVideo(options.messages)) {
|
|
3324
3434
|
throw new VideoUnsupportedError();
|
|
3325
3435
|
}
|
|
3326
|
-
|
|
3436
|
+
const messages = clampProviderContextImages(
|
|
3437
|
+
options.messages,
|
|
3438
|
+
options.provider,
|
|
3439
|
+
options.supportsImages
|
|
3440
|
+
);
|
|
3441
|
+
return entry.stream(messages === options.messages ? options : { ...options, messages });
|
|
3327
3442
|
}
|
|
3328
3443
|
function messagesContainVideo(messages) {
|
|
3329
3444
|
for (const msg of messages) {
|
|
@@ -3428,6 +3543,125 @@ Original: ${message}`;
|
|
|
3428
3543
|
return message;
|
|
3429
3544
|
}
|
|
3430
3545
|
|
|
3546
|
+
// src/redaction.ts
|
|
3547
|
+
var REDACTED = "[REDACTED]";
|
|
3548
|
+
var TRUNCATED = "[TRUNCATED]";
|
|
3549
|
+
var CIRCULAR = "[CIRCULAR]";
|
|
3550
|
+
var SENSITIVE_NAME = /(?:^|[_-])(?:api[_-]?key|access[_-]?token|refresh[_-]?token|token|key|auth(?:orization)?|bearer|cookie|credential|private[_-]?key|password|passwd|secret)(?:$|[_-])/i;
|
|
3551
|
+
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;
|
|
3552
|
+
function escaped(value) {
|
|
3553
|
+
return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
3554
|
+
}
|
|
3555
|
+
function normalizedSecrets(secrets) {
|
|
3556
|
+
if (!secrets) return [];
|
|
3557
|
+
return [...new Set([...secrets].filter((value) => value.length >= 8 && value !== REDACTED))].sort(
|
|
3558
|
+
(a, b) => b.length - a.length
|
|
3559
|
+
);
|
|
3560
|
+
}
|
|
3561
|
+
function environmentSecrets(env) {
|
|
3562
|
+
const values = /* @__PURE__ */ new Set();
|
|
3563
|
+
for (const [name, value] of Object.entries(env)) {
|
|
3564
|
+
if (!value || value.length < 8 || value === REDACTED || !SENSITIVE_NAME.test(name)) continue;
|
|
3565
|
+
values.add(value);
|
|
3566
|
+
}
|
|
3567
|
+
return [...values].sort((a, b) => b.length - a.length);
|
|
3568
|
+
}
|
|
3569
|
+
function redactText(text, options = {}) {
|
|
3570
|
+
let result = text;
|
|
3571
|
+
result = result.replace(
|
|
3572
|
+
/-----BEGIN (?:[A-Z0-9 ]+ )?PRIVATE KEY-----[\s\S]*?-----END (?:[A-Z0-9 ]+ )?PRIVATE KEY-----/g,
|
|
3573
|
+
REDACTED
|
|
3574
|
+
);
|
|
3575
|
+
result = result.replace(/\b([a-z][a-z0-9+.-]*:\/\/)[^\s/@:]+:[^\s/@]+@/gi, `$1${REDACTED}@`);
|
|
3576
|
+
result = result.replace(
|
|
3577
|
+
/\b(authorization\s*[:=]\s*)(?:bearer|basic)\s+[^\s,;]+/gi,
|
|
3578
|
+
`$1${REDACTED}`
|
|
3579
|
+
);
|
|
3580
|
+
result = result.replace(/\b(bearer|basic)\s+[A-Za-z0-9+/_.=-]{8,}/gi, `$1 ${REDACTED}`);
|
|
3581
|
+
result = result.replace(/\b(cookie|set-cookie)(\s*[:=]\s*)[^\r\n]+/gi, `$1$2${REDACTED}`);
|
|
3582
|
+
result = result.replace(
|
|
3583
|
+
/\beyJ[A-Za-z0-9_-]{6,}\.[A-Za-z0-9_-]{6,}\.[A-Za-z0-9_-]{6,}\b/g,
|
|
3584
|
+
REDACTED
|
|
3585
|
+
);
|
|
3586
|
+
result = result.replace(
|
|
3587
|
+
/\b(?:sk-(?:ant-|proj-)?|xox[baprs]-|gh[pousr]_|github_pat_|AIza)[A-Za-z0-9_-]{12,}\b/g,
|
|
3588
|
+
REDACTED
|
|
3589
|
+
);
|
|
3590
|
+
result = result.replace(
|
|
3591
|
+
SENSITIVE_ASSIGNMENT,
|
|
3592
|
+
(_match, name, separator) => `${name}${separator}${REDACTED}`
|
|
3593
|
+
);
|
|
3594
|
+
for (const secret of normalizedSecrets(options.secrets)) {
|
|
3595
|
+
result = result.replace(new RegExp(escaped(secret), "g"), REDACTED);
|
|
3596
|
+
}
|
|
3597
|
+
const maxStringLength = options.maxStringLength ?? 1e6;
|
|
3598
|
+
if (result.length > maxStringLength) {
|
|
3599
|
+
result = `${result.slice(0, maxStringLength)}${TRUNCATED}`;
|
|
3600
|
+
}
|
|
3601
|
+
return result;
|
|
3602
|
+
}
|
|
3603
|
+
function isBinary(value) {
|
|
3604
|
+
return value instanceof ArrayBuffer || ArrayBuffer.isView(value) || typeof Blob !== "undefined" && value instanceof Blob;
|
|
3605
|
+
}
|
|
3606
|
+
function isMediaObject(value) {
|
|
3607
|
+
return (value.type === "image" || value.type === "video") && (typeof value.data === "string" || typeof value.url === "string");
|
|
3608
|
+
}
|
|
3609
|
+
function redactValue(value, options = {}) {
|
|
3610
|
+
const maxDepth = options.maxDepth ?? 20;
|
|
3611
|
+
const maxEntries = options.maxEntries ?? 1e4;
|
|
3612
|
+
const seen = /* @__PURE__ */ new WeakSet();
|
|
3613
|
+
let entries = 0;
|
|
3614
|
+
const visit = (current, depth, sensitive = false) => {
|
|
3615
|
+
if (typeof current === "string") {
|
|
3616
|
+
if (sensitive && current.length > 0 && current !== REDACTED) return REDACTED;
|
|
3617
|
+
return redactText(current, options);
|
|
3618
|
+
}
|
|
3619
|
+
if (current === null || current === void 0 || typeof current === "number" || typeof current === "boolean" || typeof current === "bigint") {
|
|
3620
|
+
return current;
|
|
3621
|
+
}
|
|
3622
|
+
if (typeof current !== "object") return current;
|
|
3623
|
+
if (isBinary(current)) return current;
|
|
3624
|
+
if (current instanceof Date) return new Date(current.getTime());
|
|
3625
|
+
if (depth >= maxDepth) return TRUNCATED;
|
|
3626
|
+
if (seen.has(current)) return CIRCULAR;
|
|
3627
|
+
seen.add(current);
|
|
3628
|
+
if (current instanceof Error) {
|
|
3629
|
+
const error = {
|
|
3630
|
+
name: current.name,
|
|
3631
|
+
message: visit(current.message, depth + 1),
|
|
3632
|
+
stack: visit(current.stack, depth + 1)
|
|
3633
|
+
};
|
|
3634
|
+
for (const [key, child] of Object.entries(current)) {
|
|
3635
|
+
error[key] = visit(child, depth + 1, SENSITIVE_NAME.test(key));
|
|
3636
|
+
}
|
|
3637
|
+
return error;
|
|
3638
|
+
}
|
|
3639
|
+
if (Array.isArray(current)) {
|
|
3640
|
+
const clone2 = [];
|
|
3641
|
+
for (const child of current) {
|
|
3642
|
+
if (++entries > maxEntries) {
|
|
3643
|
+
clone2.push(TRUNCATED);
|
|
3644
|
+
break;
|
|
3645
|
+
}
|
|
3646
|
+
clone2.push(visit(child, depth + 1));
|
|
3647
|
+
}
|
|
3648
|
+
return clone2;
|
|
3649
|
+
}
|
|
3650
|
+
const record = current;
|
|
3651
|
+
if (isMediaObject(record)) return { ...record };
|
|
3652
|
+
const clone = {};
|
|
3653
|
+
for (const [key, child] of Object.entries(record)) {
|
|
3654
|
+
if (++entries > maxEntries) {
|
|
3655
|
+
clone[TRUNCATED] = true;
|
|
3656
|
+
break;
|
|
3657
|
+
}
|
|
3658
|
+
clone[key] = visit(child, depth + 1, SENSITIVE_NAME.test(key));
|
|
3659
|
+
}
|
|
3660
|
+
return clone;
|
|
3661
|
+
};
|
|
3662
|
+
return visit(value, 0);
|
|
3663
|
+
}
|
|
3664
|
+
|
|
3431
3665
|
// src/providers/palsu.ts
|
|
3432
3666
|
function palsuText(text) {
|
|
3433
3667
|
return { role: "assistant", content: text ? [{ type: "text", text }] : [] };
|
|
@@ -3584,8 +3818,11 @@ function registerPalsuProvider(config) {
|
|
|
3584
3818
|
EventStream,
|
|
3585
3819
|
GGAIError,
|
|
3586
3820
|
ProviderError,
|
|
3821
|
+
REDACTION_MARKER,
|
|
3587
3822
|
StreamResult,
|
|
3823
|
+
clampProviderContextImages,
|
|
3588
3824
|
classifyProviderError,
|
|
3825
|
+
environmentSecrets,
|
|
3589
3826
|
formatError,
|
|
3590
3827
|
formatErrorForDisplay,
|
|
3591
3828
|
isHardBillingMessage,
|
|
@@ -3596,6 +3833,8 @@ function registerPalsuProvider(config) {
|
|
|
3596
3833
|
palsuToolCall,
|
|
3597
3834
|
prewarmAnthropicCache,
|
|
3598
3835
|
providerRegistry,
|
|
3836
|
+
redactText,
|
|
3837
|
+
redactValue,
|
|
3599
3838
|
registerPalsuProvider,
|
|
3600
3839
|
setProviderDiagnostic,
|
|
3601
3840
|
stream,
|