@howaboua/pi-codex-conversion 1.0.29 → 1.0.30
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/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@howaboua/pi-codex-conversion",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.30",
|
|
4
4
|
"description": "Codex-oriented tool and prompt adapter for pi coding agent",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"repository": {
|
|
@@ -51,15 +51,15 @@
|
|
|
51
51
|
"access": "public"
|
|
52
52
|
},
|
|
53
53
|
"peerDependencies": {
|
|
54
|
-
"@mariozechner/pi-ai": "^0.
|
|
55
|
-
"@mariozechner/pi-coding-agent": "^0.
|
|
56
|
-
"@mariozechner/pi-tui": "^0.
|
|
54
|
+
"@mariozechner/pi-ai": "^0.73.0",
|
|
55
|
+
"@mariozechner/pi-coding-agent": "^0.73.0",
|
|
56
|
+
"@mariozechner/pi-tui": "^0.73.0",
|
|
57
57
|
"typebox": "^1.1.24"
|
|
58
58
|
},
|
|
59
59
|
"devDependencies": {
|
|
60
|
-
"@mariozechner/pi-ai": "^0.
|
|
61
|
-
"@mariozechner/pi-coding-agent": "^0.
|
|
62
|
-
"@mariozechner/pi-tui": "^0.
|
|
60
|
+
"@mariozechner/pi-ai": "^0.73.0",
|
|
61
|
+
"@mariozechner/pi-coding-agent": "^0.73.0",
|
|
62
|
+
"@mariozechner/pi-tui": "^0.73.0",
|
|
63
63
|
"tsx": "^4.20.5",
|
|
64
64
|
"typebox": "^1.1.24",
|
|
65
65
|
"typescript": "^5.9.3"
|
|
@@ -2,7 +2,9 @@ import type { ExtensionAPI } from "@mariozechner/pi-coding-agent";
|
|
|
2
2
|
import { Box, Image, Spacer, Text } from "@mariozechner/pi-tui";
|
|
3
3
|
import {
|
|
4
4
|
createAssistantMessageEventStream,
|
|
5
|
+
appendAssistantMessageDiagnostic,
|
|
5
6
|
clampThinkingLevel,
|
|
7
|
+
createAssistantMessageDiagnostic,
|
|
6
8
|
getEnvApiKey,
|
|
7
9
|
type Api,
|
|
8
10
|
type AssistantMessage,
|
|
@@ -412,16 +414,6 @@ function headersToRecord(headers: Headers): Record<string, string> {
|
|
|
412
414
|
return Object.fromEntries(headers.entries());
|
|
413
415
|
}
|
|
414
416
|
|
|
415
|
-
function buildWebSocketCacheKey(url: string, headers: Headers, sessionId: string | undefined): string | undefined {
|
|
416
|
-
if (!sessionId) return undefined;
|
|
417
|
-
const headerFingerprint = Object.entries(headersToRecord(headers))
|
|
418
|
-
.map(([key, value]) => [key.toLowerCase(), value] as const)
|
|
419
|
-
.sort(([a], [b]) => a.localeCompare(b))
|
|
420
|
-
.map(([key, value]) => `${key}:${value}`)
|
|
421
|
-
.join("\n");
|
|
422
|
-
return `${sessionId}:${shortHash(`${url}\n${headerFingerprint}`)}`;
|
|
423
|
-
}
|
|
424
|
-
|
|
425
417
|
function createCodexRequestId(): string {
|
|
426
418
|
if (typeof globalThis.crypto?.randomUUID === "function") {
|
|
427
419
|
return globalThis.crypto.randomUUID();
|
|
@@ -674,6 +666,7 @@ function closeWebSocketSilently(socket: WebSocketLike, code = 1000, reason = "do
|
|
|
674
666
|
}
|
|
675
667
|
}
|
|
676
668
|
|
|
669
|
+
|
|
677
670
|
function scheduleSessionWebSocketExpiry(cacheKey: string, entry: SessionWebSocketCacheEntry): void {
|
|
678
671
|
if (entry.idleTimer) {
|
|
679
672
|
clearTimeout(entry.idleTimer);
|
|
@@ -772,8 +765,7 @@ async function acquireWebSocket(
|
|
|
772
765
|
sessionId: string | undefined,
|
|
773
766
|
signal: AbortSignal | undefined,
|
|
774
767
|
): Promise<AcquiredWebSocket> {
|
|
775
|
-
|
|
776
|
-
if (!cacheKey) {
|
|
768
|
+
if (!sessionId) {
|
|
777
769
|
const socket = await connectWebSocket(url, headers, signal);
|
|
778
770
|
return {
|
|
779
771
|
socket,
|
|
@@ -788,7 +780,7 @@ async function acquireWebSocket(
|
|
|
788
780
|
};
|
|
789
781
|
}
|
|
790
782
|
|
|
791
|
-
const cached = websocketSessionCache.get(
|
|
783
|
+
const cached = websocketSessionCache.get(sessionId);
|
|
792
784
|
if (cached) {
|
|
793
785
|
if (cached.idleTimer) {
|
|
794
786
|
clearTimeout(cached.idleTimer);
|
|
@@ -804,11 +796,11 @@ async function acquireWebSocket(
|
|
|
804
796
|
release: ({ keep } = {}) => {
|
|
805
797
|
if (!keep || !isWebSocketReusable(cached.socket)) {
|
|
806
798
|
closeWebSocketSilently(cached.socket);
|
|
807
|
-
websocketSessionCache.delete(
|
|
799
|
+
websocketSessionCache.delete(sessionId);
|
|
808
800
|
return;
|
|
809
801
|
}
|
|
810
802
|
cached.busy = false;
|
|
811
|
-
scheduleSessionWebSocketExpiry(
|
|
803
|
+
scheduleSessionWebSocketExpiry(sessionId, cached);
|
|
812
804
|
},
|
|
813
805
|
};
|
|
814
806
|
}
|
|
@@ -826,13 +818,13 @@ async function acquireWebSocket(
|
|
|
826
818
|
|
|
827
819
|
if (!isWebSocketReusable(cached.socket)) {
|
|
828
820
|
closeWebSocketSilently(cached.socket);
|
|
829
|
-
websocketSessionCache.delete(
|
|
821
|
+
websocketSessionCache.delete(sessionId);
|
|
830
822
|
}
|
|
831
823
|
}
|
|
832
824
|
|
|
833
825
|
const socket = await connectWebSocket(url, headers, signal);
|
|
834
826
|
const entry: SessionWebSocketCacheEntry = { socket, busy: true };
|
|
835
|
-
websocketSessionCache.set(
|
|
827
|
+
websocketSessionCache.set(sessionId, entry);
|
|
836
828
|
return {
|
|
837
829
|
socket,
|
|
838
830
|
entry,
|
|
@@ -841,13 +833,13 @@ async function acquireWebSocket(
|
|
|
841
833
|
if (!keep || !isWebSocketReusable(entry.socket)) {
|
|
842
834
|
closeWebSocketSilently(entry.socket);
|
|
843
835
|
if (entry.idleTimer) clearTimeout(entry.idleTimer);
|
|
844
|
-
if (websocketSessionCache.get(
|
|
845
|
-
websocketSessionCache.delete(
|
|
836
|
+
if (websocketSessionCache.get(sessionId) === entry) {
|
|
837
|
+
websocketSessionCache.delete(sessionId);
|
|
846
838
|
}
|
|
847
839
|
return;
|
|
848
840
|
}
|
|
849
841
|
entry.busy = false;
|
|
850
|
-
scheduleSessionWebSocketExpiry(
|
|
842
|
+
scheduleSessionWebSocketExpiry(sessionId, entry);
|
|
851
843
|
},
|
|
852
844
|
};
|
|
853
845
|
}
|
|
@@ -1197,7 +1189,8 @@ async function processWebSocketStream<TApi extends Api>(
|
|
|
1197
1189
|
let keepConnection = true;
|
|
1198
1190
|
let released = false;
|
|
1199
1191
|
let eventCount = 0;
|
|
1200
|
-
const
|
|
1192
|
+
const transport = (options as { transport?: string } | undefined)?.transport ?? "auto";
|
|
1193
|
+
const useCachedContext = transport === "websocket-cached" || transport === "auto";
|
|
1201
1194
|
// ChatGPT Codex Responses rejects `store: true` ("Store must be set to false").
|
|
1202
1195
|
// WebSocket continuation still works via connection-scoped previous_response_id state.
|
|
1203
1196
|
const fullBody = body;
|
|
@@ -1460,7 +1453,7 @@ function createCodexStream<TApi extends Api>(
|
|
|
1460
1453
|
const sseHeaders = buildSSEHeaders(model.headers, options?.headers, accountId, apiKey, options?.sessionId);
|
|
1461
1454
|
const websocketHeaders = buildWebSocketHeaders(model.headers, options?.headers, accountId, apiKey, websocketRequestId);
|
|
1462
1455
|
const bodyJson = JSON.stringify(body);
|
|
1463
|
-
const transport = options?.transport || "
|
|
1456
|
+
const transport = options?.transport || "auto";
|
|
1464
1457
|
|
|
1465
1458
|
if (transport !== "sse") {
|
|
1466
1459
|
let websocketStarted = false;
|
|
@@ -1488,6 +1481,16 @@ function createCodexStream<TApi extends Api>(
|
|
|
1488
1481
|
stream.end();
|
|
1489
1482
|
return;
|
|
1490
1483
|
} catch (error) {
|
|
1484
|
+
appendAssistantMessageDiagnostic(
|
|
1485
|
+
output,
|
|
1486
|
+
createAssistantMessageDiagnostic("provider_transport_failure", error, {
|
|
1487
|
+
configuredTransport: transport,
|
|
1488
|
+
fallbackTransport: websocketStarted ? undefined : "sse",
|
|
1489
|
+
eventsEmitted: websocketStarted,
|
|
1490
|
+
phase: websocketStarted ? "after_message_stream_start" : "before_message_stream_start",
|
|
1491
|
+
requestBytes: new TextEncoder().encode(bodyJson).byteLength,
|
|
1492
|
+
}),
|
|
1493
|
+
);
|
|
1491
1494
|
if (transport === "websocket" || transport === "websocket-cached" || websocketStarted) {
|
|
1492
1495
|
throw error;
|
|
1493
1496
|
}
|