@howaboua/pi-codex-conversion 1.0.30 → 1.0.31-dev.3.4b87b70

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 CHANGED
@@ -9,7 +9,7 @@ This package replaces Pi's default Codex/GPT experience with a narrower Codex-li
9
9
  - preserves Pi's composed system prompt and applies a narrow Codex-oriented delta on top
10
10
  - renders exec activity with Codex-style command and background-terminal labels
11
11
  - renders `apply_patch` calls with Codex-style `Added` / `Edited` / `Deleted` diff blocks and Pi-style colored diff lines
12
- - targets modern Pi tool/rendering APIs and is aligned with Pi `0.72.x`
12
+ - targets modern Pi tool/rendering APIs and is aligned with Pi `0.74.x` / the `@earendil-works/*` package scope
13
13
 
14
14
  ![Available tools](./available-tools.png)
15
15
 
@@ -0,0 +1,30 @@
1
+ #!/usr/bin/env node
2
+ import { spawnSync } from "node:child_process";
3
+ import { existsSync } from "node:fs";
4
+ import { dirname, join } from "node:path";
5
+ import { fileURLToPath } from "node:url";
6
+
7
+ const root = dirname(dirname(fileURLToPath(import.meta.url)));
8
+ const platform = process.platform;
9
+ const arch = process.arch;
10
+ const exe = platform === "win32" ? "apply_patch.exe" : "apply_patch";
11
+ const platformArch = `${platform}-${arch}`;
12
+ const binary = join(root, "vendor", "apply-patch", platformArch, exe);
13
+
14
+ if (!existsSync(binary)) {
15
+ console.error(`apply_patch binary is not bundled for ${platformArch}.`);
16
+ console.error("Expected bundled binaries under vendor/apply-patch/<platform>-<arch>/.");
17
+ process.exit(127);
18
+ }
19
+
20
+ const result = spawnSync(binary, process.argv.slice(2), {
21
+ stdio: "inherit",
22
+ env: process.env,
23
+ cwd: process.cwd(),
24
+ });
25
+
26
+ if (result.error) {
27
+ console.error(result.error.message);
28
+ process.exit(1);
29
+ }
30
+ process.exit(result.status ?? 0);
@@ -0,0 +1,2 @@
1
+ @echo off
2
+ node "%~dp0apply_patch" %*
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@howaboua/pi-codex-conversion",
3
- "version": "1.0.30",
3
+ "version": "1.0.31-dev.3.4b87b70",
4
4
  "description": "Codex-oriented tool and prompt adapter for pi coding agent",
5
5
  "type": "module",
6
6
  "repository": {
@@ -21,10 +21,6 @@
21
21
  "apply-patch"
22
22
  ],
23
23
  "license": "MIT",
24
- "os": [
25
- "darwin",
26
- "linux"
27
- ],
28
24
  "pi": {
29
25
  "extensions": [
30
26
  "./src/index.ts"
@@ -33,6 +29,9 @@
33
29
  "files": [
34
30
  "src/**/*.ts",
35
31
  "src/**/*.md",
32
+ "bin/apply_patch",
33
+ "bin/apply_patch.cmd",
34
+ "vendor/apply-patch/**",
36
35
  "available-tools.png",
37
36
  "README.md",
38
37
  "LICENSE"
@@ -45,21 +44,24 @@
45
44
  "publish:dev": "npm publish --tag dev",
46
45
  "release:dev": "npm version prerelease --preid dev && npm publish --tag dev",
47
46
  "prepack": "npm run check",
48
- "prepublishOnly": "npm run check"
47
+ "prepublishOnly": "npm run verify:apply-patch-binaries && npm run check",
48
+ "build:apply-patch": "node scripts/build-apply-patch-binary.mjs",
49
+ "sync:apply-patch-source": "node scripts/sync-apply-patch-source.mjs",
50
+ "verify:apply-patch-binaries": "node scripts/verify-apply-patch-binaries.mjs"
49
51
  },
50
52
  "publishConfig": {
51
53
  "access": "public"
52
54
  },
53
55
  "peerDependencies": {
54
- "@mariozechner/pi-ai": "^0.73.0",
55
- "@mariozechner/pi-coding-agent": "^0.73.0",
56
- "@mariozechner/pi-tui": "^0.73.0",
57
- "typebox": "^1.1.24"
56
+ "@earendil-works/pi-ai": "*",
57
+ "@earendil-works/pi-coding-agent": "*",
58
+ "@earendil-works/pi-tui": "*",
59
+ "typebox": "*"
58
60
  },
59
61
  "devDependencies": {
60
- "@mariozechner/pi-ai": "^0.73.0",
61
- "@mariozechner/pi-coding-agent": "^0.73.0",
62
- "@mariozechner/pi-tui": "^0.73.0",
62
+ "@earendil-works/pi-ai": "^0.74.0",
63
+ "@earendil-works/pi-coding-agent": "^0.74.0",
64
+ "@earendil-works/pi-tui": "^0.74.0",
63
65
  "tsx": "^4.20.5",
64
66
  "typebox": "^1.1.24",
65
67
  "typescript": "^5.9.3"
@@ -69,5 +71,8 @@
69
71
  "partial-json": "^0.1.7",
70
72
  "tree-sitter-bash": "^0.25.1",
71
73
  "web-tree-sitter": "^0.26.7"
74
+ },
75
+ "bin": {
76
+ "apply_patch": "./bin/apply_patch"
72
77
  }
73
78
  }
@@ -1,4 +1,4 @@
1
- import type { ExtensionContext } from "@mariozechner/pi-coding-agent";
1
+ import type { ExtensionContext } from "@earendil-works/pi-coding-agent";
2
2
 
3
3
  export interface CodexLikeModelDescriptor {
4
4
  provider: string;
package/src/index.ts CHANGED
@@ -1,4 +1,4 @@
1
- import type { ExtensionAPI, ExtensionContext } from "@mariozechner/pi-coding-agent";
1
+ import type { ExtensionAPI, ExtensionContext } from "@earendil-works/pi-coding-agent";
2
2
  import { getCodexRuntimeShell } from "./adapter/runtime-shell.ts";
3
3
  import {
4
4
  CORE_ADAPTER_TOOL_NAMES,
@@ -24,21 +24,18 @@ import { buildCodexSystemPrompt, extractPiPromptSkills, type PromptSkill } from
24
24
  import { registerViewImageTool, supportsOriginalImageDetail } from "./tools/view-image-tool.ts";
25
25
  import {
26
26
  registerWebSearchTool,
27
- registerWebSearchSessionNoteRenderer,
28
27
  rewriteNativeWebSearchTool,
29
- shouldShowWebSearchSessionNote,
30
28
  supportsNativeWebSearch,
31
- WEB_SEARCH_SESSION_NOTE_TEXT,
32
29
  WEB_SEARCH_SESSION_NOTE_TYPE,
33
30
  } from "./tools/web-search-tool.ts";
34
31
  import { registerWriteStdinTool } from "./tools/write-stdin-tool.ts";
32
+ import { ensureBundledApplyPatchOnPath } from "./tools/apply-patch-binary.ts";
35
33
 
36
34
  interface AdapterState {
37
35
  enabled: boolean;
38
36
  cwd: string;
39
37
  previousToolNames?: string[];
40
38
  promptSkills: PromptSkill[];
41
- webSearchNoticeShown: boolean;
42
39
  }
43
40
 
44
41
  const ADAPTER_TOOL_NAMES = [...CORE_ADAPTER_TOOL_NAMES, WEB_SEARCH_TOOL_NAME, IMAGE_GENERATION_TOOL_NAME, VIEW_IMAGE_TOOL_NAME];
@@ -61,8 +58,9 @@ function isToolCallOnlyAssistantMessage(message: unknown): boolean {
61
58
  }
62
59
 
63
60
  export default function codexConversion(pi: ExtensionAPI) {
61
+ ensureBundledApplyPatchOnPath();
64
62
  const tracker = createExecCommandTracker();
65
- const state: AdapterState = { enabled: false, cwd: process.cwd(), promptSkills: [], webSearchNoticeShown: false };
63
+ const state: AdapterState = { enabled: false, cwd: process.cwd(), promptSkills: [] };
66
64
  const sessions = createExecSessionManager();
67
65
 
68
66
  registerOpenAICodexCustomProvider(pi, {
@@ -73,7 +71,6 @@ export default function codexConversion(pi: ExtensionAPI) {
73
71
  registerWriteStdinTool(pi, sessions);
74
72
  registerImageGenerationTool(pi);
75
73
  registerWebSearchTool(pi);
76
- registerWebSearchSessionNoteRenderer(pi);
77
74
 
78
75
  sessions.onSessionExit((sessionId) => {
79
76
  tracker.recordSessionFinished(sessionId);
@@ -81,7 +78,6 @@ export default function codexConversion(pi: ExtensionAPI) {
81
78
 
82
79
  pi.on("session_start", async (_event, ctx) => {
83
80
  state.cwd = ctx.cwd;
84
- state.webSearchNoticeShown = false;
85
81
  clearApplyPatchRenderState();
86
82
  tracker.clear();
87
83
  syncAdapter(pi, ctx, state);
@@ -157,7 +153,6 @@ function syncAdapter(pi: ExtensionAPI, ctx: ExtensionContext, state: AdapterStat
157
153
  state.promptSkills = extractPiPromptSkills(ctx.getSystemPrompt());
158
154
 
159
155
  registerViewImageTool(pi, { allowOriginalDetail: supportsOriginalImageDetail(ctx.model) });
160
- maybeShowWebSearchSessionNote(pi, ctx, state);
161
156
 
162
157
  if (isCodexLikeContext(ctx)) {
163
158
  enableAdapter(pi, ctx, state);
@@ -227,15 +222,3 @@ export function restoreTools(previousTools: string[], activeTools: string[]): st
227
222
  function hasAdapterTools(activeTools: string[]): boolean {
228
223
  return activeTools.some((toolName) => ADAPTER_TOOL_NAMES.includes(toolName));
229
224
  }
230
-
231
- function maybeShowWebSearchSessionNote(pi: ExtensionAPI, ctx: ExtensionContext, state: AdapterState): void {
232
- if (!shouldShowWebSearchSessionNote(ctx.model, ctx.hasUI, state.webSearchNoticeShown)) {
233
- return;
234
- }
235
- pi.sendMessage({
236
- customType: WEB_SEARCH_SESSION_NOTE_TYPE,
237
- content: WEB_SEARCH_SESSION_NOTE_TEXT,
238
- display: true,
239
- });
240
- state.webSearchNoticeShown = true;
241
- }
@@ -1,5 +1,5 @@
1
- import type { ExtensionAPI } from "@mariozechner/pi-coding-agent";
2
- import { Box, Image, Spacer, Text } from "@mariozechner/pi-tui";
1
+ import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
2
+ import { Box, Image, Spacer, Text } from "@earendil-works/pi-tui";
3
3
  import {
4
4
  createAssistantMessageEventStream,
5
5
  appendAssistantMessageDiagnostic,
@@ -12,7 +12,7 @@ import {
12
12
  type Context,
13
13
  type Model,
14
14
  type SimpleStreamOptions,
15
- } from "@mariozechner/pi-ai";
15
+ } from "@earendil-works/pi-ai";
16
16
  import type { ResponseCreateParamsStreaming } from "openai/resources/responses/responses.js";
17
17
  import {
18
18
  convertResponsesMessages,
@@ -31,6 +31,7 @@ const BASE_DELAY_MS = 1000;
31
31
  const CODEX_TOOL_CALL_PROVIDERS = new Set(["openai", "openai-codex", "opencode"]);
32
32
  const CODEX_RESPONSE_STATUSES = new Set(["completed", "incomplete", "failed", "cancelled", "queued", "in_progress"]);
33
33
  const OPENAI_BETA_RESPONSES_WEBSOCKETS = "responses_websockets=2026-02-06";
34
+ const WEBSOCKET_MESSAGE_TOO_BIG_CLOSE_CODE = 1009;
34
35
  const SESSION_WEBSOCKET_CACHE_TTL_MS = 5 * 60 * 1000;
35
36
  const dynamicImport = (specifier: string) => import(specifier);
36
37
  let _os: { platform(): string; release(): string; arch(): string } | null = null;
@@ -515,7 +516,7 @@ function resolveCodexServiceTier(responseServiceTier: ServiceTier, requestServic
515
516
  return responseServiceTier ?? requestServiceTier;
516
517
  }
517
518
 
518
- function buildRequestBody<TApi extends Api>(model: Model<TApi>, context: Context, options?: SimpleStreamOptions): ResponsesBody {
519
+ export function buildRequestBody<TApi extends Api>(model: Model<TApi>, context: Context, options?: SimpleStreamOptions): ResponsesBody {
519
520
  const messages = convertResponsesMessages(model, context, CODEX_TOOL_CALL_PROVIDERS, {
520
521
  includeSystemPrompt: false,
521
522
  });
@@ -524,7 +525,7 @@ function buildRequestBody<TApi extends Api>(model: Model<TApi>, context: Context
524
525
  model: model.id,
525
526
  store: false,
526
527
  stream: true,
527
- instructions: context.systemPrompt,
528
+ instructions: context.systemPrompt || "You are a helpful assistant.",
528
529
  input: messages,
529
530
  text: { verbosity: ((options as { textVerbosity?: string } | undefined)?.textVerbosity ?? "low") as string },
530
531
  include: ["reasoning.encrypted_content"],
@@ -595,7 +596,7 @@ function sleep(ms: number, signal: AbortSignal | undefined): Promise<void> {
595
596
  });
596
597
  }
597
598
 
598
- async function* parseSSE(response: Response): AsyncIterable<StreamEventShape> {
599
+ export async function* parseSSE(response: Response): AsyncIterable<StreamEventShape> {
599
600
  if (!response.body) return;
600
601
 
601
602
  const reader = response.body.getReader();
@@ -622,8 +623,8 @@ async function* parseSSE(response: Response): AsyncIterable<StreamEventShape> {
622
623
  if (data && data !== "[DONE]") {
623
624
  try {
624
625
  yield JSON.parse(data) as StreamEventShape;
625
- } catch {
626
- // Ignore malformed SSE chunks and continue consuming the stream.
626
+ } catch (error) {
627
+ throw new Error(`Invalid Codex SSE JSON: ${error instanceof Error ? error.message : String(error)}`);
627
628
  }
628
629
  }
629
630
  }
@@ -666,6 +667,28 @@ function closeWebSocketSilently(socket: WebSocketLike, code = 1000, reason = "do
666
667
  }
667
668
  }
668
669
 
670
+ export function closeOpenAICodexWebSocketSessions(sessionId?: string): void {
671
+ const closeEntry = (entry: SessionWebSocketCacheEntry) => {
672
+ if (entry.idleTimer) {
673
+ clearTimeout(entry.idleTimer);
674
+ entry.idleTimer = undefined;
675
+ }
676
+ closeWebSocketSilently(entry.socket, 1000, "session_shutdown");
677
+ };
678
+
679
+ if (sessionId) {
680
+ const entry = websocketSessionCache.get(sessionId);
681
+ if (entry) closeEntry(entry);
682
+ websocketSessionCache.delete(sessionId);
683
+ return;
684
+ }
685
+
686
+ for (const entry of websocketSessionCache.values()) {
687
+ closeEntry(entry);
688
+ }
689
+ websocketSessionCache.clear();
690
+ }
691
+
669
692
 
670
693
  function scheduleSessionWebSocketExpiry(cacheKey: string, entry: SessionWebSocketCacheEntry): void {
671
694
  if (entry.idleTimer) {
@@ -693,7 +716,10 @@ function extractWebSocketCloseError(event: unknown): Error {
693
716
  const code = "code" in event ? (event as { code?: unknown }).code : undefined;
694
717
  const reason = "reason" in event ? (event as { reason?: unknown }).reason : undefined;
695
718
  const codeText = typeof code === "number" ? ` ${code}` : "";
696
- const reasonText = typeof reason === "string" && reason.length > 0 ? ` ${reason}` : "";
719
+ let reasonText = typeof reason === "string" && reason.length > 0 ? ` ${reason}` : "";
720
+ if (!reasonText && code === WEBSOCKET_MESSAGE_TOO_BIG_CLOSE_CODE) {
721
+ reasonText = " message too big";
722
+ }
697
723
  return new Error(`WebSocket closed${codeText}${reasonText}`.trim());
698
724
  }
699
725
  return new Error("WebSocket closed");
@@ -943,8 +969,9 @@ async function* parseWebSocket(socket: WebSocketLike, signal: AbortSignal | unde
943
969
  done = true;
944
970
  }
945
971
  queue.push(parsed);
946
- } catch {
947
- // ignore malformed websocket messages
972
+ } catch (error) {
973
+ failed = new Error(`Invalid Codex WebSocket JSON: ${error instanceof Error ? error.message : String(error)}`);
974
+ done = true;
948
975
  }
949
976
  })
950
977
  .catch((error: unknown) => {
@@ -1025,9 +1052,27 @@ async function* countWebSocketEvents(
1025
1052
  }
1026
1053
  }
1027
1054
 
1055
+ async function* startWebSocketOutputOnFirstEvent(
1056
+ events: AsyncIterable<StreamEventShape>,
1057
+ output: AssistantMessage,
1058
+ stream: AssistantMessageEventStream,
1059
+ onStart: () => void,
1060
+ ): AsyncIterable<StreamEventShape> {
1061
+ let started = false;
1062
+ for await (const event of events) {
1063
+ if (!started) {
1064
+ started = true;
1065
+ onStart();
1066
+ stream.push({ type: "start", partial: output });
1067
+ }
1068
+ yield event;
1069
+ }
1070
+ }
1071
+
1028
1072
  function isRetryableEarlyWebSocketError(error: unknown): boolean {
1029
1073
  const message = error instanceof Error ? error.message : String(error);
1030
- return /^WebSocket (error|closed)(?:\s|$)/.test(message);
1074
+ if (/message too big/i.test(message)) return false;
1075
+ return /^(?:WebSocket (?:error|closed)(?:\s|$)|Invalid Codex WebSocket JSON)/.test(message);
1031
1076
  }
1032
1077
 
1033
1078
  async function* mapCodexEvents(events: AsyncIterable<StreamEventShape>): AsyncIterable<StreamEventShape> {
@@ -1185,7 +1230,7 @@ async function processWebSocketStream<TApi extends Api>(
1185
1230
  let streamStarted = false;
1186
1231
 
1187
1232
  for (let attempt = 0; attempt < 2; attempt++) {
1188
- const { socket, entry, release, reused } = await acquireWebSocket(url, headers, options?.sessionId, options?.signal);
1233
+ const { socket, entry, release } = await acquireWebSocket(url, headers, options?.sessionId, options?.signal);
1189
1234
  let keepConnection = true;
1190
1235
  let released = false;
1191
1236
  let eventCount = 0;
@@ -1204,15 +1249,18 @@ async function processWebSocketStream<TApi extends Api>(
1204
1249
 
1205
1250
  try {
1206
1251
  socket.send(JSON.stringify({ type: "response.create", ...requestBody }));
1207
- if (!streamStarted) {
1208
- onStart();
1209
- stream.push({ type: "start", partial: output });
1210
- streamStarted = true;
1211
- }
1212
1252
  await processCapturedResponsesStream(
1213
- countWebSocketEvents(parseWebSocket(socket, options?.signal), () => {
1214
- eventCount++;
1215
- }),
1253
+ startWebSocketOutputOnFirstEvent(
1254
+ countWebSocketEvents(parseWebSocket(socket, options?.signal), () => {
1255
+ eventCount++;
1256
+ }),
1257
+ output,
1258
+ stream,
1259
+ () => {
1260
+ streamStarted = true;
1261
+ onStart();
1262
+ },
1263
+ ),
1216
1264
  output,
1217
1265
  stream,
1218
1266
  model,
@@ -1241,11 +1289,10 @@ async function processWebSocketStream<TApi extends Api>(
1241
1289
  }
1242
1290
  keepConnection = false;
1243
1291
  releaseOnce({ keep: false });
1244
- // Pi's stock provider reuses session WebSockets. In practice the Codex
1245
- // backend sometimes cleanly closes an idle cached socket between turns;
1246
- // if that stale socket fails before any response event, retry once on a
1247
- // fresh WebSocket without changing request shape or falling back transports.
1248
- if (attempt === 0 && reused && eventCount === 0 && !options?.signal?.aborted && isRetryableEarlyWebSocketError(error)) {
1292
+ // If WebSocket fails before the first response event, nothing has been
1293
+ // emitted to the UI/history yet. Retry once on a fresh WebSocket; if that
1294
+ // also fails, the caller can fall back to SSE for `auto` transport.
1295
+ if (attempt === 0 && eventCount === 0 && !streamStarted && !options?.signal?.aborted && isRetryableEarlyWebSocketError(error)) {
1249
1296
  continue;
1250
1297
  }
1251
1298
  throw error;
@@ -1659,6 +1706,7 @@ export function registerOpenAICodexCustomProvider(pi: ExtensionAPI, options: { g
1659
1706
  flushPendingMessages();
1660
1707
  }
1661
1708
  clearPendingMessages();
1709
+ closeOpenAICodexWebSocketSessions();
1662
1710
  });
1663
1711
 
1664
1712
  pi.on("agent_end", async () => {
@@ -1,7 +1,7 @@
1
- import { calculateCost, type Api, type AssistantMessage, type Context, type Model, type Tool, type Usage } from "@mariozechner/pi-ai";
1
+ import { calculateCost, type Api, type AssistantMessage, type Context, type Model, type Tool, type Usage } from "@earendil-works/pi-ai";
2
2
  import type { ResponseCreateParamsStreaming, ResponseInput, ResponseStreamEvent, Tool as OpenAITool } from "openai/resources/responses/responses.js";
3
3
  import { parse as partialParse } from "partial-json";
4
- import type { AssistantMessageEventStream } from "@mariozechner/pi-ai";
4
+ import type { AssistantMessageEventStream } from "@earendil-works/pi-ai";
5
5
 
6
6
  type MessageRole = Context["messages"][number]["role"];
7
7
  type Message = Context["messages"][number];
@@ -0,0 +1,21 @@
1
+ import { existsSync } from "node:fs";
2
+ import { dirname, delimiter, join } from "node:path";
3
+ import { fileURLToPath } from "node:url";
4
+
5
+ export function getBundledApplyPatchBinDir(): string {
6
+ return join(dirname(dirname(dirname(fileURLToPath(import.meta.url)))), "bin");
7
+ }
8
+
9
+ export function ensureBundledApplyPatchOnPath(env: NodeJS.ProcessEnv = process.env): string | undefined {
10
+ const binDir = getBundledApplyPatchBinDir();
11
+ const wrapperPath = join(binDir, process.platform === "win32" ? "apply_patch.cmd" : "apply_patch");
12
+ if (!existsSync(wrapperPath)) {
13
+ return undefined;
14
+ }
15
+ const currentPath = env.PATH ?? "";
16
+ const entries = currentPath.split(delimiter).filter(Boolean);
17
+ if (!entries.includes(binDir)) {
18
+ env.PATH = [binDir, ...entries].join(delimiter);
19
+ }
20
+ return binDir;
21
+ }
@@ -1,5 +1,5 @@
1
1
  import { isAbsolute, relative } from "node:path";
2
- import { renderDiff } from "@mariozechner/pi-coding-agent";
2
+ import { renderDiff } from "@earendil-works/pi-coding-agent";
3
3
  import { openFileAtPath } from "../patch/paths.ts";
4
4
  import { parsePatchActions } from "../patch/parser.ts";
5
5
  import type { ParsedPatchAction } from "../patch/types.ts";
@@ -1,6 +1,6 @@
1
1
  import { Type } from "typebox";
2
- import type { ExtensionAPI } from "@mariozechner/pi-coding-agent";
3
- import { Container, Text } from "@mariozechner/pi-tui";
2
+ import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
3
+ import { Container, Text } from "@earendil-works/pi-tui";
4
4
  import { executePatch } from "../patch/core.ts";
5
5
  import { ExecutePatchError, type ExecutePatchResult } from "../patch/types.ts";
6
6
  import { formatApplyPatchSummary, formatPatchTarget, renderApplyPatchCall } from "./apply-patch-rendering.ts";
@@ -1,6 +1,6 @@
1
- import type { ExtensionAPI } from "@mariozechner/pi-coding-agent";
1
+ import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
2
2
  import { Type } from "typebox";
3
- import { Container, Text } from "@mariozechner/pi-tui";
3
+ import { Container, Text } from "@earendil-works/pi-tui";
4
4
  import { renderExecCommandCall, renderGroupedExecCommandCall } from "./codex-rendering.ts";
5
5
  import type { ExecCommandTracker } from "./exec-command-state.ts";
6
6
  import type { ExecSessionManager, UnifiedExecResult } from "./exec-session-manager.ts";
@@ -1,6 +1,6 @@
1
- import type { ExtensionAPI, ExtensionContext, ToolDefinition } from "@mariozechner/pi-coding-agent";
1
+ import type { ExtensionAPI, ExtensionContext, ToolDefinition } from "@earendil-works/pi-coding-agent";
2
2
  import { Type } from "typebox";
3
- import { Container, Text } from "@mariozechner/pi-tui";
3
+ import { Container, Text } from "@earendil-works/pi-tui";
4
4
  import { isOpenAICodexModel } from "../adapter/codex-model.ts";
5
5
 
6
6
  export const IMAGE_GENERATION_UNSUPPORTED_MESSAGE =
@@ -6,9 +6,9 @@ import {
6
6
  type ExtensionAPI,
7
7
  type ExtensionContext,
8
8
  type ToolDefinition,
9
- } from "@mariozechner/pi-coding-agent";
9
+ } from "@earendil-works/pi-coding-agent";
10
10
  import { Type, type TSchema } from "typebox";
11
- import { Text } from "@mariozechner/pi-tui";
11
+ import { Text } from "@earendil-works/pi-tui";
12
12
 
13
13
  const VIEW_IMAGE_UNSUPPORTED_MESSAGE = "view_image is not allowed because you do not support image inputs";
14
14
  const DETAIL_DESCRIPTION =
@@ -1,14 +1,12 @@
1
- import type { ExtensionAPI, ExtensionContext, ToolDefinition } from "@mariozechner/pi-coding-agent";
1
+ import type { ExtensionAPI, ExtensionContext, ToolDefinition } from "@earendil-works/pi-coding-agent";
2
2
  import { Type } from "typebox";
3
- import { Box, Container, Text } from "@mariozechner/pi-tui";
3
+ import { Container, Text } from "@earendil-works/pi-tui";
4
4
  import { isOpenAICodexModel } from "../adapter/codex-model.ts";
5
5
 
6
6
  export const WEB_SEARCH_UNSUPPORTED_MESSAGE = "web_search is only available with the openai-codex provider";
7
7
  const WEB_SEARCH_LOCAL_EXECUTION_MESSAGE =
8
8
  "web_search is a native openai-codex provider tool and should not execute locally";
9
9
  export const WEB_SEARCH_SESSION_NOTE_TYPE = "codex-web-search-session-note";
10
- export const WEB_SEARCH_SESSION_NOTE_TEXT =
11
- "Native OpenAI Codex web search is enabled for this session. Search activity is surfaced as merged foldable status messages instead of native tool-call rows.";
12
10
  const WEB_SEARCH_MULTIMODAL_CONTENT_TYPES = ["text", "image"] as const;
13
11
 
14
12
  const WEB_SEARCH_PARAMETERS = Type.Unsafe<Record<string, never>>({
@@ -36,14 +34,6 @@ export function supportsNativeWebSearch(model: ExtensionContext["model"]): boole
36
34
  return isOpenAICodexModel(model);
37
35
  }
38
36
 
39
- export function shouldShowWebSearchSessionNote(
40
- model: ExtensionContext["model"],
41
- hasUI: boolean,
42
- alreadyShown: boolean,
43
- ): boolean {
44
- return hasUI && !alreadyShown && supportsNativeWebSearch(model);
45
- }
46
-
47
37
  export function supportsMultimodalNativeWebSearch(model: ExtensionContext["model"]): boolean {
48
38
  if (!supportsNativeWebSearch(model)) {
49
39
  return false;
@@ -130,12 +120,3 @@ export function createWebSearchTool(): ToolDefinition<typeof WEB_SEARCH_PARAMETE
130
120
  export function registerWebSearchTool(pi: ExtensionAPI): void {
131
121
  pi.registerTool(createWebSearchTool());
132
122
  }
133
-
134
- export function registerWebSearchSessionNoteRenderer(pi: ExtensionAPI): void {
135
- pi.registerMessageRenderer(WEB_SEARCH_SESSION_NOTE_TYPE, (_message, _options, theme) => {
136
- const box = new Box(1, 1, (text) => theme.bg("toolSuccessBg", text));
137
- box.addChild(new Text(theme.bold("Web search enabled"), 0, 0));
138
- box.addChild(new Text(`\n${theme.fg("dim", WEB_SEARCH_SESSION_NOTE_TEXT)}`, 0, 0));
139
- return box;
140
- });
141
- }
@@ -1,6 +1,6 @@
1
- import type { ExtensionAPI } from "@mariozechner/pi-coding-agent";
1
+ import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
2
2
  import { Type } from "typebox";
3
- import { Container, Text } from "@mariozechner/pi-tui";
3
+ import { Container, Text } from "@earendil-works/pi-tui";
4
4
  import { renderWriteStdinCall } from "./codex-rendering.ts";
5
5
  import type { ExecSessionManager, UnifiedExecResult } from "./exec-session-manager.ts";
6
6
  import { formatUnifiedExecResult } from "./unified-exec-format.ts";