@prestyj/ai 5.27.0 → 5.28.1
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 +2 -2
- package/dist/index.cjs +66 -12
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +66 -12
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -40,10 +40,10 @@ Tool parameters are Zod schemas. Converted to JSON Schema at the provider bounda
|
|
|
40
40
|
|
|
41
41
|
| Provider | Models | Notes |
|
|
42
42
|
|---|---|---|
|
|
43
|
-
| `anthropic` | Claude Fable 5.1, Opus 5.5, Opus 5, Sonnet 5, Haiku 4.5 | Extended thinking, prompt caching, server-side compaction |
|
|
43
|
+
| `anthropic` | Claude Fable 5.1, Opus 5.5, Opus 5, Sonnet 5.5, 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.3 | Z.AI platform, OpenAI-compatible |
|
|
46
|
-
| `moonshot` | Kimi K3, Kimi K2.7 Code | Moonshot platform, OpenAI-compatible |
|
|
46
|
+
| `moonshot` | Kimi K3, Kimi K2.8 Preview, Kimi K2.7 Code | Moonshot platform, OpenAI-compatible |
|
|
47
47
|
|
|
48
48
|
---
|
|
49
49
|
|
package/dist/index.cjs
CHANGED
|
@@ -1100,7 +1100,7 @@ function isAdaptiveThinkingModel(model) {
|
|
|
1100
1100
|
function toAnthropicThinking(level, maxTokens, model) {
|
|
1101
1101
|
if (isAdaptiveThinkingModel(model)) {
|
|
1102
1102
|
let effort = level;
|
|
1103
|
-
if (effort === "xhigh" && !/opus-5|opus-4
|
|
1103
|
+
if (effort === "xhigh" && !/opus-5|opus-4[-.]8|opus-4[-.]7|sonnet-5[-.]5/.test(model)) {
|
|
1104
1104
|
effort = "high";
|
|
1105
1105
|
}
|
|
1106
1106
|
return {
|
|
@@ -2103,7 +2103,7 @@ async function* runStream2(options) {
|
|
|
2103
2103
|
const endpointKey = reasoningFieldKey(providerName, options.baseUrl, options.model);
|
|
2104
2104
|
const client = createClient2(options);
|
|
2105
2105
|
const isLocal = options.provider === "local";
|
|
2106
|
-
const isKimiK3 = options.provider === "moonshot" && options.model === "kimi-k3";
|
|
2106
|
+
const isKimiK3 = options.provider === "moonshot" && (options.model === "kimi-k3" || options.model === "kimi-for-coding");
|
|
2107
2107
|
const isManagedKimiK3 = isKimiK3 && options.baseUrl?.replace(/\/+$/, "").endsWith("/coding/v1") === true;
|
|
2108
2108
|
const k3Effort = options.thinking ? toKimiK3Effort(options.thinking) : void 0;
|
|
2109
2109
|
const isKimiK27 = options.provider === "moonshot" && options.model.startsWith("kimi-k2.7-code");
|
|
@@ -2577,7 +2577,7 @@ function extractRequestIdFromMessage(message) {
|
|
|
2577
2577
|
|
|
2578
2578
|
// src/providers/openai-codex.ts
|
|
2579
2579
|
var DEFAULT_BASE_URL = "https://chatgpt.com/backend-api";
|
|
2580
|
-
var CODEX_CLIENT_VERSION = "0.
|
|
2580
|
+
var CODEX_CLIENT_VERSION = "0.159.1";
|
|
2581
2581
|
var CODEX_REQUEST_COMPRESSION_MIN_BYTES = 16 * 1024;
|
|
2582
2582
|
var zstdInitPromise;
|
|
2583
2583
|
async function encodeCodexRequest(body) {
|
|
@@ -2623,7 +2623,7 @@ async function encodeCodexRequest(body) {
|
|
|
2623
2623
|
}
|
|
2624
2624
|
}
|
|
2625
2625
|
function usesResponsesLite(model) {
|
|
2626
|
-
return model.startsWith("gpt-5.6-") || model.startsWith("gpt-6-");
|
|
2626
|
+
return model.startsWith("gpt-5.6-") || model.startsWith("gpt-6-") || model.startsWith("gpt-6.");
|
|
2627
2627
|
}
|
|
2628
2628
|
function outputTextKey(itemId, contentIndex) {
|
|
2629
2629
|
return `${itemId ?? ""}:${contentIndex ?? 0}`;
|
|
@@ -2745,7 +2745,7 @@ async function* runStream3(options, retriedWithoutReasoning = false) {
|
|
|
2745
2745
|
if (response.status === 400 && message === `The '${options.model}' model is not supported when using Codex with a ChatGPT account.`) {
|
|
2746
2746
|
hint = "This model is not available through your ChatGPT account. Switch to a model listed for OpenAI via the model selector, or check your ChatGPT usage limits.";
|
|
2747
2747
|
} else if (response.status === 404 && text.includes("does not exist")) {
|
|
2748
|
-
hint = "This model is not in OpenAI's current catalog for your ChatGPT account. Switch to GPT-6 Astra, GPT-6 Sol, or GPT-6 Luna via the model selector.";
|
|
2748
|
+
hint = "This model is not in OpenAI's current catalog for your ChatGPT account. Switch to GPT-6 Astra, GPT-6.1 Sol, or GPT-6 Luna via the model selector.";
|
|
2749
2749
|
}
|
|
2750
2750
|
throw new ProviderError("openai", message, {
|
|
2751
2751
|
statusCode: response.status,
|
|
@@ -2759,6 +2759,8 @@ async function* runStream3(options, retriedWithoutReasoning = false) {
|
|
|
2759
2759
|
const contentParts = [];
|
|
2760
2760
|
let textAccum = "";
|
|
2761
2761
|
const toolCalls = /* @__PURE__ */ new Map();
|
|
2762
|
+
const finishedToolCalls = /* @__PURE__ */ new Set();
|
|
2763
|
+
let terminal;
|
|
2762
2764
|
const orderedItems = [];
|
|
2763
2765
|
const outputItemTypes = /* @__PURE__ */ new Map();
|
|
2764
2766
|
const outputTextByPart = /* @__PURE__ */ new Map();
|
|
@@ -2902,6 +2904,7 @@ async function* runStream3(options, retriedWithoutReasoning = false) {
|
|
|
2902
2904
|
for (const [key, tc] of toolCalls) {
|
|
2903
2905
|
if (key.endsWith(`|${itemId}`)) {
|
|
2904
2906
|
tc.argsJson = argsStr;
|
|
2907
|
+
finishedToolCalls.add(key);
|
|
2905
2908
|
break;
|
|
2906
2909
|
}
|
|
2907
2910
|
}
|
|
@@ -2927,6 +2930,7 @@ async function* runStream3(options, retriedWithoutReasoning = false) {
|
|
|
2927
2930
|
const id = `${callId}|${itemId}`;
|
|
2928
2931
|
const tc = toolCalls.get(id);
|
|
2929
2932
|
if (tc) {
|
|
2933
|
+
finishedToolCalls.add(id);
|
|
2930
2934
|
orderedItems.push({ kind: "tool", id });
|
|
2931
2935
|
const args = parseToolArguments(tc.argsJson);
|
|
2932
2936
|
yield {
|
|
@@ -2938,8 +2942,17 @@ async function* runStream3(options, retriedWithoutReasoning = false) {
|
|
|
2938
2942
|
}
|
|
2939
2943
|
}
|
|
2940
2944
|
}
|
|
2941
|
-
if (type === "response.completed" || type === "response.done") {
|
|
2945
|
+
if (type === "response.completed" || type === "response.done" || type === "response.incomplete") {
|
|
2942
2946
|
const resp = event.response;
|
|
2947
|
+
if (type === "response.incomplete" || resp?.status === "incomplete") {
|
|
2948
|
+
const details = resp?.incomplete_details;
|
|
2949
|
+
terminal = {
|
|
2950
|
+
status: "incomplete",
|
|
2951
|
+
reason: typeof details?.reason === "string" ? details.reason : void 0
|
|
2952
|
+
};
|
|
2953
|
+
} else {
|
|
2954
|
+
terminal = { status: "completed" };
|
|
2955
|
+
}
|
|
2943
2956
|
const usage = resp?.usage;
|
|
2944
2957
|
if (usage) {
|
|
2945
2958
|
cacheRead = usage.input_tokens_details?.cached_tokens ?? 0;
|
|
@@ -2949,6 +2962,25 @@ async function* runStream3(options, retriedWithoutReasoning = false) {
|
|
|
2949
2962
|
}
|
|
2950
2963
|
}
|
|
2951
2964
|
}
|
|
2965
|
+
if (!terminal) {
|
|
2966
|
+
throw new ProviderError("openai", "Stream ended before completion (no response.completed).", {
|
|
2967
|
+
statusCode: 504
|
|
2968
|
+
});
|
|
2969
|
+
}
|
|
2970
|
+
const droppedToolCalls = [...toolCalls.keys()].filter((id) => !finishedToolCalls.has(id)).length;
|
|
2971
|
+
if (terminal.status === "completed") {
|
|
2972
|
+
for (const [id, tc] of toolCalls) {
|
|
2973
|
+
if (!finishedToolCalls.has(id)) {
|
|
2974
|
+
throw new ProviderError(
|
|
2975
|
+
"openai",
|
|
2976
|
+
`Codex reply completed with an unfinished tool call: ${tc.name} (${id}).`,
|
|
2977
|
+
{ statusCode: 502 }
|
|
2978
|
+
);
|
|
2979
|
+
}
|
|
2980
|
+
}
|
|
2981
|
+
} else {
|
|
2982
|
+
providerDiag("codex_incomplete", { reason: terminal.reason ?? null, droppedToolCalls });
|
|
2983
|
+
}
|
|
2952
2984
|
const seenTool = /* @__PURE__ */ new Set();
|
|
2953
2985
|
let textInserted = false;
|
|
2954
2986
|
for (const entry of orderedItems) {
|
|
@@ -2975,7 +3007,7 @@ async function* runStream3(options, retriedWithoutReasoning = false) {
|
|
|
2975
3007
|
contentParts.push({ type: "text", text: textAccum });
|
|
2976
3008
|
}
|
|
2977
3009
|
for (const [id, tc] of toolCalls) {
|
|
2978
|
-
if (seenTool.has(id)) continue;
|
|
3010
|
+
if (seenTool.has(id) || !finishedToolCalls.has(id)) continue;
|
|
2979
3011
|
seenTool.add(id);
|
|
2980
3012
|
contentParts.push({
|
|
2981
3013
|
type: "tool_call",
|
|
@@ -2984,8 +3016,15 @@ async function* runStream3(options, retriedWithoutReasoning = false) {
|
|
|
2984
3016
|
args: parseToolArguments(tc.argsJson)
|
|
2985
3017
|
});
|
|
2986
3018
|
}
|
|
3019
|
+
if (droppedToolCalls > 0) {
|
|
3020
|
+
let last = contentParts.at(-1);
|
|
3021
|
+
while (last?.type === "raw" && isEncryptedReasoning(last.data)) {
|
|
3022
|
+
contentParts.pop();
|
|
3023
|
+
last = contentParts.at(-1);
|
|
3024
|
+
}
|
|
3025
|
+
}
|
|
2987
3026
|
const hasToolCalls = contentParts.some((p) => p.type === "tool_call");
|
|
2988
|
-
const stopReason = hasToolCalls ? "tool_use" : "end_turn";
|
|
3027
|
+
const stopReason = terminal.status === "incomplete" ? incompleteStopReason(terminal.reason) : hasToolCalls ? "tool_use" : "end_turn";
|
|
2989
3028
|
const streamResponse = {
|
|
2990
3029
|
message: {
|
|
2991
3030
|
role: "assistant",
|
|
@@ -3002,6 +3041,11 @@ async function* runStream3(options, retriedWithoutReasoning = false) {
|
|
|
3002
3041
|
yield { type: "done", stopReason };
|
|
3003
3042
|
return streamResponse;
|
|
3004
3043
|
}
|
|
3044
|
+
function incompleteStopReason(reason) {
|
|
3045
|
+
if (reason === "max_output_tokens") return "max_tokens";
|
|
3046
|
+
if (reason === "content_filter") return "refusal";
|
|
3047
|
+
return "error";
|
|
3048
|
+
}
|
|
3005
3049
|
async function* parseSSE(body) {
|
|
3006
3050
|
for await (const event of readSseStream(body)) {
|
|
3007
3051
|
const data = event.data.trim();
|
|
@@ -4137,6 +4181,8 @@ var CIRCULAR = "[CIRCULAR]";
|
|
|
4137
4181
|
var SENSITIVE_NAME = /(?:^|[_-])(?:api[_-]?key|access[_-]?token|refresh[_-]?token|token|key|auth(?:orization)?|bearer|cookie|credential|private[_-]?key|password|passwd|secret)(?:$|[_-])/i;
|
|
4138
4182
|
var ENV_SECRET_ASSIGNMENT = /\b((?:[A-Z0-9]+_)*(?:API_?KEY|ACCESS_TOKEN|REFRESH_TOKEN|TOKEN|KEY|AUTH|AUTHORIZATION|BEARER|CREDENTIALS?|PASSWORD|PASSWD|SECRET))\b(\s*[=:]\s*)(["']?)(?!\$|process\.env|os\.environ|import\.meta|env\.)(?=[^\s,"';}]*\d)([^\s,"';}=$][^\s,"';}]{7,})\3/g;
|
|
4139
4183
|
var COMPACT_SECRET_ASSIGNMENT = /\b((?:[a-z0-9]+[_-])*(?:api[_-]?key|access[_-]?token|refresh[_-]?token|token|auth|authorization|credentials?|password|passwd|secret)|(?:[a-z0-9]+[_-])+key)=(["']?)(?!\$)([^\s,"'&;}=][^\s,"'&;}]{7,})\2/gi;
|
|
4184
|
+
var URL_USERINFO = /\b([a-z][a-z0-9+.-]*:\/\/)[^\s/?#@:"'`<>]*:[^\s/?#"'`<>]+@/gi;
|
|
4185
|
+
var URL_USERINFO_TO_FIRST_AT = /\b([a-z][a-z0-9+.-]*:\/\/)[^\s/@:]*:[^\s/@]+@/gi;
|
|
4140
4186
|
function escaped(value) {
|
|
4141
4187
|
return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
4142
4188
|
}
|
|
@@ -4160,7 +4206,8 @@ function redactText(text, options = {}) {
|
|
|
4160
4206
|
/-----BEGIN (?:[A-Z0-9 ]+ )?PRIVATE KEY-----[\s\S]*?-----END (?:[A-Z0-9 ]+ )?PRIVATE KEY-----/g,
|
|
4161
4207
|
REDACTED
|
|
4162
4208
|
);
|
|
4163
|
-
result = result.replace(
|
|
4209
|
+
result = result.replace(URL_USERINFO, `$1${REDACTED}@`);
|
|
4210
|
+
result = result.replace(URL_USERINFO_TO_FIRST_AT, `$1${REDACTED}@`);
|
|
4164
4211
|
result = result.replace(
|
|
4165
4212
|
/\b(authorization\s*[:=]\s*)(?:bearer|basic)\s+[^\s,;]+/gi,
|
|
4166
4213
|
`$1${REDACTED}`
|
|
@@ -4204,7 +4251,7 @@ function isMediaObject(value) {
|
|
|
4204
4251
|
function redactValue(value, options = {}) {
|
|
4205
4252
|
const maxDepth = options.maxDepth ?? 20;
|
|
4206
4253
|
const maxEntries = options.maxEntries ?? 1e4;
|
|
4207
|
-
const
|
|
4254
|
+
const ancestors = /* @__PURE__ */ new WeakSet();
|
|
4208
4255
|
let entries = 0;
|
|
4209
4256
|
const visit = (current, depth, sensitive = false) => {
|
|
4210
4257
|
if (typeof current === "string") {
|
|
@@ -4218,8 +4265,15 @@ function redactValue(value, options = {}) {
|
|
|
4218
4265
|
if (isBinary(current)) return current;
|
|
4219
4266
|
if (current instanceof Date) return new Date(current.getTime());
|
|
4220
4267
|
if (depth >= maxDepth) return TRUNCATED;
|
|
4221
|
-
if (
|
|
4222
|
-
|
|
4268
|
+
if (ancestors.has(current)) return CIRCULAR;
|
|
4269
|
+
ancestors.add(current);
|
|
4270
|
+
try {
|
|
4271
|
+
return cloneObject(current, depth);
|
|
4272
|
+
} finally {
|
|
4273
|
+
ancestors.delete(current);
|
|
4274
|
+
}
|
|
4275
|
+
};
|
|
4276
|
+
const cloneObject = (current, depth) => {
|
|
4223
4277
|
if (current instanceof Error) {
|
|
4224
4278
|
const error = {
|
|
4225
4279
|
name: current.name,
|