codex-plus-patcher 0.7.1 → 0.7.2

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": "codex-plus-patcher",
3
- "version": "0.7.1",
3
+ "version": "0.7.2",
4
4
  "private": false,
5
5
  "description": "Patch queue tool for building a local Codex Plus.app from an installed Codex.app.",
6
6
  "repository": {
package/src/cli.js CHANGED
@@ -13,6 +13,7 @@ const {
13
13
  const { readAsar, walkFiles } = require("./core/asar");
14
14
  const {
15
15
  DEFAULT_DEV_HOME,
16
+ DEFAULT_DEV_INSTANCE_ID,
16
17
  DEFAULT_ELECTRON_USER_DATA,
17
18
  formatLaunchDevResult,
18
19
  formatSyncDevHomeResult,
@@ -49,12 +50,14 @@ function parseArgs(argv) {
49
50
  includeNativeOpenProbes: false,
50
51
  noProgress: false,
51
52
  quiet: false,
53
+ devInstanceId: DEFAULT_DEV_INSTANCE_ID,
52
54
  };
53
55
  const rest = [...argv];
54
56
  if (rest[0] && !rest[0].startsWith("--")) args.command = rest.shift();
55
57
  if (args.command === "audit-plugins") {
56
58
  args.target = DEFAULT_AUDIT_TARGET;
57
59
  args.remoteDebuggingPort = DEFAULT_AUDIT_PORT;
60
+ args.devInstanceId = "audit";
58
61
  }
59
62
  for (let index = 0; index < rest.length; index += 1) {
60
63
  const arg = rest[index];
@@ -68,6 +71,7 @@ function parseArgs(argv) {
68
71
  else if (arg === "--source-home") args.sourceHome = path.resolve(expandPath(next()));
69
72
  else if (arg === "--dev-home") args.devHome = path.resolve(expandPath(next()));
70
73
  else if (arg === "--electron-user-data") args.electronUserDataPath = path.resolve(expandPath(next()));
74
+ else if (arg === "--dev-instance-id") args.devInstanceId = next();
71
75
  else if (arg === "--remote-debugging-port" || arg === "--port") {
72
76
  const value = next();
73
77
  args.remoteDebuggingPort = args.command === "audit-plugins" ? Number(value) : value;
@@ -120,6 +124,7 @@ Options:
120
124
  Isolated Electron userData for launch-dev. Default: ./work/codex-plus-electron-user-data
121
125
  --remote-debugging-port <port>
122
126
  Remote debugging port passed to launch-dev or audit-plugins
127
+ --dev-instance-id <id> Dev-only bundle identity suffix. Default: dev, or audit for audit-plugins
123
128
  --asar <path> app.asar path for ASAR readback commands
124
129
  --file <asar-path> Packed file path for asar-cat
125
130
  --contains <text> Filter asar-list paths by substring
@@ -396,6 +401,7 @@ async function main() {
396
401
  devHome: args.devHome,
397
402
  electronUserDataPath: args.electronUserDataPath,
398
403
  remoteDebuggingPort: args.remoteDebuggingPort,
404
+ devInstanceId: args.devInstanceId,
399
405
  });
400
406
  process.stdout.write(args.json ? `${JSON.stringify(result, null, 2)}\n` : formatLaunchDevResult(result));
401
407
  return;
package/src/core/asar.js CHANGED
@@ -11,9 +11,10 @@ function sha256File(file) {
11
11
 
12
12
  function readAsar(asarPath) {
13
13
  const buffer = fs.readFileSync(asarPath);
14
+ const headerSize = buffer.readUInt32LE(4);
14
15
  const jsonSize = buffer.readUInt32LE(12);
15
16
  const header = JSON.parse(buffer.subarray(16, 16 + jsonSize).toString("utf8"));
16
- return { buffer, dataStart: 16 + jsonSize, header };
17
+ return { buffer, dataStart: 8 + headerSize, header };
17
18
  }
18
19
 
19
20
  function walkFiles(node, prefix = "", out = []) {
@@ -99,13 +100,14 @@ function patchAsar(asarPath, fileTransforms, transformContext = {}) {
99
100
  }
100
101
 
101
102
  const json = Buffer.from(JSON.stringify(archive.header), "utf8");
103
+ const padding = Buffer.alloc((4 - (json.length % 4)) % 4);
102
104
  const header = Buffer.alloc(16);
103
105
  header.writeUInt32LE(4, 0);
104
- header.writeUInt32LE(json.length + 8, 4);
105
- header.writeUInt32LE(json.length + 4, 8);
106
+ header.writeUInt32LE(json.length + padding.length + 8, 4);
107
+ header.writeUInt32LE(json.length + padding.length + 4, 8);
106
108
  header.writeUInt32LE(json.length, 12);
107
109
 
108
- fs.writeFileSync(asarPath, Buffer.concat([header, json, ...dataBuffers]));
110
+ fs.writeFileSync(asarPath, Buffer.concat([header, json, padding, ...dataBuffers]));
109
111
  return sha256File(asarPath);
110
112
  }
111
113
 
@@ -4,12 +4,13 @@ const os = require("node:os");
4
4
  const path = require("node:path");
5
5
 
6
6
  const { patchAsar } = require("./asar");
7
- const { setPlistBuddyValue } = require("./plist");
7
+ const { replacePlistString, setPlistBuddyValue } = require("./plist");
8
8
 
9
9
  const ASAR_PATH_IN_BUNDLE = "Contents/Resources/app.asar";
10
10
  const RUNTIME_MANIFEST_FILE = "webview/assets/codex-plus/runtime-manifest.js";
11
11
  const DEFAULT_DEV_HOME = path.resolve("work/codex-plus-dev-home");
12
12
  const DEFAULT_ELECTRON_USER_DATA = path.resolve("work/codex-plus-electron-user-data");
13
+ const DEFAULT_DEV_INSTANCE_ID = "dev";
13
14
  const DEV_MODE_WARNING =
14
15
  "Dev mode shares the original Codex worktrees. Use it for UI/plugin validation; do not edit the same checkout from regular Codex and Codex Plus at the same time.";
15
16
 
@@ -179,11 +180,40 @@ function syncDevHome({
179
180
  };
180
181
  }
181
182
 
182
- function buildLaunchDev({ targetApp, devHome = DEFAULT_DEV_HOME, electronUserDataPath = DEFAULT_ELECTRON_USER_DATA, remoteDebuggingPort } = {}) {
183
+ function sanitizeDevInstanceId(devInstanceId) {
184
+ if (devInstanceId == null || devInstanceId === "") return null;
185
+ const sanitized = String(devInstanceId)
186
+ .trim()
187
+ .toLowerCase()
188
+ .replace(/[^a-z0-9-]+/g, "-")
189
+ .replace(/^-+|-+$/g, "");
190
+ if (!sanitized) throw new Error("--dev-instance-id must contain at least one letter or number");
191
+ return sanitized;
192
+ }
193
+
194
+ function devBundleIdentity(devInstanceId) {
195
+ const sanitized = sanitizeDevInstanceId(devInstanceId);
196
+ if (!sanitized) return null;
197
+ return {
198
+ id: sanitized,
199
+ bundleIdentifier: `com.openai.codex-plus.${sanitized}`,
200
+ displayName: `Codex Plus (${sanitized})`,
201
+ name: `Codex Plus ${sanitized}`,
202
+ };
203
+ }
204
+
205
+ function buildLaunchDev({
206
+ targetApp,
207
+ devHome = DEFAULT_DEV_HOME,
208
+ electronUserDataPath = DEFAULT_ELECTRON_USER_DATA,
209
+ remoteDebuggingPort,
210
+ devInstanceId = DEFAULT_DEV_INSTANCE_ID,
211
+ } = {}) {
183
212
  if (!targetApp) throw new Error("--target is required");
184
213
  const appBinary = path.join(path.resolve(targetApp), "Contents/MacOS/Codex");
185
214
  const resolvedDevHome = path.resolve(devHome);
186
215
  const resolvedElectronUserDataPath = path.resolve(electronUserDataPath);
216
+ const instanceIdentity = devBundleIdentity(devInstanceId);
187
217
  const args = [`--user-data-dir=${resolvedElectronUserDataPath}`];
188
218
  if (remoteDebuggingPort != null) args.push(`--remote-debugging-port=${remoteDebuggingPort}`);
189
219
  return {
@@ -193,6 +223,7 @@ function buildLaunchDev({ targetApp, devHome = DEFAULT_DEV_HOME, electronUserDat
193
223
  CODEX_HOME: resolvedDevHome,
194
224
  CODEX_ELECTRON_USER_DATA_PATH: resolvedElectronUserDataPath,
195
225
  },
226
+ instanceIdentity,
196
227
  warning: DEV_MODE_WARNING,
197
228
  };
198
229
  }
@@ -217,18 +248,46 @@ function markDevRuntimeConfig(targetApp, { patchAsarImpl = patchAsar, setPlistBu
217
248
  return { asar: asarPath, patchedAsarSha };
218
249
  }
219
250
 
220
- function launchDevApp({ spawn = childProcess.spawn, env = process.env, markDevRuntimeConfigImpl = markDevRuntimeConfig, ...options } = {}) {
251
+ function signDevApp(targetApp, execFileSync = childProcess.execFileSync) {
252
+ execFileSync("/usr/bin/codesign", ["--force", "--deep", "--sign", "-", path.resolve(targetApp)], { stdio: "pipe" });
253
+ return { signed: true };
254
+ }
255
+
256
+ function markDevBundleIdentity(
257
+ targetApp,
258
+ devInstanceId = DEFAULT_DEV_INSTANCE_ID,
259
+ { replacePlistStringImpl = replacePlistString } = {},
260
+ ) {
261
+ const identity = devBundleIdentity(devInstanceId);
262
+ if (!identity) return null;
263
+ const plistPath = path.join(path.resolve(targetApp), "Contents/Info.plist");
264
+ replacePlistStringImpl(plistPath, "CFBundleIdentifier", identity.bundleIdentifier);
265
+ replacePlistStringImpl(plistPath, "CFBundleDisplayName", identity.displayName);
266
+ replacePlistStringImpl(plistPath, "CFBundleName", identity.name);
267
+ return identity;
268
+ }
269
+
270
+ function launchDevApp({
271
+ spawn = childProcess.spawn,
272
+ env = process.env,
273
+ markDevRuntimeConfigImpl = markDevRuntimeConfig,
274
+ markDevBundleIdentityImpl = markDevBundleIdentity,
275
+ signDevAppImpl = signDevApp,
276
+ ...options
277
+ } = {}) {
221
278
  const launch = buildLaunchDev(options);
222
279
  fs.mkdirSync(launch.env.CODEX_HOME, { recursive: true });
223
280
  fs.mkdirSync(launch.env.CODEX_ELECTRON_USER_DATA_PATH, { recursive: true });
224
281
  const devRuntimeConfig = markDevRuntimeConfigImpl(options.targetApp);
282
+ const devBundle = markDevBundleIdentityImpl(options.targetApp, options.devInstanceId);
283
+ const devSignature = signDevAppImpl(options.targetApp);
225
284
  const child = spawn(launch.command, launch.args, {
226
285
  detached: true,
227
286
  env: { ...env, ...launch.env },
228
287
  stdio: "ignore",
229
288
  });
230
289
  child.unref();
231
- return { ...launch, devRuntimeConfig, pid: child.pid };
290
+ return { ...launch, devRuntimeConfig, devBundle, devSignature, pid: child.pid };
232
291
  }
233
292
 
234
293
  function formatSyncDevHomeResult(result) {
@@ -255,6 +314,7 @@ function formatLaunchDevResult(result) {
255
314
  `CODEX_ELECTRON_USER_DATA_PATH: ${result.env.CODEX_ELECTRON_USER_DATA_PATH}`,
256
315
  ];
257
316
  if (result.pid != null) lines.push(`PID: ${result.pid}`);
317
+ if (result.instanceIdentity) lines.push(`Bundle identity: ${result.instanceIdentity.bundleIdentifier}`);
258
318
  lines.push(`Warning: ${result.warning}`);
259
319
  return `${lines.join("\n")}\n`;
260
320
  }
@@ -262,13 +322,18 @@ function formatLaunchDevResult(result) {
262
322
  module.exports = {
263
323
  COPY_ENTRIES,
264
324
  DEFAULT_DEV_HOME,
325
+ DEFAULT_DEV_INSTANCE_ID,
265
326
  DEFAULT_ELECTRON_USER_DATA,
266
327
  DEV_MODE_WARNING,
267
328
  SQLITE_SNAPSHOT_ENTRIES,
268
329
  buildLaunchDev,
330
+ devBundleIdentity,
269
331
  formatLaunchDevResult,
270
332
  formatSyncDevHomeResult,
271
333
  launchDevApp,
334
+ markDevBundleIdentity,
272
335
  markDevRuntimeConfig,
336
+ sanitizeDevInstanceId,
337
+ signDevApp,
273
338
  syncDevHome,
274
339
  };
@@ -40,6 +40,7 @@ function parseArgs(argv) {
40
40
  includeNativeOpenProbes: false,
41
41
  noProgress: false,
42
42
  quiet: false,
43
+ devInstanceId: "audit",
43
44
  };
44
45
  for (let index = 0; index < argv.length; index += 1) {
45
46
  const arg = argv[index];
@@ -53,6 +54,7 @@ function parseArgs(argv) {
53
54
  else if (arg === "--source-home") args.sourceHome = path.resolve(expandPath(next()));
54
55
  else if (arg === "--dev-home") args.devHome = path.resolve(expandPath(next()));
55
56
  else if (arg === "--electron-user-data") args.electronUserDataPath = path.resolve(expandPath(next()));
57
+ else if (arg === "--dev-instance-id") args.devInstanceId = next();
56
58
  else if (arg === "--remote-debugging-port" || arg === "--port") args.remoteDebuggingPort = Number(next());
57
59
  else if (arg === "--no-apply") args.apply = false;
58
60
  else if (arg === "--no-launch") args.launch = false;
@@ -168,6 +170,88 @@ async function findRendererTargetOnPort(port) {
168
170
  }
169
171
  }
170
172
 
173
+ async function waitForMermaidViewerTarget(port, beforeIds = new Set(), timeoutMs = 10000) {
174
+ const deadline = Date.now() + timeoutMs;
175
+ let lastError = null;
176
+ while (Date.now() < deadline) {
177
+ try {
178
+ const targets = await getJson(`http://127.0.0.1:${port}/json/list`);
179
+ const target = targets.find((entry) =>
180
+ !beforeIds.has(entry.id) &&
181
+ entry.url?.startsWith("file://") &&
182
+ entry.url.includes("codex-plus-mermaid-"));
183
+ if (target) return target;
184
+ } catch (error) {
185
+ lastError = error;
186
+ }
187
+ await delay(250);
188
+ }
189
+ throw new Error(`Timed out waiting for Mermaid viewer target on port ${port}${lastError ? `: ${lastError.message}` : ""}`);
190
+ }
191
+
192
+ async function verifyMermaidViewerRender(appCdp, port, { Session = CdpSession, timeoutMs = 15000 } = {}) {
193
+ const beforeTargets = await getJson(`http://127.0.0.1:${port}/json/list`).catch(() => []);
194
+ const beforeIds = new Set(beforeTargets.map((target) => target.id));
195
+ await appCdp.evaluate(`(() => {
196
+ const host = document.createElement("div");
197
+ host.setAttribute("data-markdown-copy", "code-block");
198
+ const pre = document.createElement("pre");
199
+ pre.className = "sr-only";
200
+ pre.textContent = "graph TD;A-->B";
201
+ const diagram = document.createElement("div");
202
+ diagram.setAttribute("data-codex-plus-mermaid-diagram", "");
203
+ host.append(pre, diagram);
204
+ document.body.appendChild(host);
205
+ window.CodexPlus.plugins.get("mermaidFullscreen").exports.openViewer(diagram);
206
+ setTimeout(() => host.remove(), 1000);
207
+ return true;
208
+ })()`);
209
+ const viewerTarget = await waitForMermaidViewerTarget(port, beforeIds, timeoutMs);
210
+ const viewer = new Session(viewerTarget.webSocketDebuggerUrl);
211
+ try {
212
+ await viewer.connect();
213
+ await viewer.send("Runtime.enable");
214
+ const deadline = Date.now() + timeoutMs;
215
+ let status = null;
216
+ while (Date.now() < deadline) {
217
+ status = await viewer.evaluate(`(() => {
218
+ const svg = document.querySelector("#stage svg");
219
+ const status = document.getElementById("render-status")?.textContent || "";
220
+ return {
221
+ hasSvg: Boolean(svg && svg.outerHTML.length > 1000),
222
+ status,
223
+ statusHidden: document.getElementById("render-status")?.hidden ?? null,
224
+ svgLength: svg?.outerHTML?.length || 0,
225
+ bodyText: document.body?.innerText?.slice(0, 500) || "",
226
+ };
227
+ })()`);
228
+ if (status.hasSvg && !/Mermaid render failed:/i.test(status.status)) {
229
+ return {
230
+ ok: true,
231
+ url: viewerTarget.url,
232
+ status: status.status,
233
+ svgLength: status.svgLength,
234
+ };
235
+ }
236
+ if (/Mermaid render failed:/i.test(status.status) || /Mermaid render failed:/i.test(status.bodyText)) break;
237
+ await delay(250);
238
+ }
239
+ return {
240
+ ok: false,
241
+ url: viewerTarget.url,
242
+ message: status?.status || "Mermaid viewer did not render an SVG",
243
+ status,
244
+ };
245
+ } finally {
246
+ try {
247
+ await viewer.send("Page.close");
248
+ } catch {
249
+ // The viewer may already be closed.
250
+ }
251
+ await viewer.close();
252
+ }
253
+ }
254
+
171
255
  function listRunningAuditApps({
172
256
  targetApp = DEFAULT_TARGET,
173
257
  electronUserDataPath = DEFAULT_ELECTRON_USER_DATA,
@@ -361,16 +445,21 @@ async function waitForAppShellMounted(cdp, timeoutMs = 90000) {
361
445
  const root = document.getElementById("root");
362
446
  const bodyText = document.body?.innerText?.trim() ?? "";
363
447
  const interactiveCount = document.querySelectorAll("button,a,nav,[role=navigation]").length;
448
+ const hasErrorBoundary = /^Oops, an error has occurred\\b/.test(bodyText);
364
449
  return {
365
450
  readyState: document.readyState,
366
451
  hasRoot: Boolean(root),
367
452
  hasStartupLoader: Boolean(document.querySelector("#root .startup-loader")),
453
+ hasErrorBoundary,
368
454
  bodyTextLength: bodyText.length,
369
455
  elementCount: document.querySelectorAll("*").length,
370
456
  interactiveCount,
371
457
  sampleText: bodyText.slice(0, 120),
372
458
  };
373
459
  })()`);
460
+ if (lastStatus.hasErrorBoundary) {
461
+ throw new Error(`Codex app shell rendered error boundary: ${JSON.stringify(lastStatus)}`);
462
+ }
374
463
  if (
375
464
  lastStatus.readyState === "complete" &&
376
465
  lastStatus.hasRoot &&
@@ -407,10 +496,12 @@ function formatAuditJson(result) {
407
496
  }
408
497
 
409
498
  function formatAuditResult(result, { quiet = false } = {}) {
499
+ const expectedWarnings = result.expectedWarnings || [];
410
500
  if (quiet) {
411
- return result.ok
412
- ? "All plugin probes passed.\n"
413
- : `Plugin audit failed: ${result.failures.length} failures\n`;
501
+ if (!result.ok) return `Plugin audit failed: ${result.failures.length} failures\n`;
502
+ return expectedWarnings.length > 0
503
+ ? "All plugin probes passed with expected warnings.\n"
504
+ : "All plugin probes passed.\n";
414
505
  }
415
506
 
416
507
  if (!result.ok) {
@@ -440,6 +531,13 @@ function formatAuditResult(result, { quiet = false } = {}) {
440
531
  }
441
532
  lines.push("");
442
533
  }
534
+ if (expectedWarnings.length > 0) {
535
+ lines.push("Expected warnings:");
536
+ for (const warning of expectedWarnings) {
537
+ lines.push(` ${warning.plugin || "audit"} ${warning.code || "warning"}: ${warning.message || "expected warning"}`);
538
+ }
539
+ lines.push("");
540
+ }
443
541
  lines.push("Re-run with --json for full probe details.");
444
542
  return `${lines.join("\n").replace(/\n{3,}/g, "\n\n")}\n`;
445
543
  }
@@ -466,11 +564,18 @@ function formatAuditResult(result, { quiet = false } = {}) {
466
564
  `Runtime ready: ${runtime.registered ?? result.registeredPlugins?.length ?? 0} registered, ${runtime.started ?? result.startedPlugins?.length ?? 0} started`,
467
565
  `App shell: ${appShell.hasStartupLoader === false ? "mounted" : "unknown"}`,
468
566
  `Probed ${probeCount} plugins`,
567
+ `Warnings: ${expectedWarnings.length} expected`,
469
568
  `Native open probes: ${result.nativeOpenProbes?.included ? "included" : "skipped"}`,
470
569
  `Cleanup: ${cleanupText}`,
471
570
  "",
472
571
  "All plugin probes passed.",
473
572
  );
573
+ if (expectedWarnings.length > 0) {
574
+ lines.push("", "Expected warnings:");
575
+ for (const warning of expectedWarnings) {
576
+ lines.push(`${warning.plugin || "audit"} ${warning.code || "warning"}: ${warning.message || "expected warning"}`);
577
+ }
578
+ }
474
579
  return `${lines.join("\n")}\n`;
475
580
  }
476
581
 
@@ -661,12 +766,16 @@ function pluginAuditExpression({ includeNativeOpenProbes = false } = {}) {
661
766
  ];
662
767
  const pluginResults = {};
663
768
  const failures = [];
769
+ const expectedWarnings = [];
664
770
  const add = (id, ok, details = {}) => {
665
771
  pluginResults[id] = { ok, ...details };
666
772
  if (!ok) failures.push({ plugin: id, message: details.message || "probe failed", details });
667
773
  };
668
774
  const fail = (id, error, details = {}) => add(id, false, { message: error?.message || String(error), ...details });
669
775
  const pass = (id, details = {}) => add(id, true, details);
776
+ const warn = (id, code, message, details = {}) => {
777
+ expectedWarnings.push({ plugin: id, code, message, details });
778
+ };
670
779
  const pluginIds = () => {
671
780
  if (typeof window.CodexPlus?.plugins?.list !== "function") {
672
781
  throw new Error("CodexPlus.plugins.list is not available");
@@ -721,6 +830,120 @@ function pluginAuditExpression({ includeNativeOpenProbes = false } = {}) {
721
830
  evidence,
722
831
  };
723
832
  };
833
+ const waitForProjectThreadRows = async (timeoutMs = 45000) => {
834
+ const startedAt = Date.now();
835
+ while (Date.now() - startedAt < timeoutMs) {
836
+ const rows = document.querySelectorAll("[data-app-action-sidebar-project-list-id] [data-app-action-sidebar-thread-row]");
837
+ if (rows.length > 0) return rows.length;
838
+ await new Promise((resolve) => setTimeout(resolve, 500));
839
+ }
840
+ return 0;
841
+ };
842
+ const isTransparentColor = (value) => value === "rgba(0, 0, 0, 0)" || value === "transparent";
843
+ const waitForMountedProjectComposer = async (expectedAccent, timeoutMs = 20000) => {
844
+ const startedAt = Date.now();
845
+ while (Date.now() - startedAt < timeoutMs) {
846
+ const editor = document.querySelector("[data-codex-composer]");
847
+ const surface = editor?.closest("[data-codex-plus-user-entry]") || editor?.closest(".composer-surface-chrome");
848
+ if (surface) {
849
+ const computed = getComputedStyle(surface);
850
+ const surfaceAccent = computed.getPropertyValue("--codex-plus-project-accent").trim();
851
+ if (
852
+ surface.hasAttribute("data-codex-plus-user-entry") &&
853
+ surface.hasAttribute("data-codex-plus-project-color") &&
854
+ surfaceAccent === expectedAccent &&
855
+ computed.boxShadow !== "none"
856
+ ) {
857
+ return {
858
+ marked: true,
859
+ projectMarked: true,
860
+ accent: surfaceAccent,
861
+ boxShadow: computed.boxShadow,
862
+ };
863
+ }
864
+ }
865
+ await new Promise((resolve) => setTimeout(resolve, 250));
866
+ }
867
+ const editor = document.querySelector("[data-codex-composer]");
868
+ const surface = editor?.closest("[data-codex-plus-user-entry]") || editor?.closest(".composer-surface-chrome");
869
+ const computed = surface ? getComputedStyle(surface) : null;
870
+ return {
871
+ marked: surface?.hasAttribute("data-codex-plus-user-entry") || false,
872
+ projectMarked: surface?.hasAttribute("data-codex-plus-project-color") || false,
873
+ accent: computed?.getPropertyValue("--codex-plus-project-accent").trim() || "",
874
+ boxShadow: computed?.boxShadow || "",
875
+ };
876
+ };
877
+ const composerPermissionPickerStatus = () => {
878
+ const editor = document.querySelector("[data-codex-composer]");
879
+ const labels = ["Full access", "Ask for approval", "Approve for me", "Custom"];
880
+ const normalize = (value) => String(value || "").replace(/\s+/g, " ").trim();
881
+ const rgb = (value) => {
882
+ const match = String(value || "").match(/rgba?\((\d+),\s*(\d+),\s*(\d+)/);
883
+ return match ? [Number(match[1]), Number(match[2]), Number(match[3])] : null;
884
+ };
885
+ const luminance = (color) => {
886
+ if (!color) return null;
887
+ const channel = (value) => {
888
+ const normalized = value / 255;
889
+ return normalized <= 0.03928 ? normalized / 12.92 : Math.pow((normalized + 0.055) / 1.055, 2.4);
890
+ };
891
+ return 0.2126 * channel(color[0]) + 0.7152 * channel(color[1]) + 0.0722 * channel(color[2]);
892
+ };
893
+ const contrast = (foreground, background) => {
894
+ const fg = luminance(rgb(foreground));
895
+ const bg = luminance(rgb(background));
896
+ if (fg == null || bg == null) return null;
897
+ const lighter = Math.max(fg, bg);
898
+ const darker = Math.min(fg, bg);
899
+ return (lighter + 0.05) / (darker + 0.05);
900
+ };
901
+ const isTransparent = (value) => {
902
+ const text = String(value || "").trim();
903
+ return text === "transparent" || text === "rgba(0, 0, 0, 0)" || /rgba\([^)]*,\s*0\)$/.test(text);
904
+ };
905
+ const trigger = Array.from(document.querySelectorAll("button")).find((button) => {
906
+ const text = normalize(button.textContent);
907
+ return labels.some((label) => text === label || text.startsWith(`${label} `));
908
+ });
909
+ const triggerStyle = trigger ? getComputedStyle(trigger) : null;
910
+ const surface = editor?.closest("[data-codex-plus-user-entry]");
911
+ const surfaceStyle = surface ? getComputedStyle(surface) : null;
912
+ let labelStyle = null;
913
+ if (trigger) {
914
+ const walker = document.createTreeWalker(trigger, NodeFilter.SHOW_TEXT);
915
+ while (walker.nextNode()) {
916
+ const node = walker.currentNode;
917
+ if (normalize(node.nodeValue) !== "") {
918
+ labelStyle = getComputedStyle(node.parentElement);
919
+ break;
920
+ }
921
+ }
922
+ }
923
+ const triggerColor = triggerStyle?.color || null;
924
+ const labelColor = labelStyle?.color || triggerColor;
925
+ const labelTextFillColor = labelStyle?.webkitTextFillColor || triggerStyle?.webkitTextFillColor || null;
926
+ const effectiveLabelColor = labelTextFillColor && !isTransparent(labelTextFillColor) ? labelTextFillColor : labelColor;
927
+ const surfaceBackground = surfaceStyle?.backgroundColor || null;
928
+ return {
929
+ editorMounted: Boolean(editor),
930
+ editorEditable: editor?.getAttribute("contenteditable") === "true",
931
+ editorText: normalize(editor?.textContent),
932
+ triggerMounted: Boolean(trigger),
933
+ triggerText: normalize(trigger?.textContent),
934
+ triggerDisabled: Boolean(trigger?.disabled),
935
+ triggerAriaDisabled: trigger?.getAttribute("aria-disabled") || null,
936
+ triggerState: trigger?.getAttribute("data-state") || null,
937
+ triggerOpacity: triggerStyle?.opacity || null,
938
+ triggerColor,
939
+ labelColor,
940
+ labelTextFillColor,
941
+ surfaceBackground,
942
+ triggerContrast: contrast(effectiveLabelColor, surfaceBackground),
943
+ labelTextFillTransparent: isTransparent(labelTextFillColor),
944
+ triggerClassName: String(trigger?.className || ""),
945
+ };
946
+ };
724
947
  const jsx = (type, props, key) => ({ type, props: props || {}, key });
725
948
  const jsxs = jsx;
726
949
  const reviewDeps = {
@@ -835,14 +1058,63 @@ function pluginAuditExpression({ includeNativeOpenProbes = false } = {}) {
835
1058
  props?.style?.["--codex-plus-project-accent"] === accent);
836
1059
  const liveRows = Array.from(document.querySelectorAll("[data-codex-plus-project-color]"));
837
1060
  const liveAccents = liveRows.map((row) => getComputedStyle(row).getPropertyValue("--codex-plus-project-accent").trim()).filter(Boolean);
1061
+ const projectThreadRowCount = await waitForProjectThreadRows();
1062
+ let selectedProjectAccent = "";
1063
+ let mountedComposer = null;
1064
+ const unstyledProjectThreadLists = Array.from(document.querySelectorAll("[data-app-action-sidebar-project-list-id]"))
1065
+ .map((list) => {
1066
+ const projectId = list.getAttribute("data-app-action-sidebar-project-list-id") || "";
1067
+ const projectRow = document.querySelector(`[data-app-action-sidebar-project-row][data-app-action-sidebar-project-id="${CSS.escape(projectId)}"]`);
1068
+ const threadRows = Array.from(list.querySelectorAll("[data-app-action-sidebar-thread-row]"));
1069
+ if (!projectRow || threadRows.length === 0) return null;
1070
+ const projectAccent = getComputedStyle(projectRow).getPropertyValue("--codex-plus-project-accent").trim();
1071
+ const listComputed = getComputedStyle(list);
1072
+ const listAccent = listComputed.getPropertyValue("--codex-plus-project-accent").trim();
1073
+ const listBackground = listComputed.backgroundColor;
1074
+ if (!selectedProjectAccent) {
1075
+ selectedProjectAccent = projectAccent;
1076
+ threadRows[0].click();
1077
+ }
1078
+ const unstyledRows = threadRows.filter((row) => {
1079
+ const computed = getComputedStyle(row);
1080
+ const rowAccent = computed.getPropertyValue("--codex-plus-project-accent").trim();
1081
+ return rowAccent !== projectAccent || isTransparentColor(computed.backgroundColor);
1082
+ });
1083
+ return list.hasAttribute("data-codex-plus-project-sidebar-color") &&
1084
+ listAccent === projectAccent &&
1085
+ !isTransparentColor(listBackground) &&
1086
+ unstyledRows.length === 0
1087
+ ? null
1088
+ : {
1089
+ projectId,
1090
+ projectLabel: projectRow.getAttribute("data-app-action-sidebar-project-label") || projectRow.innerText.trim(),
1091
+ projectAccent,
1092
+ listAccent,
1093
+ listBackground,
1094
+ threadRows: threadRows.length,
1095
+ unstyledRows: unstyledRows.length,
1096
+ listMarked: list.hasAttribute("data-codex-plus-project-sidebar-color"),
1097
+ };
1098
+ })
1099
+ .filter(Boolean);
1100
+ if (selectedProjectAccent) mountedComposer = await waitForMountedProjectComposer(selectedProjectAccent);
838
1101
  if (!accent) throw new Error("Project accent was not computed");
839
1102
  if (!matchingProps) throw new Error("Project, thread, bubble, and composer props do not share an accent");
1103
+ if (projectThreadRowCount === 0) throw new Error("No visible project child thread rows appeared; project sidebar styling was not proven");
1104
+ if (unstyledProjectThreadLists.length > 0) {
1105
+ throw new Error(`Project sidebar child rows or list containers are not styled like their project rows: ${JSON.stringify(unstyledProjectThreadLists.slice(0, 4))}`);
1106
+ }
1107
+ if (!mountedComposer?.marked || !mountedComposer?.projectMarked || mountedComposer?.accent !== selectedProjectAccent) {
1108
+ throw new Error(`Mounted composer does not carry the selected project accent: ${JSON.stringify(mountedComposer)}`);
1109
+ }
840
1110
  pass("projectColors", {
841
1111
  ...details,
842
1112
  accent,
843
1113
  matchingProps,
844
1114
  liveRows: liveRows.length,
845
1115
  liveAccents: Array.from(new Set(liveAccents)).slice(0, 8),
1116
+ styledProjectThreadLists: projectThreadRowCount,
1117
+ mountedComposer,
846
1118
  });
847
1119
  } catch (error) {
848
1120
  fail("projectColors", error);
@@ -860,6 +1132,33 @@ function pluginAuditExpression({ includeNativeOpenProbes = false } = {}) {
860
1132
  fail("projectPathHeader", error);
861
1133
  }
862
1134
 
1135
+ try {
1136
+ const status = composerPermissionPickerStatus();
1137
+ if (status.editorMounted && status.editorEditable && status.triggerMounted) {
1138
+ const lowOpacity = Number(status.triggerOpacity) < 0.5;
1139
+ const lowContrast = status.triggerContrast != null && status.triggerContrast < 4.5;
1140
+ if (lowOpacity || lowContrast || status.labelTextFillTransparent) {
1141
+ throw new Error(`Composer permissions picker text is unreadable: ${JSON.stringify(status)}`);
1142
+ }
1143
+ const ariaDisabled = status.triggerAriaDisabled === "true";
1144
+ const visuallyDisabled = /\bopacity-40\b/.test(status.triggerClassName);
1145
+ if (status.triggerDisabled || ariaDisabled || visuallyDisabled) {
1146
+ warn(
1147
+ "audit",
1148
+ "composer-permission-picker-disabled",
1149
+ "Composer permissions picker is disabled while the composer is editable",
1150
+ status,
1151
+ );
1152
+ }
1153
+ }
1154
+ if (!status.editorMounted || !status.triggerMounted) {
1155
+ throw new Error(`Composer permissions picker was not found: ${JSON.stringify(status)}`);
1156
+ }
1157
+ pass("audit", { composerPermissionPicker: status });
1158
+ } catch (error) {
1159
+ fail("audit", error);
1160
+ }
1161
+
863
1162
  try {
864
1163
  const details = checkCommon("sidebarNameBlur");
865
1164
  const metadata = window.CodexPlus.ui.commands.commandMetadata().some((command) => command.id === "codexPlusToggleSidebarNameBlur");
@@ -991,6 +1290,7 @@ function pluginAuditExpression({ includeNativeOpenProbes = false } = {}) {
991
1290
  ok: failures.length === 0,
992
1291
  failures,
993
1292
  pluginResults,
1293
+ expectedWarnings,
994
1294
  registeredPlugins: typeof window.CodexPlus?.plugins?.list === "function" ? pluginIds() : null,
995
1295
  startedPlugins: started(),
996
1296
  };
@@ -1009,6 +1309,7 @@ async function runAudit(args, {
1009
1309
  const Session = operations.CdpSession || CdpSession;
1010
1310
  const waitRuntime = operations.waitForLiveRuntime || waitForLiveRuntime;
1011
1311
  const waitAppShell = operations.waitForAppShellMounted || waitForAppShellMounted;
1312
+ const verifyMermaidViewer = operations.verifyMermaidViewerRender || verifyMermaidViewerRender;
1012
1313
  const cleanupApp = operations.cleanupLaunchedAuditApp || cleanupLaunchedAuditApp;
1013
1314
  const checkStability = operations.checkKeepOpenAppStability || checkKeepOpenAppStability;
1014
1315
  const preflightAudit = operations.auditPreflight || auditPreflight;
@@ -1041,15 +1342,17 @@ async function runAudit(args, {
1041
1342
  }),
1042
1343
  );
1043
1344
  }
1044
- syncResult = await withAuditProgress(
1045
- progress,
1046
- "Syncing dev home",
1047
- "Synced dev home",
1048
- () => syncHome({
1049
- sourceHome: args.sourceHome,
1050
- devHome: args.devHome,
1051
- }),
1052
- );
1345
+ if (args.apply || args.launch) {
1346
+ syncResult = await withAuditProgress(
1347
+ progress,
1348
+ "Syncing dev home",
1349
+ "Synced dev home",
1350
+ () => syncHome({
1351
+ sourceHome: args.sourceHome,
1352
+ devHome: args.devHome,
1353
+ }),
1354
+ );
1355
+ }
1053
1356
  if (preflight.launch) {
1054
1357
  launchResult = await withAuditProgress(
1055
1358
  progress,
@@ -1060,6 +1363,7 @@ async function runAudit(args, {
1060
1363
  devHome: args.devHome,
1061
1364
  electronUserDataPath: args.electronUserDataPath,
1062
1365
  remoteDebuggingPort: port,
1366
+ devInstanceId: args.devInstanceId,
1063
1367
  }),
1064
1368
  );
1065
1369
  }
@@ -1090,9 +1394,36 @@ async function runAudit(args, {
1090
1394
  "Probed plugins",
1091
1395
  () => cdp.evaluate(pluginAuditExpression({ includeNativeOpenProbes: args.includeNativeOpenProbes })),
1092
1396
  );
1397
+ const shouldProbeMermaidViewer = live.pluginResults?.mermaidFullscreen?.ok;
1398
+ const mermaidViewerRender = shouldProbeMermaidViewer
1399
+ ? await withAuditProgress(
1400
+ progress,
1401
+ "Verifying Mermaid viewer render",
1402
+ "Mermaid viewer rendered",
1403
+ () => verifyMermaidViewer(cdp, port, { Session }),
1404
+ )
1405
+ : null;
1406
+ if (mermaidViewerRender != null) {
1407
+ live.pluginResults.mermaidFullscreen.viewerRenderProbe = mermaidViewerRender;
1408
+ if (!mermaidViewerRender.ok) {
1409
+ live.ok = false;
1410
+ live.pluginResults.mermaidFullscreen.ok = false;
1411
+ live.failures.push({
1412
+ plugin: "mermaidFullscreen",
1413
+ message: `Mermaid viewer render failed: ${mermaidViewerRender.message || "no SVG rendered"}`,
1414
+ });
1415
+ }
1416
+ }
1417
+ appShellStatus = await withAuditProgress(
1418
+ progress,
1419
+ "Verifying Codex app shell after probes",
1420
+ "App shell still healthy",
1421
+ () => waitAppShell(cdp),
1422
+ );
1093
1423
  result = {
1094
1424
  ok: live.ok,
1095
1425
  failures: live.failures,
1426
+ expectedWarnings: live.expectedWarnings || [],
1096
1427
  pluginResults: live.pluginResults,
1097
1428
  target: {
1098
1429
  app: path.resolve(args.target),
@@ -1115,6 +1446,8 @@ async function runAudit(args, {
1115
1446
  command: launchResult.command,
1116
1447
  args: launchResult.args,
1117
1448
  pid: launchResult.pid,
1449
+ devBundle: launchResult.devBundle,
1450
+ instanceIdentity: launchResult.instanceIdentity,
1118
1451
  },
1119
1452
  registeredPlugins: live.registeredPlugins,
1120
1453
  startedPlugins: live.startedPlugins,
@@ -1124,6 +1457,7 @@ async function runAudit(args, {
1124
1457
  nativeOpenProbes: {
1125
1458
  included: Boolean(args.includeNativeOpenProbes),
1126
1459
  },
1460
+ mermaidViewerRender,
1127
1461
  preflight,
1128
1462
  };
1129
1463
  return result;
@@ -1135,6 +1469,7 @@ async function runAudit(args, {
1135
1469
  message: error.message,
1136
1470
  details: error.details,
1137
1471
  }],
1472
+ expectedWarnings: [],
1138
1473
  pluginResults: {},
1139
1474
  target: {
1140
1475
  app: path.resolve(args.target),
@@ -1157,6 +1492,8 @@ async function runAudit(args, {
1157
1492
  command: launchResult.command,
1158
1493
  args: launchResult.args,
1159
1494
  pid: launchResult.pid,
1495
+ devBundle: launchResult.devBundle,
1496
+ instanceIdentity: launchResult.instanceIdentity,
1160
1497
  },
1161
1498
  registeredPlugins: null,
1162
1499
  startedPlugins: null,
@@ -1263,5 +1600,6 @@ module.exports = {
1263
1600
  shouldShowAuditProgress,
1264
1601
  waitForAppShellMounted,
1265
1602
  waitForLiveRuntime,
1603
+ verifyMermaidViewerRender,
1266
1604
  waitForRendererTarget,
1267
1605
  };
@@ -0,0 +1,44 @@
1
+ const { buildCodexPlusPatchSet } = require("./lib/common-patches");
2
+
3
+ module.exports = buildCodexPlusPatchSet({
4
+ id: "codex-26.623.42026-4514",
5
+ codexVersion: "26.623.42026",
6
+ bundleVersion: "4514",
7
+ asarSha256: "6f4ec4c023ad3c0680e31f0963988870dc6f07d76b64a64c8866e09d482ddda6",
8
+ files: {
9
+ main: ".vite/build/main-r5HnecX_.js",
10
+ electronCommandSource: ".vite/build/src-C3H9d_bd.js",
11
+ appMain: "webview/assets/app-initial~app-main~remote-conversation-page~projects-index-page-14pJ3ozX.js",
12
+ appShell: "webview/assets/app-initial~app-main~onboarding-page-BUwCKIcU.js",
13
+ errorBoundary: "webview/assets/app-initial~app-main~onboarding-page-BUwCKIcU.js",
14
+ generalSettings: "webview/assets/general-settings-DeOIy93M.js",
15
+ header: "webview/assets/header-DpUZYotp.js",
16
+ threadPageHeader: null,
17
+ localConversationPage: "webview/assets/local-conversation-page-C379OsPf.js",
18
+ threadContext: null,
19
+ sidebarProjectHoverCardSourceRows: "webview/assets/app-initial~app-main~remote-conversation-page~projects-index-page-14pJ3ozX.js",
20
+ threadSidePanelTabs: "webview/assets/app-initial~app-main~onboarding-page-BUwCKIcU.js",
21
+ userMessageAttachments: "webview/assets/app-initial~app-main~onboarding-page-BUwCKIcU.js",
22
+ composer: "webview/assets/app-initial~app-main~remote-conversation-page~new-thread-panel-page~appgen-library-page~hot~djo67r4n-CFm41aDU.js",
23
+ localActiveWorkspaceRootDropdown: "webview/assets/local-remote-dropdown-BZlMncy8.js",
24
+ homeProjectDropdown: "webview/assets/app-initial~app-main~projects-index-page~hotkey-window-new-thread-page~hotkey-window-home-p~hswrsggc-CI5sWBpw.js",
25
+ runCommand: "webview/assets/app-initial~app-main~automations-page-BfqUlSo6.js",
26
+ localTaskRow: "webview/assets/app-initial~app-main~remote-conversation-page~projects-index-page-14pJ3ozX.js",
27
+ mermaidDiagramShell: "webview/assets/app-initial~app-main~remote-conversation-page~pull-requests-page~onboarding-page~hotkey-win~fzw0jvy4-rg89odR_.js",
28
+ keyboardShortcutsSearchInput: "webview/assets/app-initial~app-main~automations-page-BfqUlSo6.js",
29
+ statsigStartup: "webview/assets/app-initial~app-main~automations-page-BfqUlSo6.js",
30
+ src: "webview/assets/src-BpCf56JJ.js",
31
+ sidebarThreadKeys: null,
32
+ sidebarThreadRowSignals: null,
33
+ branchPickerDropdownContent: "webview/assets/git-branch-switcher-Cb06tz5G.js",
34
+ electronMenuShortcuts: ".vite/build/src-C3H9d_bd.js",
35
+ },
36
+ anchors: {
37
+ composerProjectImports: null,
38
+ composerProjectStyleCaller: "Ls=(0,PY.jsx)(Lte,{active:Ra.ui?.active===!0&&Ra.ui.activation===`synthetic`,onOpen:()=>{ns.prepare(),fn.toggleContextSuggestions()}});return",
39
+ composerProjectAccentCaller: null,
40
+ },
41
+ runtimeConfig: {
42
+ mermaidCoreAsset: "mermaid.core-C6FbNonK.js",
43
+ },
44
+ });
@@ -1,3 +1,4 @@
1
+ const codex_26_623_42026_4514 = require("./26.623.42026-4514");
1
2
  const codex_26_623_41415_4505 = require("./26.623.41415-4505");
2
3
  const codex_26_616_81150_4306 = require("./26.616.81150-4306");
3
4
  const codex_26_616_71553_4265 = require("./26.616.71553-4265");
@@ -5,6 +6,7 @@ const codex_26_616_41845_4198 = require("./26.616.41845-4198");
5
6
  const codex_26_616_51431_4212 = require("./26.616.51431-4212");
6
7
 
7
8
  const patchSets = [
9
+ codex_26_623_42026_4514,
8
10
  codex_26_623_41415_4505,
9
11
  codex_26_616_81150_4306,
10
12
  codex_26_616_71553_4265,
@@ -57,6 +57,14 @@ function patchTitle(text) {
57
57
  }
58
58
 
59
59
  function patchDevModeStatsigFallback(text) {
60
+ if (text.includes("function XY(e){let t=(0,sX.c)(27),")) {
61
+ return replaceOnce(
62
+ text,
63
+ "function XY(e){let t=(0,sX.c)(27),{auth:n,appVersion:r,currentAccount:i,hostBuildFlavor:a,plan:o,statsigClientKey:s,systemName:c,systemVersion:l,children:u}=e,d=o===void 0?null:o,f=s===void 0?OY:s,p,m,h;if",
64
+ "function XY(e){let t=(0,sX.c)(27),{auth:n,appVersion:r,currentAccount:i,hostBuildFlavor:a,plan:o,statsigClientKey:s,systemName:c,systemVersion:l,children:u}=e,d=o===void 0?null:o,f=s===void 0?OY:s,p,m,h;if(window.__CodexPlusRuntimeConfig?.devModeStatsigFallback)return u;if",
65
+ "dev mode statsig fallback anchor",
66
+ );
67
+ }
60
68
  return replaceOnce(
61
69
  text,
62
70
  "function Ske(e){let t=(0,J1.c)(27),{auth:n,appVersion:r,currentAccount:i,hostBuildFlavor:a,plan:o,statsigClientKey:s,systemName:c,systemVersion:l,children:u}=e,d=o===void 0?null:o,f=s===void 0?F1:s,p,m,h;if",
@@ -230,6 +238,20 @@ function patchWorker(text) {
230
238
  }
231
239
 
232
240
  function patchThreadSidePanelTabs(text) {
241
+ if (text.includes("function mQe(e){let t=(0,hQe.c)(20),{diffMode:n,setTabState:r,tabState:i}=e")) {
242
+ let patched = replaceOnce(
243
+ text,
244
+ "function mQe(e){let t=(0,hQe.c)(20),{diffMode:n,setTabState:r,tabState:i}=e",
245
+ `${reviewHook("[tR,eR,B,X,Z,jw,Mw,Ow,null,fu,ze,JZe,za,Ia,null,null,null,null,null,null,null]")}function mQe(e){let t=(0,hQe.c)(20),{diffMode:n,setTabState:r,tabState:i}=e`,
246
+ "review host hook insertion anchor",
247
+ );
248
+ return replaceOnce(
249
+ patched,
250
+ "_=(0,tR.jsx)(JZe,{diffMode:n,diffRefs:u,isFileTreeOpen:s,isReviewExpanded:p,setTabState:r,setScrollContainerRef:h,tabState:i}),t[9]=n,t[10]=u,t[11]=s,t[12]=p,t[13]=h,t[14]=r,t[15]=i,t[16]=_):_=t[16];",
251
+ "_=(0,tR.jsx)(CPXRM,{mainReviewContent:(0,tR.jsx)(JZe,{diffMode:n,diffRefs:u,isFileTreeOpen:s,isReviewExpanded:p,setTabState:r,setScrollContainerRef:h,tabState:i}),diffMode:n,setTabState:r,tabState:i}),t[9]=n,t[10]=u,t[11]=s,t[12]=p,t[13]=h,t[14]=r,t[15]=i,t[16]=_):_=t[16];",
252
+ "review body mux anchor",
253
+ );
254
+ }
233
255
  if (text.includes("function oDn(e){let t=(0,sDn.c)(14),{expandedActionsPortalTarget:n,setTabState:r,tabState:i}=e")) {
234
256
  let patched = replaceOnce(
235
257
  text,
@@ -264,6 +286,26 @@ function patchThreadSidePanelTabs(text) {
264
286
  );
265
287
  }
266
288
  function patchAppShell(text) {
289
+ if (text.includes("function QUe(e){let t=(0,NP.c)(4),{onRetry:n}=e,")) {
290
+ let patched = replaceOnce(
291
+ text,
292
+ "function QUe(e){let t=(0,NP.c)(4),{onRetry:n}=e,",
293
+ `${diagnosticDetailsHook()}function QUe(e){let t=(0,NP.c)(4),{onRetry:n,error:CPX_error}=e,`,
294
+ "app shell error fallback prop anchor",
295
+ );
296
+ patched = replaceOnce(
297
+ patched,
298
+ "children:[r,(0,FP.jsx)(za,{color:`secondary`,size:`default`,onClick:n,children:i})]",
299
+ "children:[r,CPXDiagnosticDetails({jsx:FP.jsx,error:CPX_error}),(0,FP.jsx)(za,{color:`secondary`,size:`default`,onClick:n,children:i})]",
300
+ "app shell error detail insertion anchor",
301
+ );
302
+ return replaceOnce(
303
+ patched,
304
+ "fallback:e=>(0,FP.jsx)(QUe,{onRetry:()=>{e.resetError()}})",
305
+ "fallback:e=>(0,FP.jsx)(QUe,{error:e.error,onRetry:()=>{e.resetError()}})",
306
+ "app shell boundary error prop anchor",
307
+ );
308
+ }
267
309
  if (text.includes("function xdn(e){let t=(0,Cdn.c)(4),{onRetry:n}=e")) {
268
310
  let patched = replaceOnce(
269
311
  text,
@@ -300,6 +342,12 @@ function patchAppShell(text) {
300
342
  }
301
343
 
302
344
  function patchErrorBoundary(text) {
345
+ if (
346
+ !text.includes("function Xf(e){let t=(0,Vf.c)(9),{resetError:n}=e,r=ee(),i,a;") &&
347
+ text.includes("function QUe(e){let t=(0,NP.c)(4),{onRetry:n,error:CPX_error}=e,")
348
+ ) {
349
+ return text;
350
+ }
303
351
  if (
304
352
  !text.includes("function Xf(e){let t=(0,Vf.c)(9),{resetError:n}=e,r=ee(),i,a;") &&
305
353
  text.includes("function xdn(e){let t=(0,Cdn.c)(")
@@ -327,6 +375,29 @@ function patchErrorBoundary(text) {
327
375
  }
328
376
 
329
377
  function patchAppMainProjectColors(text) {
378
+ if (
379
+ text.includes("function Vm(e){let t=(0,Gm.c)(57),") &&
380
+ text.includes("return t[41]!==Y||t[42]!==H?(ne=(0,$.jsx)(`div`,{...H,children:Y})")
381
+ ) {
382
+ let patched = replaceOnce(
383
+ text,
384
+ "function Vm(e){let t=(0,Gm.c)(57),",
385
+ `${projectColorHook()}function Vm(e){let t=(0,Gm.c)(57),`,
386
+ "project color app main helper insertion anchor",
387
+ );
388
+ patched = replaceOnce(
389
+ patched,
390
+ "q=(0,Km.jsxs)(`div`,{...v,...O,ref:n,className:j,role:`button`,",
391
+ "q=(0,Km.jsxs)(`div`,{...v,...O,...CPXPR({projectId:_,label:p}),ref:n,className:j,role:`button`,",
392
+ "project header row color attributes anchor",
393
+ );
394
+ return replaceOnce(
395
+ patched,
396
+ "ne=(0,$.jsx)(`div`,{...H,children:Y})",
397
+ "ne=(0,$.jsx)(`div`,{...H,...CPXPR(a),children:Y})",
398
+ "project group color render anchor",
399
+ );
400
+ }
330
401
  if (text.includes("function gg(e){let t=(0,Rg.c)(44),{threadKeys:n,")) {
331
402
  let patched = replaceOnce(
332
403
  text,
@@ -375,6 +446,14 @@ function patchAppMainProjectColors(text) {
375
446
  }
376
447
 
377
448
  function patchAppMainSidebarBlur(text) {
449
+ if (text.includes("function vh(e){let t=(0,qh.c)(15),")) {
450
+ return replaceOnce(
451
+ text,
452
+ "c=(0,$.jsx)(`span`,{className:`min-w-0 truncate pr-1`,children:n})",
453
+ "c=(0,$.jsx)(`span`,{\"data-codex-plus-sidebar-name\":``,className:`min-w-0 truncate pr-1`,children:n})",
454
+ "project header sidebar blur label anchor",
455
+ );
456
+ }
378
457
  if (!text.includes("openFolder:$y,toggleSidebar:$i,toggleTerminal:Md,")) {
379
458
  return replaceOnce(
380
459
  text,
@@ -405,6 +484,29 @@ function patchAppMainSidebarBlur(text) {
405
484
  }
406
485
 
407
486
  function patchHeader(text) {
487
+ if (
488
+ text.includes("function Jn(e){let t=(0,$n.c)(66),") &&
489
+ text.includes("(0,$.jsx)(L,{color:`ghostActive`,type:`button`,onClick:u,")
490
+ ) {
491
+ let patched = replaceOnce(
492
+ text,
493
+ "function Jn(e){let t=(0,$n.c)(66),",
494
+ `${threadHeaderHook()}function Jn(e){let t=(0,$n.c)(66),`,
495
+ "thread header accessory helper insertion anchor",
496
+ );
497
+ patched = replaceOnce(
498
+ patched,
499
+ "let x;t[35]!==c||t[36]!==g||t[37]!==i?",
500
+ "let CPX_headerContext={cwd:null,hostId:null,header:{surface:`header`,titleText:typeof i==`string`?i:null}},CPX_headerAccessories=CPXThreadHeaderAccessories({context:CPX_headerContext,deps:{jsx:$.jsx,jsxs:$.jsxs,Tooltip:re}});let x;t[35]!==c||t[36]!==g||t[37]!==i?",
501
+ "thread header accessory context anchor",
502
+ );
503
+ return replaceOnce(
504
+ patched,
505
+ "children:(0,$.jsx)(`span`,{className:`truncate`,children:i})})]}):",
506
+ "children:(0,$.jsx)(`span`,{className:`truncate`,children:i})}),CPX_headerAccessories]}):",
507
+ "thread header accessory render anchor",
508
+ );
509
+ }
408
510
  if (text.includes("function Jn(e){let t=(0,$n.c)(66),")) {
409
511
  let patched = replaceOnce(
410
512
  text,
@@ -476,6 +578,21 @@ function patchThreadPageHeader(text) {
476
578
  }
477
579
 
478
580
  function patchLocalConversationPageHeader(text) {
581
+ if (text.includes("function pi(e){let t=(0,W.c)(32),")) {
582
+ let patched = replaceOnce(
583
+ text,
584
+ "function pi(e){let t=(0,W.c)(32),",
585
+ `${threadHeaderHook()}function pi(e){let t=(0,W.c)(32),`,
586
+ "local conversation header helper insertion anchor",
587
+ );
588
+ patched = replaceOnce(
589
+ patched,
590
+ "let k;t[26]===Symbol.for(`react.memo_cache_sentinel`)?(k=null,t[26]=k):k=t[26];",
591
+ "let CPX_headerContext={cwd:p,hostId:null,header:{surface:`local-conversation`,titleText:typeof c==`string`?c:null,projectName:s??null}},k=CPXThreadHeaderAccessories({context:CPX_headerContext,deps:{jsx:G.jsx,jsxs:G.jsxs,Tooltip:ht}});",
592
+ "local conversation header accessory render anchor",
593
+ );
594
+ return patched;
595
+ }
479
596
  if (text.includes("function mi(e){let t=(0,U.c)(32),")) {
480
597
  let patched = replaceOnce(
481
598
  text,
@@ -524,7 +641,10 @@ function patchLocalConversationPageHeader(text) {
524
641
  }
525
642
 
526
643
  function patchGeneralSettingsUserBubbleColors(text) {
527
- if (text.includes("function Lr({showCodeFont:e,showTranslucentSidebarToggle:t,variant:n}){")) {
644
+ if (
645
+ text.includes("function Lr({showCodeFont:e,showTranslucentSidebarToggle:t,variant:n}){") &&
646
+ text.includes("children:[T.map(e=>(0,J.jsx)(L,{control:(0,J.jsx)(Hr,{ariaLabel:e.ariaLabel,value:y[e.role],onChange:t=>{k(e.role,t)}}),label:e.label,variant:`nested`},e.role)),E.map")
647
+ ) {
528
648
  let patched = replaceOnce(
529
649
  text,
530
650
  "function Lr({showCodeFont:e,showTranslucentSidebarToggle:t,variant:n}){",
@@ -538,6 +658,20 @@ function patchGeneralSettingsUserBubbleColors(text) {
538
658
  "user bubble settings row anchor",
539
659
  );
540
660
  }
661
+ if (text.includes("function Lr({showCodeFont:e,showTranslucentSidebarToggle:t,variant:n}){")) {
662
+ let patched = replaceOnce(
663
+ text,
664
+ "function Lr({showCodeFont:e,showTranslucentSidebarToggle:t,variant:n}){",
665
+ `${appearanceSettingsHook("{React:ti,jsx:J.jsx,SettingRow:L,ColorInput:Hr,Switch:qt}")}function Lr({showCodeFont:e,showTranslucentSidebarToggle:t,variant:n}){`,
666
+ "user bubble settings helper insertion anchor",
667
+ );
668
+ return replaceOnce(
669
+ patched,
670
+ "children:[E.map(e=>(0,J.jsx)(L,{control:(0,J.jsx)(Hr,{ariaLabel:e.ariaLabel,value:b[e.role],onChange:t=>{O(e.role,t)}}),label:e.label,variant:`nested`},e.role)),D.map",
671
+ "children:[E.map(e=>(0,J.jsx)(L,{control:(0,J.jsx)(Hr,{ariaLabel:e.ariaLabel,value:b[e.role],onChange:t=>{O(e.role,t)}}),label:e.label,variant:`nested`},e.role)),...CPXAppearanceRows(n),D.map",
672
+ "user bubble settings row anchor",
673
+ );
674
+ }
541
675
  let patched = replaceOnce(
542
676
  text,
543
677
  "function tn({showCodeFont:e,showTranslucentSidebarToggle:t,variant:n}){",
@@ -553,6 +687,26 @@ function patchGeneralSettingsUserBubbleColors(text) {
553
687
  }
554
688
 
555
689
  function patchUserMessageAttachmentsBubbleColors(text) {
690
+ if (text.includes("function xst({cwd:e,hostId:t,initialMessage:n,onCancel:r,onDraftChange:i,onSubmit:a}){")) {
691
+ let patched = replaceOnce(
692
+ text,
693
+ "function xst({cwd:e,hostId:t,initialMessage:n,onCancel:r,onDraftChange:i,onSubmit:a}){",
694
+ `${messageComposerHook()}function xst({cwd:e,hostId:t,initialMessage:n,onCancel:r,onDraftChange:i,onSubmit:a}){`,
695
+ "user bubble helper insertion anchor",
696
+ );
697
+ patched = replaceOnce(
698
+ patched,
699
+ "return(0,HK.jsx)(`form`,{className:`relative flex w-full flex-col rounded-3xl bg-token-foreground/5`,onSubmit:e=>{e.preventDefault(),v()},children:",
700
+ "return(0,HK.jsx)(`form`,{\"data-codex-plus-user-entry\":!0,className:`relative flex w-full flex-col rounded-3xl bg-token-foreground/5`,onSubmit:e=>{e.preventDefault(),v()},children:",
701
+ "edit user message entry marker anchor",
702
+ );
703
+ return replaceOnce(
704
+ patched,
705
+ "fe=V?(0,KK.jsx)(`div`,{className:`w-full p-px`,children:(0,KK.jsx)(xst,{cwd:x??null,hostId:S,initialMessage:z.trim(),onCancel:()=>{ne(null)},onDraftChange:e=>{ne(e)},onSubmit:ie})}):q?(0,KK.jsx)(`div`,{\"data-user-message-bubble\":!0,role:I?`button`:void 0,",
706
+ "fe=V?(0,KK.jsx)(`div`,{className:`w-full p-px`,children:(0,KK.jsx)(xst,{cwd:x??null,hostId:S,initialMessage:z.trim(),onCancel:()=>{ne(null)},onDraftChange:e=>{ne(e)},onSubmit:ie})}):q?(0,KK.jsx)(`div`,{\"data-user-message-bubble\":!0,...CPXBubbleProps({}),role:I?`button`:void 0,",
707
+ "user bubble marker attribute anchor",
708
+ );
709
+ }
556
710
  if (text.includes("function qVn({cwd:e,hostId:t,initialMessage:n,onCancel:r,onDraftChange:i,onSubmit:a}){")) {
557
711
  let patched = replaceOnce(
558
712
  text,
@@ -623,6 +777,43 @@ function patchUserMessageAttachmentsProjectColors(text) {
623
777
  }
624
778
 
625
779
  function patchComposerBubbleColors(text) {
780
+ if (text.includes("function FN(e){let t=(0,YN.c)(13),")) {
781
+ let patched = replaceOnce(
782
+ text,
783
+ "function FN(e){let t=(0,YN.c)(13),",
784
+ `${messageComposerHook()}function FN(e){let t=(0,YN.c)(13),`,
785
+ "composer user bubble helper insertion anchor",
786
+ );
787
+ patched = replaceOnce(
788
+ patched,
789
+ "function FN(e){let t=(0,YN.c)(13),{children:n,className:r,externalFooterVariant:i,inert:a,isDragActive:o,layout:s,onDragEnter:c,onDragLeave:l,onDragOver:u,onDrop:d}=e,",
790
+ "function FN(e){let t=(0,YN.c)(13),{children:n,className:r,externalFooterVariant:i,inert:a,isDragActive:o,layout:s,onDragEnter:c,onDragLeave:l,onDragOver:u,onDrop:d,...CPX_surfaceProps}=e,CPX_resolvedSurfaceProps=Object.keys(CPX_surfaceProps).length===0?CPXSurfaceProps({}):CPX_surfaceProps,",
791
+ "composer host surface props anchor",
792
+ );
793
+ return replaceOnce(
794
+ patched,
795
+ "return t[5]!==n||t[6]!==a||t[7]!==c||t[8]!==l||t[9]!==u||t[10]!==d||t[11]!==v?(y=(0,XN.jsx)(Fm.div,{inert:a,className:v,onDragEnter:c,onDragOver:u,onDragLeave:l,onDrop:d,children:n}),t[5]=n,t[6]=a,t[7]=c,t[8]=l,t[9]=u,t[10]=d,t[11]=v,t[12]=y):y=t[12],y}",
796
+ "return t[5]!==n||t[6]!==a||t[7]!==c||t[8]!==l||t[9]!==u||t[10]!==d||t[11]!==v?(y=(0,XN.jsx)(Fm.div,{inert:a,...CPX_resolvedSurfaceProps,className:v,onDragEnter:c,onDragOver:u,onDragLeave:l,onDrop:d,children:n}),t[5]=n,t[6]=a,t[7]=c,t[8]=l,t[9]=u,t[10]=d,t[11]=v,t[12]=y):y=t[12],y}",
797
+ "composer user entry marker render anchor",
798
+ );
799
+ }
800
+ if (
801
+ text.includes("function Ss(e){if(H?.type!==`local`") &&
802
+ text.includes("(0,iW.jsx)(eW,{className:A,externalFooterVariant:k,hasDropTargetPortal:fc,")
803
+ ) {
804
+ let patched = replaceOnce(
805
+ text,
806
+ "function Ss(e){if(H?.type!==`local`",
807
+ `${messageComposerHook()}function Ss(e){if(H?.type!==\`local\``,
808
+ "composer user bubble helper insertion anchor",
809
+ );
810
+ return replaceOnce(
811
+ patched,
812
+ "(0,iW.jsx)(eW,{className:A,externalFooterVariant:k,hasDropTargetPortal:fc,",
813
+ "(0,iW.jsx)(eW,{...CPXSurfaceProps({}),className:A,externalFooterVariant:k,hasDropTargetPortal:fc,",
814
+ "composer user entry marker render anchor",
815
+ );
816
+ }
626
817
  if (text.includes("function Wbe(e){let t=(0,gW.c)(13),")) {
627
818
  let patched = replaceOnce(
628
819
  text,
@@ -665,6 +856,14 @@ function patchComposerBubbleColors(text) {
665
856
  }
666
857
 
667
858
  function patchComposerProjectColors(text) {
859
+ if (text.includes("(0,iW.jsx)(eW,{className:A,externalFooterVariant:k,hasDropTargetPortal:fc,")) {
860
+ return replaceOnce(
861
+ text,
862
+ "(0,iW.jsx)(eW,{className:A,externalFooterVariant:k,hasDropTargetPortal:fc,",
863
+ "(0,iW.jsx)(eW,{...CPXSurfaceProps({project:{cwd:fn,hostId:sr}}),className:A,externalFooterVariant:k,hasDropTargetPortal:fc,",
864
+ "composer project accent style caller anchor",
865
+ );
866
+ }
668
867
  if (text.includes("function Wbe(e){let t=(0,gW.c)(13),") && text.includes("CPX_resolvedSurfaceProps=CPX_surfaceProps??CPXSurfaceProps({})")) {
669
868
  let patched = text;
670
869
  patched = replaceOnce(
@@ -710,6 +909,14 @@ function patchElectronMenuShortcuts(text) {
710
909
  }
711
910
 
712
911
  function patchKeyboardShortcutsSearchInput(text) {
912
+ if (text.includes("function qX(e,t){return`titleIntlId`in e?")) {
913
+ return replaceOnce(
914
+ text,
915
+ "function qX(e,t){return`titleIntlId`in e?YX(XX,e.titleIntlId)?t.formatMessage(XX[e.titleIntlId]):``:t.formatMessage(ZX[e.electron.menuTitleIntlId])}",
916
+ "function qX(e,t){return`titleIntlId`in e?YX(XX,e.titleIntlId)?t.formatMessage(XX[e.titleIntlId]):``:e.title??e.electron?.menuTitle??t.formatMessage(ZX[e.electron.menuTitleIntlId])}",
917
+ "generic command metadata title fallback anchor",
918
+ );
919
+ }
713
920
  if (text.includes("function Kke(e,t){return`titleIntlId`in e?")) {
714
921
  return replaceOnce(
715
922
  text,
@@ -727,6 +934,14 @@ function patchKeyboardShortcutsSearchInput(text) {
727
934
  }
728
935
 
729
936
  function patchCommandMenuRuntimeCommands(text) {
937
+ if (text.includes("let m=ne?N.filter(VZ):N,_;")) {
938
+ return replaceOnce(
939
+ text,
940
+ "let m=ne?N.filter(VZ):N,_;",
941
+ "let m=[...(ne?N.filter(VZ):N),...(globalThis.CodexPlus?.ui?.commands?.commandMetadata?.()?.filter?.(e=>!N.some(t=>t.id===e.id))??[])],_;",
942
+ "command menu runtime command metadata anchor",
943
+ );
944
+ }
730
945
  return replaceOnce(
731
946
  text,
732
947
  "let M=j,N;t[11]===o?N=t[12]:",
@@ -736,6 +951,20 @@ function patchCommandMenuRuntimeCommands(text) {
736
951
  }
737
952
 
738
953
  function patchLocalTaskRow(text) {
954
+ if (text.includes("function Ef(e){let t=(0,Of.c)(134),")) {
955
+ let patched = replaceOnce(
956
+ text,
957
+ "function Ef(e){let t=(0,Of.c)(134),",
958
+ `${projectColorHook()}function Ef(e){let t=(0,Of.c)(134),`,
959
+ "local task row project color helper insertion anchor",
960
+ );
961
+ return replaceOnce(
962
+ patched,
963
+ "threadSummary:le,dataAttributes:ue}=e,de=l===void 0?!1:l,",
964
+ "threadSummary:le,dataAttributes:ue=CPXPR({projectId:oe,label:se,path:r,cwd:r})}=e,de=l===void 0?!1:l,",
965
+ "local task row project assignment anchor",
966
+ );
967
+ }
739
968
  if (text.includes("function _p(e){let t=(0,yp.c)(134),")) {
740
969
  let patched = replaceOnce(
741
970
  text,
@@ -767,6 +996,20 @@ function patchLocalTaskRow(text) {
767
996
  }
768
997
 
769
998
  function patchMermaidDiagramShell(text) {
999
+ if (text.includes("function xbe(e){let t=(0,E2.c)(19),")) {
1000
+ let patched = replaceOnce(
1001
+ text,
1002
+ "function xbe(e){let t=(0,E2.c)(19),",
1003
+ `${mermaidDiagramHook()}function xbe(e){let t=(0,E2.c)(19),`,
1004
+ "mermaid diagram shell helper insertion anchor",
1005
+ );
1006
+ return replaceOnce(
1007
+ patched,
1008
+ "E=(0,O2.jsx)(`div`,{ref:d,className:C,\"data-wide-markdown-block\":w,\"data-wide-markdown-block-kind\":c,children:T})",
1009
+ "E=(0,O2.jsx)(`div`,{ref:d,...CPXMermaidDiagramProps({code:a}),className:C,\"data-wide-markdown-block\":w,\"data-wide-markdown-block-kind\":c,children:T})",
1010
+ "mermaid diagram shell host props anchor",
1011
+ );
1012
+ }
770
1013
  if (text.includes("function or({blockRef:e,code:t,isCodeFenceOpen:n,isDark:r,isVisible:i,onError:a,onRendered:o,renderKey:s}){")) {
771
1014
  let patched = replaceOnce(
772
1015
  text,
@@ -5,8 +5,8 @@ function patchLocalActiveWorkspaceRootDropdownProjectSelectorShortcut(text) {
5
5
  if (text.includes("function Ti(e){let t=(0,Oi.c)(109),")) {
6
6
  return replaceOnce(
7
7
  text,
8
- "H=(0,X.jsx)(`button`,{type:`button`,className:`flex min-w-0 items-center gap-1.5 rounded-lg bg-token-foreground/5 px-2 py-0.5 text-base leading-6 font-medium tracking-[-0.13px] text-token-foreground`,disabled:M,children:de})",
9
- "H=(0,X.jsx)(`button`,{type:`button`,\"data-codex-plus-project-selector-trigger\":!0,\"data-codex-plus-project-selector-variant\":`default`,className:`flex min-w-0 items-center gap-1.5 rounded-lg bg-token-foreground/5 px-2 py-0.5 text-base leading-6 font-medium tracking-[-0.13px] text-token-foreground`,disabled:M,children:de})",
8
+ "de=(0,X.jsx)(`button`,{type:`button`,className:`flex min-w-0 items-center gap-1.5 rounded-lg bg-token-foreground/5 px-2 py-0.5 text-base leading-6 font-medium tracking-[-0.13px] text-token-foreground`,disabled:re,children:ue})",
9
+ "de=(0,X.jsx)(`button`,{type:`button`,\"data-codex-plus-project-selector-trigger\":!0,\"data-codex-plus-project-selector-variant\":`default`,className:`flex min-w-0 items-center gap-1.5 rounded-lg bg-token-foreground/5 px-2 py-0.5 text-base leading-6 font-medium tracking-[-0.13px] text-token-foreground`,disabled:re,children:ue})",
10
10
  "project selector shortcut final dropdown trigger anchor",
11
11
  );
12
12
  }
@@ -49,6 +49,62 @@ function patchLocalActiveWorkspaceRootDropdownProjectSelectorShortcut(text) {
49
49
  }
50
50
 
51
51
  function patchHomeProjectDropdownProjectSelectorShortcut(text) {
52
+ if (text.includes("function zn(e){let t=(0,Bn.c)(44),") && text.includes("function ar({activeProjectIdOverride:e,")) {
53
+ let patched = replaceOnce(
54
+ text,
55
+ "function zn(e){let t=(0,Bn.c)(44),",
56
+ `${projectSelectorSearchHook()}${projectSelectorTriggerHook("$")}function zn(e){let t=(0,Bn.c)(44),`,
57
+ "home project selector shortcut helper insertion anchor",
58
+ );
59
+ patched = replaceOnce(
60
+ patched,
61
+ "let e=_.trim().toLowerCase();b=r.filter(t=>{if(!e)return!0;let n=t.repositoryData?.rootFolder??``;return[t.label,n,t.path??``,t.hostDisplayName??``].some(t=>t.toLowerCase().includes(e))});",
62
+ "b=CPXP.fuzzyFilter(r,_);",
63
+ "home project selector fuzzy search filter anchor",
64
+ );
65
+ patched = replaceOnce(
66
+ patched,
67
+ "w=(0,Z.jsx)(_t,{value:_,onChange:s,placeholder:c,className:`mb-1`})",
68
+ "w=(0,Z.jsx)(_t,{value:_,onChange:s,onKeyDown:e=>CPXP.acceptFirst(e,b,o,_),placeholder:c,className:`mb-1`})",
69
+ "home project selector accept first match keydown anchor",
70
+ );
71
+ patched = replaceOnce(
72
+ patched,
73
+ "(0,Z.jsx)(`span`,{className:`truncate`,children:e.label})",
74
+ "(0,Z.jsx)(`span`,{className:`truncate`,children:CPXP.fuzzyHighlight(e.label,_,Z.jsx)})",
75
+ "home project selector fuzzy search highlight anchor",
76
+ );
77
+ patched = replaceOnce(
78
+ patched,
79
+ "children:(0,$.jsxs)(me,{size:`composerSm`,color:`ghost`,className:`min-w-0`,children:",
80
+ "children:(0,$.jsxs)(me,{\"data-codex-plus-project-selector-trigger\":!0,\"data-codex-plus-project-selector-variant\":u,size:`composerSm`,color:`ghost`,className:`min-w-0`,children:",
81
+ "home project selector default button marker anchor",
82
+ );
83
+ patched = replaceOnce(
84
+ patched,
85
+ "children:(0,$.jsx)($n,{categoryLabel:(0,$.jsx)(R,{id:`composer.localCwdDropdown.footerCategory`",
86
+ "children:(0,$.jsx)($n,{\"data-codex-plus-project-selector-trigger\":!0,\"data-codex-plus-project-selector-variant\":u,categoryLabel:(0,$.jsx)(R,{id:`composer.localCwdDropdown.footerCategory`",
87
+ "home project selector footer button marker anchor",
88
+ );
89
+ patched = replaceOnce(
90
+ patched,
91
+ "ze=()=>(0,$.jsxs)(`button`,{className:V(`heading-xl text-token-text-tertiary",
92
+ "ze=()=>(0,$.jsxs)(`button`,{\"data-codex-plus-project-selector-trigger\":!0,\"data-codex-plus-project-selector-variant\":u,className:V(`heading-xl text-token-text-tertiary",
93
+ "home project selector hero button marker anchor",
94
+ );
95
+ patched = replaceOnce(
96
+ patched,
97
+ "triggerButton:p??G(),contentWidth:`menu`",
98
+ "triggerButton:CPXPST(p??G(),u),contentWidth:`menu`",
99
+ "home project selector empty trigger anchor",
100
+ );
101
+ return replaceOnce(
102
+ patched,
103
+ "triggerButton:p??(u===`hero`?ze():u===`home`?G():Ie()),contentWidth:`workspace`",
104
+ "triggerButton:CPXPST(p??(u===`hero`?ze():u===`home`?G():Ie()),u),contentWidth:`workspace`",
105
+ "home project selector workspace trigger anchor",
106
+ );
107
+ }
52
108
  let patched = replaceOnce(
53
109
  text,
54
110
  "function St({activeProjectIdOverride:e,allowLocalProjects:t=!0,allowLocalProjectActions:n=t,allowRemoteProjects:r=!0,disabled:a=!1,hideLabel:o=!1,onWorkspaceRootSelected:s,variant:c=`default`,isOpen:l,onOpenChange:m,triggerButton:_}){",
@@ -107,6 +163,14 @@ function patchHomeProjectDropdownProjectSelectorShortcut(text) {
107
163
 
108
164
  function patchRunCommandProjectSelectorShortcut(text) {
109
165
  const runtimeCommandEntries = "...(window.CodexPlus?.commands?.all?.()??[]).map(e=>[e.id,()=>window.CodexPlus?.commands?.run?.(e.id)])";
166
+ if (text.includes("Jy(`toggleSidebar`,r);")) {
167
+ return replaceOnce(
168
+ text,
169
+ "Jy(`toggleSidebar`,r);",
170
+ "Jy(`toggleSidebar`,r);for(let e of window.CodexPlus?.commands?.all?.()??[])Jy(e.id,()=>window.CodexPlus?.commands?.run?.(e.id));",
171
+ "codex plus runtime command dispatch anchor",
172
+ );
173
+ }
110
174
  if (text.includes("],[`openFolder`,GTt],[`toggleSidebar`,")) {
111
175
  return replaceOnce(
112
176
  text,
@@ -40,7 +40,11 @@
40
40
  }
41
41
 
42
42
  function trigger(element, variant, React) {
43
- return React.isValidElement(element)
43
+ return typeof React?.cloneElement === "function" &&
44
+ element != null &&
45
+ typeof element === "object" &&
46
+ "props" in element &&
47
+ "type" in element
44
48
  ? React.cloneElement(element, {
45
49
  ...element.props,
46
50
  "data-codex-plus-project-selector-trigger": true,
@@ -201,8 +201,10 @@
201
201
  required: true,
202
202
  styles:
203
203
  ":root:not(.dark):not(.electron-dark) :is([data-app-action-sidebar-project-row],[data-app-action-sidebar-thread-row][data-codex-plus-project-sidebar-color],[data-app-action-sidebar-project-list-id][data-codex-plus-project-sidebar-color] [data-app-action-sidebar-thread-row]){border-radius:0;background-color:var(--codex-plus-project-soft-light);border-left-color:var(--codex-plus-project-accent)}" +
204
+ ":root:not(.dark):not(.electron-dark) [data-app-action-sidebar-project-list-id][data-codex-plus-project-sidebar-color]{background-color:var(--codex-plus-project-soft-light);border-left-color:var(--codex-plus-project-accent)}" +
204
205
  ":root:not(.dark):not(.electron-dark) :is([data-app-action-sidebar-thread-row][data-codex-plus-project-sidebar-color],[data-app-action-sidebar-project-list-id][data-codex-plus-project-sidebar-color] [data-app-action-sidebar-thread-row])[data-app-action-sidebar-thread-active=\"true\"]{background-color:var(--codex-plus-project-bg-light);box-shadow:inset 5px 0 0 var(--codex-plus-project-accent)}" +
205
206
  ":root.dark :is([data-app-action-sidebar-project-row],[data-app-action-sidebar-thread-row][data-codex-plus-project-sidebar-color],[data-app-action-sidebar-project-list-id][data-codex-plus-project-sidebar-color] [data-app-action-sidebar-thread-row]),:root.electron-dark :is([data-app-action-sidebar-project-row],[data-app-action-sidebar-thread-row][data-codex-plus-project-sidebar-color],[data-app-action-sidebar-project-list-id][data-codex-plus-project-sidebar-color] [data-app-action-sidebar-thread-row]){border-radius:0;background-color:var(--codex-plus-project-bg-dark);border-left-color:var(--codex-plus-project-border-dark)}" +
207
+ ":root.dark [data-app-action-sidebar-project-list-id][data-codex-plus-project-sidebar-color],:root.electron-dark [data-app-action-sidebar-project-list-id][data-codex-plus-project-sidebar-color]{background-color:var(--codex-plus-project-bg-dark);border-left-color:var(--codex-plus-project-border-dark)}" +
206
208
  ":root.dark :is([data-app-action-sidebar-thread-row][data-codex-plus-project-sidebar-color],[data-app-action-sidebar-project-list-id][data-codex-plus-project-sidebar-color] [data-app-action-sidebar-thread-row])[data-app-action-sidebar-thread-active=\"true\"],:root.electron-dark :is([data-app-action-sidebar-thread-row][data-codex-plus-project-sidebar-color],[data-app-action-sidebar-project-list-id][data-codex-plus-project-sidebar-color] [data-app-action-sidebar-thread-row])[data-app-action-sidebar-thread-active=\"true\"]{background-color:color-mix(in srgb,var(--codex-plus-project-accent) 38%,transparent);border-left-color:color-mix(in srgb,var(--codex-plus-project-accent) 88%,transparent);box-shadow:inset 5px 0 0 var(--codex-plus-project-accent)}" +
207
209
  ":root:not(.dark):not(.electron-dark) [data-codex-plus-project-color]{border-left-color:var(--codex-plus-project-accent)}" +
208
210
  ":root.dark [data-codex-plus-project-color],:root.electron-dark [data-codex-plus-project-color]{border-left-color:var(--codex-plus-project-border-dark)}" +
@@ -95,9 +95,13 @@
95
95
  styles:
96
96
  ':root:not(.dark):not(.electron-dark) :is([data-codex-plus-user-bubble],[data-codex-plus-user-entry]){background-color:var(--codex-plus-user-bubble-light-bg);color:var(--codex-plus-user-bubble-light-fg)}' +
97
97
  ':root:not(.dark):not(.electron-dark) [data-codex-plus-user-entry] :is(.ProseMirror,.ProseMirror *,textarea,[contenteditable="true"],[data-placeholder]),:root:not(.dark):not(.electron-dark) [data-codex-plus-user-entry] :is(button:not([class*="bg-token-foreground"]),[role="button"]:not([class*="bg-token-foreground"]),button:not([class*="bg-token-foreground"]) svg,[role="button"]:not([class*="bg-token-foreground"]) svg,[class*="text-token-foreground"],[class*="text-token-description-foreground"],[class*="text-token-input-placeholder-foreground"],[class*="text-token-text-link-foreground"],[class*="text-token-editor-warning-foreground"]){color:var(--codex-plus-user-bubble-light-fg)}' +
98
+ ':root:not(.dark):not(.electron-dark) [data-codex-plus-user-entry] :is(button[aria-disabled="true"],button[class*="opacity-25"],[role="button"][aria-disabled="true"],[role="button"][class*="opacity-25"]){opacity:1!important;color:var(--codex-plus-user-bubble-light-fg)!important;-webkit-text-fill-color:currentColor!important}' +
99
+ ':root:not(.dark):not(.electron-dark) [data-codex-plus-user-entry] :is(button[aria-disabled="true"],button[class*="opacity-25"],[role="button"][aria-disabled="true"],[role="button"][class*="opacity-25"]) *{animation:none!important;background-image:none!important;color:inherit!important;stroke:currentColor!important;-webkit-text-fill-color:currentColor!important}' +
98
100
  ':root:not(.dark):not(.electron-dark) [data-codex-plus-user-entry] :is([data-placeholder],[class*="text-token-input-placeholder-foreground"])::before,:root:not(.dark):not(.electron-dark) [data-codex-plus-user-entry] :is([data-placeholder],[class*="text-token-input-placeholder-foreground"])::after,:root:not(.dark):not(.electron-dark) [data-codex-plus-user-entry] :is(input,textarea,[contenteditable="true"],[class*="placeholder:text-token-input-placeholder-foreground"])::placeholder{color:var(--codex-plus-user-bubble-light-fg)}' +
99
101
  ':root.dark :is([data-codex-plus-user-bubble],[data-codex-plus-user-entry]),:root.electron-dark :is([data-codex-plus-user-bubble],[data-codex-plus-user-entry]){background-color:var(--codex-plus-user-bubble-dark-bg);color:var(--codex-plus-user-bubble-dark-fg)}' +
100
102
  ':root.dark [data-codex-plus-user-entry] :is(.ProseMirror,.ProseMirror *,textarea,[contenteditable="true"],[data-placeholder]),:root.electron-dark [data-codex-plus-user-entry] :is(.ProseMirror,.ProseMirror *,textarea,[contenteditable="true"],[data-placeholder]),:root.dark [data-codex-plus-user-entry] :is(button:not([class*="bg-token-foreground"]),[role="button"]:not([class*="bg-token-foreground"]),button:not([class*="bg-token-foreground"]) svg,[role="button"]:not([class*="bg-token-foreground"]) svg,[class*="text-token-foreground"],[class*="text-token-description-foreground"],[class*="text-token-input-placeholder-foreground"],[class*="text-token-text-link-foreground"],[class*="text-token-editor-warning-foreground"]),:root.electron-dark [data-codex-plus-user-entry] :is(button:not([class*="bg-token-foreground"]),[role="button"]:not([class*="bg-token-foreground"]),button:not([class*="bg-token-foreground"]) svg,[role="button"]:not([class*="bg-token-foreground"]) svg,[class*="text-token-foreground"],[class*="text-token-description-foreground"],[class*="text-token-input-placeholder-foreground"],[class*="text-token-text-link-foreground"],[class*="text-token-editor-warning-foreground"]){color:var(--codex-plus-user-bubble-dark-fg)}' +
103
+ ':root.dark [data-codex-plus-user-entry] :is(button[aria-disabled="true"],button[class*="opacity-25"],[role="button"][aria-disabled="true"],[role="button"][class*="opacity-25"]),:root.electron-dark [data-codex-plus-user-entry] :is(button[aria-disabled="true"],button[class*="opacity-25"],[role="button"][aria-disabled="true"],[role="button"][class*="opacity-25"]){opacity:1!important;color:var(--codex-plus-user-bubble-dark-fg)!important;-webkit-text-fill-color:currentColor!important}' +
104
+ ':root.dark [data-codex-plus-user-entry] :is(button[aria-disabled="true"],button[class*="opacity-25"],[role="button"][aria-disabled="true"],[role="button"][class*="opacity-25"]) *,:root.electron-dark [data-codex-plus-user-entry] :is(button[aria-disabled="true"],button[class*="opacity-25"],[role="button"][aria-disabled="true"],[role="button"][class*="opacity-25"]) *{animation:none!important;background-image:none!important;color:inherit!important;stroke:currentColor!important;-webkit-text-fill-color:currentColor!important}' +
101
105
  ':root.dark [data-codex-plus-user-entry] :is([data-placeholder],[class*="text-token-input-placeholder-foreground"])::before,:root.dark [data-codex-plus-user-entry] :is([data-placeholder],[class*="text-token-input-placeholder-foreground"])::after,:root.dark [data-codex-plus-user-entry] :is(input,textarea,[contenteditable="true"],[class*="placeholder:text-token-input-placeholder-foreground"])::placeholder,:root.electron-dark [data-codex-plus-user-entry] :is([data-placeholder],[class*="text-token-input-placeholder-foreground"])::before,:root.electron-dark [data-codex-plus-user-entry] :is([data-placeholder],[class*="text-token-input-placeholder-foreground"])::after,:root.electron-dark [data-codex-plus-user-entry] :is(input,textarea,[contenteditable="true"],[class*="placeholder:text-token-input-placeholder-foreground"])::placeholder{color:var(--codex-plus-user-bubble-dark-fg)}',
102
106
  exports: {
103
107
  defaultColor,