diff --git a/.github/workflows/electron-build.yml b/.github/workflows/electron-build.yml index 787e28e6..ec60096f 100644 --- a/.github/workflows/electron-build.yml +++ b/.github/workflows/electron-build.yml @@ -16,9 +16,9 @@ jobs: uses: actions/checkout@v6 - name: Setup pnpm - uses: pnpm/action-setup@v6 + uses: pnpm/action-setup@v4 with: - version: 10 + version: 9 - name: Setup Node.js uses: actions/setup-node@v6 @@ -39,17 +39,17 @@ jobs: node -e " const fs = require('fs'); const version = '${{ steps.version.outputs.version }}'; - + // Update apps/x/package.json const rootPackage = JSON.parse(fs.readFileSync('apps/x/package.json', 'utf8')); rootPackage.version = version; fs.writeFileSync('apps/x/package.json', JSON.stringify(rootPackage, null, 2) + '\n'); - + // Update apps/x/apps/main/package.json const mainPackage = JSON.parse(fs.readFileSync('apps/x/apps/main/package.json', 'utf8')); mainPackage.version = version; fs.writeFileSync('apps/x/apps/main/package.json', JSON.stringify(mainPackage, null, 2) + '\n'); - + console.log('Updated version to:', version); " @@ -61,25 +61,25 @@ jobs: # Create a temporary keychain KEYCHAIN_PATH=$RUNNER_TEMP/app-signing.keychain-db KEYCHAIN_PASSWORD=$(openssl rand -base64 32) - + # Create keychain security create-keychain -p "$KEYCHAIN_PASSWORD" "$KEYCHAIN_PATH" security set-keychain-settings -lut 21600 "$KEYCHAIN_PATH" security unlock-keychain -p "$KEYCHAIN_PASSWORD" "$KEYCHAIN_PATH" - + # Decode and import certificate echo "$APPLE_CERTIFICATE" | base64 --decode > $RUNNER_TEMP/certificate.p12 security import $RUNNER_TEMP/certificate.p12 -P "$APPLE_CERTIFICATE_PASSWORD" -A -t cert -f pkcs12 -k "$KEYCHAIN_PATH" - + # Allow codesign to access the keychain security set-key-partition-list -S apple-tool:,apple: -s -k "$KEYCHAIN_PASSWORD" "$KEYCHAIN_PATH" - + # Add keychain to search list security list-keychains -d user -s "$KEYCHAIN_PATH" login.keychain - + # Verify certificate was imported security find-identity -v "$KEYCHAIN_PATH" - + # Clean up certificate file rm -f $RUNNER_TEMP/certificate.p12 @@ -122,9 +122,9 @@ jobs: uses: actions/checkout@v6 - name: Setup pnpm - uses: pnpm/action-setup@v6 + uses: pnpm/action-setup@v4 with: - version: 10 + version: 9 - name: Setup Node.js uses: actions/setup-node@v6 @@ -145,17 +145,17 @@ jobs: node -e " const fs = require('fs'); const version = '${{ steps.version.outputs.version }}'; - + // Update apps/x/package.json const rootPackage = JSON.parse(fs.readFileSync('apps/x/package.json', 'utf8')); rootPackage.version = version; fs.writeFileSync('apps/x/package.json', JSON.stringify(rootPackage, null, 2) + '\n'); - + // Update apps/x/apps/main/package.json const mainPackage = JSON.parse(fs.readFileSync('apps/x/apps/main/package.json', 'utf8')); mainPackage.version = version; fs.writeFileSync('apps/x/apps/main/package.json', JSON.stringify(mainPackage, null, 2) + '\n'); - + console.log('Updated version to:', version); " @@ -187,9 +187,9 @@ jobs: uses: actions/checkout@v6 - name: Setup pnpm - uses: pnpm/action-setup@v6 + uses: pnpm/action-setup@v4 with: - version: 10 + version: 9 - name: Setup Node.js uses: actions/setup-node@v6 @@ -212,17 +212,17 @@ jobs: node -e " const fs = require('fs'); const version = '${{ steps.version.outputs.version }}'; - + // Update apps/x/package.json const rootPackage = JSON.parse(fs.readFileSync('apps/x/package.json', 'utf8')); rootPackage.version = version; fs.writeFileSync('apps/x/package.json', JSON.stringify(rootPackage, null, 2) + '\n'); - + // Update apps/x/apps/main/package.json const mainPackage = JSON.parse(fs.readFileSync('apps/x/apps/main/package.json', 'utf8')); mainPackage.version = version; fs.writeFileSync('apps/x/apps/main/package.json', JSON.stringify(mainPackage, null, 2) + '\n'); - + console.log('Updated version to:', version); " diff --git a/apps/x/apps/renderer/src/components/chat-input-with-mentions.tsx b/apps/x/apps/renderer/src/components/chat-input-with-mentions.tsx index 0254cdfd..a7d548ea 100644 --- a/apps/x/apps/renderer/src/components/chat-input-with-mentions.tsx +++ b/apps/x/apps/renderer/src/components/chat-input-with-mentions.tsx @@ -1,4 +1,4 @@ -import { useCallback, useEffect, useLayoutEffect, useRef, useState } from 'react' +import { useCallback, useEffect, useRef, useState } from 'react' import { Tooltip, TooltipContent, TooltipTrigger } from '@/components/ui/tooltip' import { ArrowUp, @@ -19,7 +19,6 @@ import { ImagePlus, LoaderIcon, Mic, - MoreHorizontal, Plus, ShieldCheck, Square, @@ -30,7 +29,6 @@ import { import { Button } from '@/components/ui/button' import { DropdownMenu, - DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuItem, DropdownMenuRadioGroup, @@ -285,51 +283,6 @@ function ChatInputInner({ const [permissionMode, setPermissionMode] = useState('auto') const [recentWorkDirs, setRecentWorkDirs] = useState([]) - // Responsive toolbar: measure real overflow and progressively collapse items - // right→left until everything fits. Stages: - // 1 code→icon · 2 perm→icon · 3 search label hidden · 4 workDir→icon - // 5 code→menu · 6 perm→menu · 7 search→menu · 8 workDir→menu - // Once items move into the "⋯" overflow menu (≥5) no icon is ever hidden. - // overflow-hidden on the left group is the hard guarantee against any overlap. - const toolbarRef = useRef(null) - const leftGroupRef = useRef(null) - const lastWidthRef = useRef(0) - const [collapseLevel, setCollapseLevel] = useState(0) - - // Re-evaluate from scratch (level 0) whenever the available width changes… - useEffect(() => { - const outer = toolbarRef.current - if (!outer) return - const ro = new ResizeObserver(() => { - const w = outer.clientWidth - if (w !== lastWidthRef.current) { - lastWidthRef.current = w - setCollapseLevel(0) - } - }) - ro.observe(outer) - return () => ro.disconnect() - }, []) - - // …or when the *set* of items changes (an item appears/disappears, or the model - // name width changes). Deliberately excludes the in-place toggles (searchEnabled, - // permissionMode, codeModeEnabled, codingAgent): those fire from the overflow menu - // for items already inside it, so resetting here would unmount the open menu. The - // no-dep effect below still re-collapses if any toggle happens to widen the row. - useLayoutEffect(() => { - setCollapseLevel(0) - }, [workDir, searchAvailable, codeModeFeatureEnabled, lockedModel, activeModelKey]) - - // After each render, if the left group still overflows, collapse one more step. - // Runs before paint, so the intermediate (overflowing) state is never visible. - useLayoutEffect(() => { - const el = leftGroupRef.current - if (!el) return - if (el.scrollWidth > el.clientWidth + 1 && collapseLevel < 8) { - setCollapseLevel((l) => Math.min(8, l + 1)) - } - }) - // When a run exists, freeze the dropdown to the run's resolved model+provider. useEffect(() => { if (!runId) { @@ -804,8 +757,7 @@ function ChatInputInner({ className="min-h-6 rounded-none border-0 py-0 shadow-none focus-visible:ring-0" /> -
-
+
@@ -910,32 +862,26 @@ function ChatInputInner({
- {workDir && collapseLevel < 8 && ( + {workDir && ( - {/* Level 4: collapse to a square icon */} -
= 4 ? "w-7 justify-center" : "max-w-[180px] pl-2.5 pr-2" - )}> +
+ - {collapseLevel < 4 && ( - - )}
@@ -943,7 +889,7 @@ function ChatInputInner({ )} - {searchAvailable && collapseLevel < 7 && ( + {searchAvailable && ( )} - {collapseLevel < 6 && ( @@ -996,54 +943,37 @@ function ChatInputInner({ : 'Manual approval prompts — click for auto-permission'} - )} - {codeModeFeatureEnabled && collapseLevel < 5 && (codeModeEnabled ? ( - collapseLevel >= 1 ? ( - /* Level 1: collapse the pill to a single icon */ + {codeModeFeatureEnabled && (codeModeEnabled ? ( +
- Code mode on ({codingAgent === 'claude' ? 'Claude Code' : 'Codex'}) — click to disable + Code mode on — click to disable - ) : ( -
- - - - - Code mode on — click to disable - - · - - - - - - Coding agent: {codingAgent === 'claude' ? 'Claude Code' : 'Codex'} — click to swap - - -
- ) + · + + + + + + Coding agent: {codingAgent === 'claude' ? 'Claude Code' : 'Codex'} — click to swap + + +
) : ( @@ -1059,89 +989,25 @@ function ChatInputInner({ Use a coding agent (Claude Code or Codex) ))} -
- {collapseLevel >= 5 && ( - - - - - - - - More options - - - {workDir && collapseLevel >= 8 && ( - { void handleSetWorkDir() }}> - - {basename(workDir) || workDir} - - )} - {searchAvailable && collapseLevel >= 7 && ( - e.preventDefault()} - onCheckedChange={(c) => setSearchEnabled(Boolean(c))} - > - Web search - - )} - {collapseLevel >= 6 && ( - e.preventDefault()} - onCheckedChange={(c) => setPermissionMode(c ? 'auto' : 'manual')} - > - Auto-approve actions - - )} - {codeModeFeatureEnabled && collapseLevel >= 5 && ( - <> - e.preventDefault()} - onCheckedChange={(c) => setCodeModeEnabled(Boolean(c))} - > - Code mode - - {codeModeEnabled && ( - { e.preventDefault(); handleToggleCodingAgent() }}> - - Coding agent - {codingAgent === 'claude' ? 'Claude' : 'Codex'} - - )} - - )} - - - )}
{lockedModel ? ( - {getSelectedModelDisplayName(lockedModel.model)} + {getSelectedModelDisplayName(lockedModel.model)} ) : configuredModels.length > 0 ? (