From 1ef354465ab37c25e0f33938491fbef52abd07e1 Mon Sep 17 00:00:00 2001 From: diegosouzapw Date: Tue, 21 Apr 2026 22:11:19 -0300 Subject: [PATCH] fix(release): resolve combo prefixing, electron packaging, and CLI auth regressions (#1471, #1492, #1496, #1497, #1486) --- electron/package.json | 3 +- next.config.mjs | 2 + open-sse/handlers/chatCore.ts | 6 +- package-lock.json | 105 +++++++++++++++++++++++- package.json | 1 + scripts/prepare-electron-standalone.mjs | 18 +++- src/shared/services/cliRuntime.ts | 23 ++++-- src/sse/services/model.ts | 16 +++- 8 files changed, 155 insertions(+), 19 deletions(-) diff --git a/electron/package.json b/electron/package.json index 58f200b0f2..3acc5c815d 100644 --- a/electron/package.json +++ b/electron/package.json @@ -53,7 +53,8 @@ "from": "../.next/electron-standalone", "to": "app", "filter": [ - "**/*" + "**/*", + "node_modules/**/*" ] }, { diff --git a/next.config.mjs b/next.config.mjs index 375b966e96..6c2a060519 100644 --- a/next.config.mjs +++ b/next.config.mjs @@ -35,6 +35,7 @@ const nextConfig = { "pino", "pino-pretty", "thread-stream", + "pino-abstract-transport", "better-sqlite3", "keytar", "wreq-js", @@ -96,6 +97,7 @@ const nextConfig = { "zod", "pino", "pino-pretty", + "pino-abstract-transport", "child_process", "fs", "path", diff --git a/open-sse/handlers/chatCore.ts b/open-sse/handlers/chatCore.ts index 11dc1b1865..062a0ae8ce 100644 --- a/open-sse/handlers/chatCore.ts +++ b/open-sse/handlers/chatCore.ts @@ -1227,8 +1227,10 @@ export async function handleChatCore({ const { getComboByName } = await import("../../src/lib/localDb"); const { parseModel } = await import("../services/model.ts"); const { resolveComboTargets } = await import("../services/combo.ts"); - const comboToSearch = comboName.startsWith("combo/") ? comboName.substring(6) : comboName; - const comboConfig = await getComboByName(comboToSearch); + let comboConfig = await getComboByName(comboName); + if (!comboConfig && comboName.startsWith("combo/")) { + comboConfig = await getComboByName(comboName.substring(6)); + } if (comboConfig) { const targets = await resolveComboTargets(comboConfig, null); const limits = targets.map((t: { modelStr?: string }) => { diff --git a/package-lock.json b/package-lock.json index 75a5030333..21871618bd 100644 --- a/package-lock.json +++ b/package-lock.json @@ -36,6 +36,7 @@ "open": "^11.0.0", "ora": "^9.1.0", "pino": "^10.3.1", + "pino-abstract-transport": "^1.2.0", "pino-pretty": "^13.1.3", "react": "19.2.5", "react-dom": "19.2.5", @@ -7298,6 +7299,18 @@ "dev": true, "license": "MIT" }, + "node_modules/abort-controller": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", + "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", + "license": "MIT", + "dependencies": { + "event-target-shim": "^5.0.0" + }, + "engines": { + "node": ">=6.5" + } + }, "node_modules/accepts": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/accepts/-/accepts-2.0.0.tgz", @@ -10670,12 +10683,30 @@ "node": ">= 0.6" } }, + "node_modules/event-target-shim": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", + "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/eventemitter3": { "version": "4.0.7", "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==", "license": "MIT" }, + "node_modules/events": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", + "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", + "license": "MIT", + "engines": { + "node": ">=0.8.x" + } + }, "node_modules/eventsource": { "version": "3.0.7", "resolved": "https://registry.npmjs.org/eventsource/-/eventsource-3.0.7.tgz", @@ -16274,14 +16305,55 @@ } }, "node_modules/pino-abstract-transport": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pino-abstract-transport/-/pino-abstract-transport-3.0.0.tgz", - "integrity": "sha512-wlfUczU+n7Hy/Ha5j9a/gZNy7We5+cXp8YL+X+PG8S0KXxw7n/JXA3c46Y0zQznIJ83URJiwy7Lh56WLokNuxg==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/pino-abstract-transport/-/pino-abstract-transport-1.2.0.tgz", + "integrity": "sha512-Guhh8EZfPCfH+PMXAb6rKOjGQEoy0xlAIn+irODG5kgfYV+BQ0rGYYWTIel3P5mmyXqkYkPmdIkywsn6QKUR1Q==", "license": "MIT", "dependencies": { + "readable-stream": "^4.0.0", "split2": "^4.0.0" } }, + "node_modules/pino-abstract-transport/node_modules/buffer": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", + "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.2.1" + } + }, + "node_modules/pino-abstract-transport/node_modules/readable-stream": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.7.0.tgz", + "integrity": "sha512-oIGGmcpTLwPga8Bn6/Z75SVaH1z5dUut2ibSyAMVhmUggWpmDn2dapB0n7f8nwaSiRtepAsfJyfXIO5DCVAODg==", + "license": "MIT", + "dependencies": { + "abort-controller": "^3.0.0", + "buffer": "^6.0.3", + "events": "^3.3.0", + "process": "^0.11.10", + "string_decoder": "^1.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, "node_modules/pino-pretty": { "version": "13.1.3", "resolved": "https://registry.npmjs.org/pino-pretty/-/pino-pretty-13.1.3.tgz", @@ -16306,6 +16378,15 @@ "pino-pretty": "bin.js" } }, + "node_modules/pino-pretty/node_modules/pino-abstract-transport": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pino-abstract-transport/-/pino-abstract-transport-3.0.0.tgz", + "integrity": "sha512-wlfUczU+n7Hy/Ha5j9a/gZNy7We5+cXp8YL+X+PG8S0KXxw7n/JXA3c46Y0zQznIJ83URJiwy7Lh56WLokNuxg==", + "license": "MIT", + "dependencies": { + "split2": "^4.0.0" + } + }, "node_modules/pino-pretty/node_modules/strip-json-comments": { "version": "5.0.3", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-5.0.3.tgz", @@ -16324,6 +16405,15 @@ "integrity": "sha512-BndPH67/JxGExRgiX1dX0w1FvZck5Wa4aal9198SrRhZjH3GxKQUKIBnYJTdj2HDN3UQAS06HlfcSbQj2OHmaw==", "license": "MIT" }, + "node_modules/pino/node_modules/pino-abstract-transport": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pino-abstract-transport/-/pino-abstract-transport-3.0.0.tgz", + "integrity": "sha512-wlfUczU+n7Hy/Ha5j9a/gZNy7We5+cXp8YL+X+PG8S0KXxw7n/JXA3c46Y0zQznIJ83URJiwy7Lh56WLokNuxg==", + "license": "MIT", + "dependencies": { + "split2": "^4.0.0" + } + }, "node_modules/pkce-challenge": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/pkce-challenge/-/pkce-challenge-5.0.1.tgz", @@ -16584,6 +16674,15 @@ "license": "MIT", "peer": true }, + "node_modules/process": { + "version": "0.11.10", + "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", + "integrity": "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==", + "license": "MIT", + "engines": { + "node": ">= 0.6.0" + } + }, "node_modules/process-warning": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/process-warning/-/process-warning-5.0.0.tgz", diff --git a/package.json b/package.json index 36ab8342b5..d3c2d7acab 100644 --- a/package.json +++ b/package.json @@ -128,6 +128,7 @@ "open": "^11.0.0", "ora": "^9.1.0", "pino": "^10.3.1", + "pino-abstract-transport": "^1.2.0", "pino-pretty": "^13.1.3", "react": "19.2.5", "react-dom": "19.2.5", diff --git a/scripts/prepare-electron-standalone.mjs b/scripts/prepare-electron-standalone.mjs index fec1b81ecb..30647e2b03 100644 --- a/scripts/prepare-electron-standalone.mjs +++ b/scripts/prepare-electron-standalone.mjs @@ -8,6 +8,7 @@ import { readFileSync, rmSync, writeFileSync, + readdirSync, } from "node:fs"; import { basename, dirname, join, relative } from "node:path"; import { fileURLToPath } from "node:url"; @@ -146,12 +147,21 @@ ensurePackage( join(ROOT, "node_modules", "@swc", "helpers") ); -// removed better-sqlite3 to ensure ABI compatibility via electron-builder -const bundledSqlite = join(ELECTRON_STANDALONE_DIR, "node_modules", "better-sqlite3"); -if (existsSync(bundledSqlite)) { - rmSync(bundledSqlite, { recursive: true, force: true }); +// Remove native modules to ensure ABI compatibility via electron-builder +function removeNativeModules(baseDir) { + if (!existsSync(baseDir)) return; + const dirs = readdirSync(baseDir); + for (const dir of dirs) { + if (dir.startsWith("better-sqlite3") || dir.startsWith("keytar")) { + const fullPath = join(baseDir, dir); + rmSync(fullPath, { recursive: true, force: true }); + } + } } +removeNativeModules(join(ELECTRON_STANDALONE_DIR, "node_modules")); +removeNativeModules(join(ELECTRON_STANDALONE_DIR, ".next", "node_modules")); + console.log( `[electron] prepared standalone bundle: ${relative(ROOT, ELECTRON_STANDALONE_DIR) || "."}` ); diff --git a/src/shared/services/cliRuntime.ts b/src/shared/services/cliRuntime.ts index ea73f454ab..ac49712a76 100644 --- a/src/shared/services/cliRuntime.ts +++ b/src/shared/services/cliRuntime.ts @@ -15,7 +15,7 @@ const CLI_TOOLS: Record = { healthcheckTimeoutMs: 4000, paths: { settings: ".claude/settings.json", - auth: ".claude/.credentials.json", + auth: [".claude/.credentials.json", ".config/claude/credentials.json"], }, }, codex: { @@ -821,10 +821,23 @@ export const getCliConfigPaths = (toolId: string) => { const home = getCliConfigHome(); return Object.fromEntries( - Object.entries(tool.paths).map(([key, relativePath]) => [ - key, - path.join(home, relativePath as string), - ]) + Object.entries(tool.paths).map(([key, relativePath]) => { + let resolvedPath = ""; + if (Array.isArray(relativePath)) { + // Find the first path that exists, or default to the first one + resolvedPath = path.join(home, relativePath[0]); + for (const p of relativePath) { + const candidate = path.join(home, p); + if (fsSync.existsSync(candidate)) { + resolvedPath = candidate; + break; + } + } + } else { + resolvedPath = path.join(home, relativePath as string); + } + return [key, resolvedPath]; + }) ); }; diff --git a/src/sse/services/model.ts b/src/sse/services/model.ts index d50ee138a2..55cbf9cb84 100644 --- a/src/sse/services/model.ts +++ b/src/sse/services/model.ts @@ -105,13 +105,21 @@ export async function getModelInfo(modelStr) { * @returns {Promise} Full combo object or null if not a combo */ export async function getCombo(modelStr) { - // Check combo DB first (supports names with /) - // Strip combo/ prefix if present - const nameToSearch = modelStr.startsWith("combo/") ? modelStr.substring(6) : modelStr; - const combo = await getComboByName(nameToSearch); + // Try exact match first (supports combos actually named "combo/ANY") + let combo = await getComboByName(modelStr); if (combo && combo.models && combo.models.length > 0) { return combo; } + + // Fallback: Strip combo/ prefix if present + if (modelStr.startsWith("combo/")) { + const nameToSearch = modelStr.substring(6); + combo = await getComboByName(nameToSearch); + if (combo && combo.models && combo.models.length > 0) { + return combo; + } + } + return null; }