Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 6 additions & 6 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "codex-plusplus",
"private": true,
"version": "0.1.5",
"version": "0.1.6",
"license": "MIT",
"description": "Tweak system for the OpenAI Codex desktop app",
"type": "module",
Expand Down
4 changes: 2 additions & 2 deletions packages/installer/assets/runtime/main.js

Large diffs are not rendered by default.

62 changes: 59 additions & 3 deletions packages/installer/assets/runtime/preload.js

Large diffs are not rendered by default.

73 changes: 71 additions & 2 deletions packages/installer/assets/runtime/preload/settings-injector.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion packages/installer/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "codex-plusplus",
"version": "0.1.5",
"version": "0.1.6",
"description": "Installer CLI for codex-plusplus tweak system",
"type": "module",
"repository": {
Expand Down
2 changes: 1 addition & 1 deletion packages/installer/src/version.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
export const CODEX_PLUSPLUS_VERSION = "0.1.5";
export const CODEX_PLUSPLUS_VERSION = "0.1.6";

const SEMVER_RE = /^v?(\d+)\.(\d+)\.(\d+)(?:[-+].*)?$/;

Expand Down
2 changes: 1 addition & 1 deletion packages/loader/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"build": "node -e \"\""
},
"name": "@codex-plusplus/loader",
"version": "0.1.5",
"version": "0.1.6",
"private": true,
"description": "Tiny stub injected into app.asar; bootstraps the runtime from the user dir.",
"main": "loader.cjs"
Expand Down
2 changes: 1 addition & 1 deletion packages/runtime/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@codex-plusplus/runtime",
"version": "0.1.5",
"version": "0.1.6",
"type": "commonjs",
"main": "dist/main.js",
"description": "In-app runtime: discovers tweaks, injects settings UI, hot-reloads.",
Expand Down
2 changes: 1 addition & 1 deletion packages/runtime/src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ const INSTALLER_STATE_FILE = join(userRoot, "state.json");
const UPDATE_MODE_FILE = join(userRoot, "update-mode.json");
const SELF_UPDATE_STATE_FILE = join(userRoot, "self-update-state.json");
const SIGNED_CODEX_BACKUP = join(userRoot, "backup", "Codex.app");
const CODEX_PLUSPLUS_VERSION = "0.1.5";
const CODEX_PLUSPLUS_VERSION = "0.1.6";
const CODEX_PLUSPLUS_REPO = "b-nnett/codex-plusplus";
const TWEAK_STORE_INDEX_URL = process.env.CODEX_PLUSPLUS_STORE_INDEX_URL ?? DEFAULT_TWEAK_STORE_INDEX_URL;
const CODEX_WINDOW_SERVICES_KEY = "__codexpp_window_services__";
Expand Down
72 changes: 70 additions & 2 deletions packages/runtime/src/preload/settings-injector.ts
Original file line number Diff line number Diff line change
Expand Up @@ -359,6 +359,8 @@ export function setListedTweaks(list: ListedTweak[]): void {
// ───────────────────────────────────────────────────────────── injection ──

function tryInject(): void {
removeMisplacedSettingsGroups();

const itemsGroup = findSidebarItemsGroup();
if (!itemsGroup) {
scheduleSettingsSurfaceHidden();
Expand All @@ -374,6 +376,14 @@ function tryInject(): void {
// to hold multiple groups (`flex flex-col gap-1 gap-0`). We inject our
// group as a sibling so the natural gap-1 acts as our visual separator.
const outer = itemsGroup.parentElement ?? itemsGroup;
if (!isSettingsSidebarCandidate(itemsGroup) || !isSettingsSidebarCandidate(outer)) {
scheduleSettingsSurfaceHidden();
plog("rejected non-settings sidebar candidate", {
itemsGroup: describe(itemsGroup),
outer: describe(outer),
});
return;
}
state.sidebarRoot = outer;
syncNativeSettingsHeader(itemsGroup, outer);

Expand Down Expand Up @@ -507,6 +517,13 @@ function setSettingsSurfaceVisible(visible: boolean, reason: string): void {
function syncPagesGroup(): void {
const outer = state.sidebarRoot;
if (!outer) return;
if (!isSettingsSidebarCandidate(outer)) {
state.sidebarRoot = null;
state.pagesGroup = null;
state.pagesGroupKey = null;
for (const p of state.pages.values()) p.navButton = null;
return;
}
const pages = [...state.pages.values()];

// Build a deterministic fingerprint of the desired group state. If the
Expand Down Expand Up @@ -2558,7 +2575,10 @@ function findSidebarItemsGroup(): HTMLElement | null {
let node: HTMLElement | null = links[0].parentElement;
while (node) {
const inside = node.querySelectorAll("a[href*='/settings/']");
if (inside.length >= Math.max(2, links.length - 1)) return node;
if (
inside.length >= Math.max(2, links.length - 1) &&
isSettingsSidebarCandidate(node)
) return node;
node = node.parentElement;
}
}
Expand All @@ -2579,6 +2599,7 @@ function findSidebarItemsGroup(): HTMLElement | null {
"button, a, [role='button'], li, div",
);
for (const el of Array.from(all)) {
if (isForbiddenSettingsSidebarSurface(el)) continue;
const t = (el.textContent ?? "").trim();
if (t.length > 30) continue;
if (KNOWN.some((k) => t === k)) matches.push(el);
Expand All @@ -2589,13 +2610,60 @@ function findSidebarItemsGroup(): HTMLElement | null {
while (node) {
let count = 0;
for (const m of matches) if (node.contains(m)) count++;
if (count >= Math.min(3, matches.length)) return node;
if (count >= Math.min(3, matches.length) && isSettingsSidebarCandidate(node)) return node;
node = node.parentElement;
}
}
return null;
}

const FORBIDDEN_SETTINGS_SIDEBAR_SELECTOR = [
"[data-composer-overlay-floating-ui='true']",
"[data-codexpp-slash-menu='true']",
"[data-codexpp-overlay-noise='true']",
".composer-home-top-menu",
".vertical-scroll-fade-mask",
"[class*='[container-name:home-main-content]']",
].join(",");

function isForbiddenSettingsSidebarSurface(node: Element | null): boolean {
if (!node) return false;
const el = node instanceof HTMLElement ? node : node.parentElement;
if (!el) return false;
if (el.closest(FORBIDDEN_SETTINGS_SIDEBAR_SELECTOR)) return true;
if (el.querySelector("[data-list-navigation-item='true'], [cmdk-item]")) return true;
return false;
}

function isSettingsSidebarCandidate(node: HTMLElement): boolean {
if (isForbiddenSettingsSidebarSurface(node)) return false;
const root = node.parentElement ?? node;
if (isForbiddenSettingsSidebarSurface(root)) return false;
if (root.querySelector("a[href*='/settings/']")) return true;
const text = compactSettingsText(root.textContent ?? "");
return (
text.includes("Back to app") &&
text.includes("General") &&
text.includes("Appearance")
);
}

function removeMisplacedSettingsGroups(): void {
const groups = document.querySelectorAll<HTMLElement>(
"[data-codexpp='nav-group'], [data-codexpp='pages-group'], [data-codexpp='native-nav-header']",
);
for (const group of Array.from(groups)) {
if (!isForbiddenSettingsSidebarSurface(group)) continue;
if (state.navGroup === group) state.navGroup = null;
if (state.pagesGroup === group) {
state.pagesGroup = null;
state.pagesGroupKey = null;
}
if (state.nativeNavHeader === group) state.nativeNavHeader = null;
group.remove();
}
}

function findContentArea(): HTMLElement | null {
const sidebar = findSidebarItemsGroup();
if (!sidebar) return null;
Expand Down
2 changes: 1 addition & 1 deletion packages/sdk/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@codex-plusplus/sdk",
"version": "0.1.5",
"version": "0.1.6",
"description": "Public types and helpers for codex-plusplus tweak authors",
"type": "module",
"main": "dist/index.js",
Expand Down
Loading