@oh-my-pi/pi-ai 14.6.2 → 14.6.4
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/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,12 @@
|
|
|
2
2
|
|
|
3
3
|
## [Unreleased]
|
|
4
4
|
|
|
5
|
+
## [14.6.4] - 2026-05-03
|
|
6
|
+
|
|
7
|
+
### Fixed
|
|
8
|
+
|
|
9
|
+
- Fixed OpenAI Codex websocket continuations to retry with full context when `previous_response_id` expires server-side instead of surfacing `previous_response_not_found`.
|
|
10
|
+
|
|
5
11
|
## [14.6.2] - 2026-05-03
|
|
6
12
|
### Added
|
|
7
13
|
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"type": "module",
|
|
3
3
|
"name": "@oh-my-pi/pi-ai",
|
|
4
|
-
"version": "14.6.
|
|
4
|
+
"version": "14.6.4",
|
|
5
5
|
"description": "Unified LLM API with automatic model discovery and provider configuration",
|
|
6
6
|
"homepage": "https://github.com/can1357/oh-my-pi",
|
|
7
7
|
"author": "Can Boluk",
|
|
@@ -46,8 +46,8 @@
|
|
|
46
46
|
"@aws-sdk/credential-provider-node": "^3.972.36",
|
|
47
47
|
"@bufbuild/protobuf": "^2.12.0",
|
|
48
48
|
"@google/genai": "^1.50.1",
|
|
49
|
-
"@oh-my-pi/pi-natives": "14.6.
|
|
50
|
-
"@oh-my-pi/pi-utils": "14.6.
|
|
49
|
+
"@oh-my-pi/pi-natives": "14.6.4",
|
|
50
|
+
"@oh-my-pi/pi-utils": "14.6.4",
|
|
51
51
|
"@sinclair/typebox": "^0.34.49",
|
|
52
52
|
"@smithy/node-http-handler": "^4.6.1",
|
|
53
53
|
"ajv": "^8.20.0",
|
|
@@ -1962,6 +1962,25 @@ function isZaiAnthropicEndpoint(model: Model<"anthropic-messages">): boolean {
|
|
|
1962
1962
|
}
|
|
1963
1963
|
}
|
|
1964
1964
|
|
|
1965
|
+
/**
|
|
1966
|
+
* Returns true for providers whose Anthropic-compatible endpoints do NOT
|
|
1967
|
+
* implement signature-based thinking-chain integrity (DeepSeek, Z.AI, etc.).
|
|
1968
|
+
* For these providers, unsigned thinking blocks must be preserved as
|
|
1969
|
+
* `type: "thinking"` instead of being degraded to text.
|
|
1970
|
+
*/
|
|
1971
|
+
function isNonSigningAnthropicEndpoint(model: Model<"anthropic-messages">): boolean {
|
|
1972
|
+
// Known non-signing providers
|
|
1973
|
+
if (model.provider === "zai" || model.provider === "deepseek") return true;
|
|
1974
|
+
const baseUrl = model.baseUrl;
|
|
1975
|
+
if (!baseUrl) return false;
|
|
1976
|
+
try {
|
|
1977
|
+
const hostname = new URL(baseUrl).hostname.toLowerCase();
|
|
1978
|
+
return hostname === "api.deepseek.com" || hostname.endsWith(".deepseek.com");
|
|
1979
|
+
} catch {
|
|
1980
|
+
return false;
|
|
1981
|
+
}
|
|
1982
|
+
}
|
|
1983
|
+
|
|
1965
1984
|
function buildToolResultBlock(model: Model<"anthropic-messages">, msg: ToolResultMessage): ContentBlockParam {
|
|
1966
1985
|
const block: ContentBlockParam = {
|
|
1967
1986
|
type: "tool_result",
|
|
@@ -2061,10 +2080,18 @@ export function convertAnthropicMessages(
|
|
|
2061
2080
|
}
|
|
2062
2081
|
if (block.thinking.trim().length === 0) continue;
|
|
2063
2082
|
if (!block.thinkingSignature || block.thinkingSignature.trim().length === 0) {
|
|
2064
|
-
|
|
2065
|
-
|
|
2066
|
-
|
|
2067
|
-
|
|
2083
|
+
if (isNonSigningAnthropicEndpoint(model)) {
|
|
2084
|
+
blocks.push({
|
|
2085
|
+
type: "thinking",
|
|
2086
|
+
thinking: block.thinking.toWellFormed(),
|
|
2087
|
+
signature: "",
|
|
2088
|
+
});
|
|
2089
|
+
} else {
|
|
2090
|
+
blocks.push({
|
|
2091
|
+
type: "text",
|
|
2092
|
+
text: block.thinking.toWellFormed(),
|
|
2093
|
+
});
|
|
2094
|
+
}
|
|
2068
2095
|
} else {
|
|
2069
2096
|
blocks.push({
|
|
2070
2097
|
type: "thinking",
|
|
@@ -1221,6 +1221,9 @@ async function recoverCodexStreamError(
|
|
|
1221
1221
|
if (await tryReconnectCodexWebSocketOnConnectionLimit(context, runtime, error)) {
|
|
1222
1222
|
return true;
|
|
1223
1223
|
}
|
|
1224
|
+
if (await tryRecoverCodexPreviousResponseNotFound(context, runtime, error)) {
|
|
1225
|
+
return true;
|
|
1226
|
+
}
|
|
1224
1227
|
if (await tryReplayWebsocketFailureOverSse(context, runtime, error)) {
|
|
1225
1228
|
return true;
|
|
1226
1229
|
}
|
|
@@ -1279,6 +1282,44 @@ async function tryReconnectCodexWebSocketOnConnectionLimit(
|
|
|
1279
1282
|
return true;
|
|
1280
1283
|
}
|
|
1281
1284
|
|
|
1285
|
+
function isCodexPreviousResponseNotFound(error: unknown): boolean {
|
|
1286
|
+
return error instanceof CodexProviderStreamError && error.code === "previous_response_not_found";
|
|
1287
|
+
}
|
|
1288
|
+
|
|
1289
|
+
async function tryRecoverCodexPreviousResponseNotFound(
|
|
1290
|
+
context: CodexStreamProcessingContext,
|
|
1291
|
+
runtime: CodexStreamRuntime,
|
|
1292
|
+
error: unknown,
|
|
1293
|
+
): Promise<boolean> {
|
|
1294
|
+
const websocketState = context.requestContext.websocketState;
|
|
1295
|
+
if (
|
|
1296
|
+
!isCodexPreviousResponseNotFound(error) ||
|
|
1297
|
+
!websocketState ||
|
|
1298
|
+
runtime.transport !== "websocket" ||
|
|
1299
|
+
context.output.content.length > 0 ||
|
|
1300
|
+
context.options?.signal?.aborted ||
|
|
1301
|
+
runtime.providerRetryAttempt >= CODEX_MAX_RETRIES
|
|
1302
|
+
) {
|
|
1303
|
+
return false;
|
|
1304
|
+
}
|
|
1305
|
+
|
|
1306
|
+
runtime.providerRetryAttempt += 1;
|
|
1307
|
+
resetCodexWebSocketAppendState(websocketState);
|
|
1308
|
+
resetCodexSessionMetadata(websocketState);
|
|
1309
|
+
runtime.currentItem = null;
|
|
1310
|
+
runtime.currentBlock = null;
|
|
1311
|
+
runtime.sawTerminalEvent = false;
|
|
1312
|
+
runtime.nativeOutputItems.length = 0;
|
|
1313
|
+
resetOutputState(context.output);
|
|
1314
|
+
context.firstTokenTime = undefined;
|
|
1315
|
+
|
|
1316
|
+
logCodexDebug("codex previous_response_id expired; retrying with full context", {
|
|
1317
|
+
retry: runtime.providerRetryAttempt,
|
|
1318
|
+
});
|
|
1319
|
+
await reopenCodexWebSocketRuntimeStream(context, runtime, websocketState);
|
|
1320
|
+
return true;
|
|
1321
|
+
}
|
|
1322
|
+
|
|
1282
1323
|
async function tryReplayWebsocketFailureOverSse(
|
|
1283
1324
|
context: CodexStreamProcessingContext,
|
|
1284
1325
|
runtime: CodexStreamRuntime,
|