feat: issue 2097 wave 3 features#2109
Conversation
Stijnus
left a comment
There was a problem hiding this comment.
Code Review — PR #2109
Same author as #2108, same pattern — this PR bundles 10 unrelated features across 2 "waves" in a single PR (+1417/-75, 22 files). Reviewing each feature:
Structural Issue: This needs to be split
This PR contains 10 independent features across 22 files in 2 commits. Each feature should be its own PR:
- Agent mode, confirm file writes, auto prompt enhancement, mobile UI, performance mode (Wave 2)
- Azure OpenAI, Vertex AI, framework lock, keyboard shortcuts, pause/resume preview (Wave 3)
Bundling makes it impossible to review, revert, or bisect individual features.
Critical Issues
1. Agent Mode doubles LLM cost with no user visibility
In stream-text.ts, Agent Mode makes a separate LLM call before every response to generate a plan:
const planResult = await _streamText({
model: provider.getModelInstance({...}),
system: planPrompt,
messages: convertToCoreMessages(processedMessages as any),
...planTokenParams,
});This silently doubles API costs on every message. There's no indication to the user that an extra call is happening, no cost estimate, and no way to see the generated plan. The plan is injected into the system prompt but never shown to the user — making it impossible to debug if it generates bad plans.
2. Confirm File Writes can lose user work permanently
When confirmFileWrites is enabled, file write actions are intercepted and queued as pending. But:
- If the user closes the browser/tab, all pending actions are lost forever (stored only in a nanostores map, not persisted)
- Actions queued during streaming (
isStreamingcheck) are silently skipped — the user sees no feedback about why files weren't written - Discarding an action marks it as
abortedbut subsequent LLM responses may reference files they assume were written, causing cascading confusion
3. Azure OpenAI provider has authentication issues
In azure-openai.ts, the custom fetch wrapper sends both Authorization header (from the SDK) and api-key header. It then tries to remove Authorization and re-set api-key:
const headers = new Headers(init?.headers);
headers.delete('Authorization');
headers.set('api-key', apiKey);But it also passes apiKey to createOpenAI() which sets the Authorization header. This dual-auth approach is fragile. Azure OpenAI requires either api-key header OR Authorization: Bearer — not both. The compatibility: 'compatible' flag with the OpenAI SDK may also cause issues with Azure's slightly different API shape.
4. Vertex AI provider uses wrong SDK
In vertex-ai.ts, it uses createGoogleGenerativeAI from @ai-sdk/google:
import { createGoogleGenerativeAI } from '@ai-sdk/google';But this creates a Google AI Studio client, not a Vertex AI client. The Vertex AI API has a different URL structure and authentication scheme (OAuth2 service account tokens vs API keys). The @ai-sdk/google-vertex package exists specifically for Vertex AI. Using @ai-sdk/google with a custom base URL and Bearer token may work for some endpoints but is not the correct integration and will likely break for certain models or features.
5. Framework detection runs on every render
In Chat.client.tsx:
const frameworkHint = useMemo(() => {
if (!frameworkLock) return undefined;
const detected = detectFrameworkFromFiles(files);
...
}, [files, frameworkLock]);files is a nanostores FileMap that changes frequently (on every file save, every LLM file write). This means detectFrameworkFromFiles — which parses package.json from the file map — runs on every file change. While not catastrophic, it's unnecessary. The framework rarely changes; this should be debounced or cached.
6. Keyboard shortcuts can conflict with browser/OS shortcuts
The shortcut recording in FeaturesTab.tsx captures any key combo without checking for conflicts:
updateShortcutBinding(recordingShortcut, {
key: event.key,
ctrlKey: event.ctrlKey || undefined,
metaKey: event.metaKey || undefined,
...
});A user could record Cmd+W (close tab), Cmd+Q (quit browser), Cmd+T (new tab), etc. There's no validation or warning about conflicts with browser shortcuts. Also, the ctrlOrMetaKey field is always set to undefined when recording — meaning the cross-platform behavior is lost. If a user records Ctrl+D on Mac, it won't match Cmd+D.
7. Mobile toggle manipulates stores directly without coordination
const toggleMobileView = () => {
const nextShowWorkbench = !showWorkbench;
workbenchStore.showWorkbench.set(nextShowWorkbench);
chatStore.setKey('showChat', !nextShowWorkbench);
};This directly sets two independent stores. If either setter triggers side effects or if there's a listener that reads both stores, they may see inconsistent state. The sidebar toggle button also had its disabled check removed (disabled={!canHideChat} instead of disabled={!canHideChat || isSmallViewport}), which could cause layout issues.
Minor Issues
8. docs/issue-2097-tracker.txt — Same as #2108, tracking files don't belong in the repo.
9. Performance mode is cosmetic only — It removes backdrop-blur and background rays, but these are CSS-only effects that browsers already GPU-accelerate. The actual CPU/GPU drain comes from the WebContainer, iframe preview, and CodeMirror editor — none of which are affected by this toggle. The feature risks being misleading.
10. Auto prompt enhancement UX — When enabled, every message silently gets enhanced before sending. The user types one thing but a different prompt gets sent. There's a toast notification but no way to see/approve the enhanced version before it's sent. Combined with Agent Mode (which adds another invisible planning step), a single user message could trigger 3 LLM calls.
What's done well
- Framework detection logic in
framework.tsis comprehensive and well-ordered (specific frameworks before generic ones) - The
PendingFileActionscomponent UI with diff preview is a nice concept - Keyboard shortcut persistence with proper defaults merging is solid
- Pause/resume preview is clean and simple
- The mobile toggle idea addresses a real need
Recommendation: Do NOT approve
- Split into individual PRs — each feature needs independent review
- Agent Mode — needs user visibility (show the plan), cost warning, and opt-in per message
- Vertex AI — use the correct SDK (
@ai-sdk/google-vertex) - Azure OpenAI — fix dual-auth, test with actual Azure endpoints
- Confirm File Writes — persist pending actions, handle the streaming case properly
- Keyboard shortcuts — add conflict detection, preserve ctrlOrMetaKey behavior
- Remove tracker file from the repo
Summary
This PR continues issue #2097 by shipping the next 5 community requests plus a few QoL items already in this branch.
Detailed Change Log
Wave 2 (QoL + performance + workflow)
Wave 3 (new providers + stability + workflow)
Tracker Update
Testing
Refs #2097