diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 6d6e19ce..5f2cbbd2 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -39,23 +39,12 @@ jobs: exit 1 fi - - name: Build and publish macOS artifacts + - name: Build and publish ad-hoc macOS artifacts env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - CSC_LINK: ${{ secrets.CSC_LINK }} - CSC_KEY_PASSWORD: ${{ secrets.CSC_KEY_PASSWORD }} - APPLE_API_KEY: ${{ secrets.APPLE_API_KEY }} - APPLE_API_KEY_ID: ${{ secrets.APPLE_API_KEY_ID }} - APPLE_API_ISSUER: ${{ secrets.APPLE_API_ISSUER }} - APPLE_ID: ${{ secrets.APPLE_ID }} - APPLE_APP_SPECIFIC_PASSWORD: ${{ secrets.APPLE_APP_SPECIFIC_PASSWORD }} - APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }} - APPLE_KEYCHAIN: ${{ secrets.APPLE_KEYCHAIN }} - APPLE_KEYCHAIN_PROFILE: ${{ secrets.APPLE_KEYCHAIN_PROFILE }} run: | - node build/macos-release-preflight.mjs npm run build:assets - npx electron-builder --mac --publish always + npx electron-builder --config build/electron-builder.local.cjs --mac --publish always windows: name: Windows diff --git a/examples/plugins/claude-design-plugin.cjs b/examples/plugins/claude-design-plugin.cjs index c97dc6b5..da9fbd8d 100644 --- a/examples/plugins/claude-design-plugin.cjs +++ b/examples/plugins/claude-design-plugin.cjs @@ -7904,6 +7904,7 @@ function renderDefaultDesignIndex(me, scriptPath, stylePath, options = {}) { Claude Design + ${claudeAppDesktopFeaturesScript()} `; + return ``; } function designModelPreferenceResetScript(me) { diff --git a/src/main/claude-app-cdp.ts b/src/main/claude-app-cdp.ts index ddf27600..e9596fab 100644 --- a/src/main/claude-app-cdp.ts +++ b/src/main/claude-app-cdp.ts @@ -45,7 +45,14 @@ const claudeAppDesignCdpConnectTimeoutMs = 15_000; const claudeAppDesignCdpKeepAliveMs = 45_000; const claudeAppDesignCdpPollIntervalMs = 250; +export function shouldEnableClaudeAppDesignCdp(): boolean { + return process.env.CCR_CLAUDE_APP_DESIGN_CDP?.trim().toLowerCase() === "true"; +} + export async function reserveClaudeAppCdpPort(logger: ClaudeAppCdpLogger = console): Promise { + if (!shouldEnableClaudeAppDesignCdp()) { + return undefined; + } const configured = Number(process.env.CCR_CLAUDE_APP_CDP_PORT); if (Number.isInteger(configured) && configured > 0 && configured <= 65535) { return configured; @@ -63,7 +70,7 @@ export function prepareClaudeAppCdpUserDataDir(userDataDir: string): void { } export function scheduleClaudeAppDesignCdp(options: ClaudeAppDesignCdpOptions): void { - if (process.env.CCR_CLAUDE_APP_DESIGN_CDP?.trim().toLowerCase() === "false") { + if (!shouldEnableClaudeAppDesignCdp()) { return; } const logger = options.logger || console; @@ -215,19 +222,30 @@ function claudeAppDesignFeatureScript(): string { } catch (_) { globalThis.desktopBootFeatures = bootFeatures; } + function patchAppFeatures(container) { + if (!container) { + return; + } + const existing = container.AppFeatures || {}; + if (existing.__ccrClaudeDesignPatched) { + return; + } + const previous = existing.getSupportedFeatures; + container.AppFeatures = Object.assign({}, existing, { + __ccrClaudeDesignPatched: true, + getSupportedFeatures() { + if (typeof previous === "function") { + return Promise.resolve(previous.call(existing)).then(merge, () => merge()); + } + return Promise.resolve(merge()); + } + }); + } + globalThis["claude.settings"] = globalThis["claude.settings"] || {}; + patchAppFeatures(globalThis["claude.settings"]); globalThis.claude = globalThis.claude || {}; globalThis.claude.settings = globalThis.claude.settings || {}; - const existing = globalThis.claude.settings.AppFeatures || {}; - const previous = existing.getSupportedFeatures; - globalThis.claude.settings.AppFeatures = Object.assign({}, existing, { - __ccrClaudeDesignPatched: true, - getSupportedFeatures() { - if (typeof previous === "function") { - return Promise.resolve(previous.call(existing)).then(merge, () => merge()); - } - return Promise.resolve(merge()); - } - }); + patchAppFeatures(globalThis.claude.settings); })();`; } diff --git a/src/main/codex-cli-middleware-runtime.ts b/src/main/codex-cli-middleware-runtime.ts index 308cc5de..6791ffb6 100644 --- a/src/main/codex-cli-middleware-runtime.ts +++ b/src/main/codex-cli-middleware-runtime.ts @@ -1984,11 +1984,12 @@ function collaborationModes() { function modelList(params, existingResult) { const runtimeAgent = codexRuntimeAgent(); const isClaudeCodeRuntime = normalizeRemoteFrontendMode(agentEnv(runtimeAgent, "REMOTE_FRONTEND_MODE", "CORE_MODE")) === "claude-code"; - const configured = normalizeModelSelector(agentEnv(runtimeAgent, "MODEL") || nonEmptyEnv("CODEXL_CLAUDE_CODE_MODEL") || (isClaudeCodeRuntime ? DEFAULT_MODEL : "")); + const configured = normalizeModelSelector(agentEnv(runtimeAgent, "MODEL") || nonEmptyEnv("CODEXL_CLAUDE_CODE_MODEL")); + const selected = configured || (isClaudeCodeRuntime ? DEFAULT_MODEL : ""); const fallbackIds = isClaudeCodeRuntime - ? [configured, DEFAULT_MODEL, "claude-opus-4-5", "claude-haiku-4-5"].filter(Boolean) + ? [configured].filter(Boolean) : [configured].filter((model) => model && !isClaudeCodeOnlyModel(model)); - const models = mergeModelListItems(extractModelListItems(existingResult), [...catalogModelIds(), ...fallbackIds], configured); + const models = mergeModelListItems(extractModelListItems(existingResult), [...catalogModelIds(), ...fallbackIds], selected); const offset = Number(params.cursor || 0) || 0; const limit = Number(params.limit || models.length) || models.length; const data = models.slice(offset, offset + limit); diff --git a/src/main/profile-launch-service.ts b/src/main/profile-launch-service.ts index 250a984c..b6d3ef53 100644 --- a/src/main/profile-launch-service.ts +++ b/src/main/profile-launch-service.ts @@ -140,7 +140,18 @@ async function openClaudeAppProfile(config: AppConfig, profile: ReturnType, options: ClaudeAppGatewayModelRouteOptions = {} ): ClaudeAppGatewayModelRoute[] { - const targetModels = claudeAppGatewayTargetModels(config).slice(0, CLAUDE_APP_ROUTE_NAMES.length); + const targetModels = claudeAppGatewayTargetModels(config); const displayNames = claudeAppGatewayDisplayNames(targetModels); return targetModels.map((rawTargetModel, index) => { const targetModel = stripClaudeAppGatewayOneMillionContextSuffix(rawTargetModel); const oneMillionContext = claudeAppGatewaySupportsOneMillionContext(rawTargetModel, options); - const routeId = claudeAppGatewayRouteId(index); + const routeId = claudeAppGatewayRouteId(rawTargetModel); return { displayName: oneMillionContext ? `${displayNames[index]} (1M context)` : displayNames[index], id: routeId, + legacyId: claudeAppGatewayLegacyRouteId(index), oneMillionContext, targetModel }; @@ -63,8 +65,11 @@ export function resolveClaudeAppGatewayRouteModel( const normalized = model.trim().toLowerCase(); return buildClaudeAppGatewayModelRoutes(config, options).find((route) => { const routeId = route.id.toLowerCase(); + const legacyRouteId = route.legacyId?.toLowerCase(); return routeId === normalized || - stripClaudeAppGatewayOneMillionContextSuffix(routeId).toLowerCase() === normalized; + stripClaudeAppGatewayOneMillionContextSuffix(routeId).toLowerCase() === normalized || + legacyRouteId === normalized || + (legacyRouteId ? stripClaudeAppGatewayOneMillionContextSuffix(legacyRouteId).toLowerCase() === normalized : false); })?.targetModel; } @@ -153,8 +158,13 @@ function claudeAppGatewaySupportsOneMillionContext( Boolean(options.supportsOneMillionContext?.(baseModel)); } -function claudeAppGatewayRouteId(index: number): string { - return CLAUDE_APP_ROUTE_NAMES[index] ?? CLAUDE_APP_FALLBACK_MODEL; +function claudeAppGatewayLegacyRouteId(index: number): string | undefined { + return CLAUDE_APP_LEGACY_ROUTE_NAMES[index]; +} + +function claudeAppGatewayRouteId(model: string): string { + const normalized = model.trim(); + return normalized.toLowerCase().startsWith("claude-") ? normalized : `claude-${normalized}`; } function claudeAppGatewayDisplayNames(models: string[]): string[] {