Restore features lost during main merge and fix workspace setup flow

Restores all features dropped when merging main into dev:
- Keyboard shortcuts (send, dictation-confirm) with full e2e chain
- Feature toggles (plan/fast mode) in agent status bar
- Sidebar kebab menu (Remove Project) on project rows
- Combined model selector (sticky header, sizing, favorites sort, search)
- Question form Enter key submit with guard
- Input focus restoration (composer + AgentStatusBar onDropdownClose)
- Draft-agent feature toggles and focus restoration
- Provider diagnostics UI (settings section, diagnostic sheet, status badge)
- Provider diagnostics server (snapshot manager, diagnostic utils, RPC)

Fixes dev-branch regressions:
- New workspace button now opens composer in setup dialog via beginWorkspaceSetup
- Setup tab auto-opens when workspace setup is running
This commit is contained in:
Mohamed Boudra
2026-04-05 21:10:16 +07:00
parent 8e482b1613
commit 4dca672711
26 changed files with 2002 additions and 147 deletions
@@ -7,6 +7,7 @@ import {
type CreateAgentInitialValues,
type UseAgentFormStateResult,
} from "@/hooks/use-agent-form-state";
import { useDraftAgentFeatures } from "@/hooks/use-draft-agent-features";
import { useDraftStore } from "@/stores/draft-store";
import type { AgentModelDefinition } from "@server/server/agent/agent-sdk-types";
@@ -35,6 +36,7 @@ type DraftComposerState = UseAgentFormStateResult & {
workingDir: string;
effectiveModelId: string;
effectiveThinkingOptionId: string;
featureValues: Record<string, unknown> | undefined;
statusControls: DraftAgentStatusBarProps;
commandDraftConfig: DraftCommandConfig | undefined;
};
@@ -116,6 +118,7 @@ function buildDraftComposerCommandConfig(input: {
selectedMode: string;
effectiveModelId: string;
effectiveThinkingOptionId: string;
featureValues?: Record<string, unknown>;
}): DraftCommandConfig | undefined {
const cwd = input.cwd.trim();
if (!cwd) {
@@ -130,13 +133,17 @@ function buildDraftComposerCommandConfig(input: {
...(input.effectiveThinkingOptionId
? { thinkingOptionId: input.effectiveThinkingOptionId }
: {}),
...(input.featureValues ? { featureValues: input.featureValues } : {}),
};
}
function buildDraftStatusControls(input: {
formState: UseAgentFormStateResult;
features?: DraftAgentStatusBarProps["features"];
onSetFeature?: DraftAgentStatusBarProps["onSetFeature"];
onDropdownClose?: DraftAgentStatusBarProps["onDropdownClose"];
}): DraftAgentStatusBarProps {
const { formState } = input;
const { formState, features, onSetFeature, onDropdownClose } = input;
return {
providerDefinitions: formState.providerDefinitions,
selectedProvider: formState.selectedProvider,
@@ -154,6 +161,9 @@ function buildDraftStatusControls(input: {
thinkingOptions: formState.availableThinkingOptions,
selectedThinkingOptionId: formState.selectedThinkingOptionId,
onSelectThinkingOption: formState.setThinkingOptionFromUser,
features,
onSetFeature,
onDropdownClose,
};
}
@@ -316,6 +326,18 @@ export function useAgentInputDraft(input: UseAgentInputDraftInput): AgentInputDr
);
const workingDir = lockedWorkingDir || formState.workingDir;
const {
features: draftFeatures,
featureValues: draftFeatureValues,
setFeatureValue: setDraftFeatureValue,
} = useDraftAgentFeatures({
serverId: formState.selectedServerId,
provider: formState.selectedProvider,
cwd: workingDir,
modeId: formState.selectedMode,
modelId: effectiveModelId,
thinkingOptionId: effectiveThinkingOptionId,
});
const commandDraftConfig = useMemo(
() =>
@@ -327,12 +349,14 @@ export function useAgentInputDraft(input: UseAgentInputDraftInput): AgentInputDr
selectedMode: formState.selectedMode,
effectiveModelId,
effectiveThinkingOptionId,
featureValues: draftFeatureValues,
})
: undefined,
[
composerOptions,
effectiveModelId,
effectiveThinkingOptionId,
draftFeatureValues,
workingDir,
formState.modeOptions,
formState.selectedMode,
@@ -350,7 +374,12 @@ export function useAgentInputDraft(input: UseAgentInputDraftInput): AgentInputDr
workingDir,
effectiveModelId,
effectiveThinkingOptionId,
statusControls: buildDraftStatusControls({ formState }),
featureValues: draftFeatureValues,
statusControls: buildDraftStatusControls({
formState,
features: draftFeatures,
onSetFeature: setDraftFeatureValue,
}),
commandDraftConfig,
};
}, [
@@ -358,7 +387,10 @@ export function useAgentInputDraft(input: UseAgentInputDraftInput): AgentInputDr
composerOptions,
effectiveModelId,
effectiveThinkingOptionId,
draftFeatures,
draftFeatureValues,
formState,
setDraftFeatureValue,
workingDir,
]);
@@ -129,6 +129,11 @@ export function useKeyboardShortcuts({
id: "message-input.focus",
scope: "message-input",
});
case "send":
return keyboardActionDispatcher.dispatch({
id: "message-input.send",
scope: "message-input",
});
case "dictation-toggle":
return keyboardActionDispatcher.dispatch({
id: "message-input.dictation-toggle",
@@ -139,6 +144,11 @@ export function useKeyboardShortcuts({
id: "message-input.dictation-cancel",
scope: "message-input",
});
case "dictation-confirm":
return keyboardActionDispatcher.dispatch({
id: "message-input.dictation-confirm",
scope: "message-input",
});
case "voice-toggle":
return keyboardActionDispatcher.dispatch({
id: "message-input.voice-toggle",