@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.29",
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.72.0",
55
- "@mariozechner/pi-coding-agent": "^0.72.0",
56
- "@mariozechner/pi-tui": "^0.72.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.72.0",
61
- "@mariozechner/pi-coding-agent": "^0.72.0",
62
- "@mariozechner/pi-tui": "^0.72.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
- const cacheKey = buildWebSocketCacheKey(url, headers, sessionId);
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(cacheKey);
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(cacheKey);
799
+ websocketSessionCache.delete(sessionId);
808
800
  return;
809
801
  }
810
802
  cached.busy = false;
811
- scheduleSessionWebSocketExpiry(cacheKey, cached);
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(cacheKey);
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(cacheKey, entry);
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(cacheKey) === entry) {
845
- websocketSessionCache.delete(cacheKey);
836
+ if (websocketSessionCache.get(sessionId) === entry) {
837
+ websocketSessionCache.delete(sessionId);
846
838
  }
847
839
  return;
848
840
  }
849
841
  entry.busy = false;
850
- scheduleSessionWebSocketExpiry(cacheKey, entry);
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 useCachedContext = (options as { transport?: string } | undefined)?.transport === "websocket-cached";
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 || "sse";
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
  }