fix: use live copilot model availability

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
David Kaya
2026-03-22 11:07:43 +01:00
co-authored by Copilot
parent 9799a959d6
commit 6e623b7bd6
16 changed files with 691 additions and 267 deletions
+42 -10
View File
@@ -14,13 +14,20 @@ import {
import { applySessionEventWorkspace } from '@renderer/lib/sessionWorkspace';
import { WelcomePane } from '@renderer/components/WelcomePane';
import { getElectronApi } from '@renderer/lib/electronApi';
import type { SidecarCapabilities } from '@shared/contracts/sidecar';
import {
buildAvailableModelCatalog,
findModel,
normalizePatternModels,
resolveReasoningEffort,
} from '@shared/domain/models';
import type { PatternDefinition } from '@shared/domain/pattern';
import { isScratchpadProject } from '@shared/domain/project';
import { applyScratchpadSessionConfig } from '@shared/domain/session';
import type { WorkspaceState } from '@shared/domain/workspace';
import { createId, nowIso } from '@shared/utils/ids';
function createDraftPattern(): PatternDefinition {
function createDraftPattern(defaultModelId: string, defaultReasoningEffort: PatternDefinition['agents'][0]['reasoningEffort']): PatternDefinition {
const timestamp = nowIso();
return {
id: createId('custom-pattern'),
@@ -35,8 +42,8 @@ function createDraftPattern(): PatternDefinition {
name: 'Primary Agent',
description: 'General-purpose assistant.',
instructions: 'You are a helpful coding assistant working inside the selected project.',
model: 'gpt-5.4',
reasoningEffort: 'high',
model: defaultModelId,
reasoningEffort: defaultReasoningEffort,
},
],
createdAt: timestamp,
@@ -48,6 +55,7 @@ export default function App() {
const api = getElectronApi();
const [workspace, setWorkspace] = useState<WorkspaceState>();
const [error, setError] = useState<string>();
const [sidecarCapabilities, setSidecarCapabilities] = useState<SidecarCapabilities>();
const [sessionActivities, setSessionActivities] = useState<SessionActivityMap>({});
const [showSettings, setShowSettings] = useState(false);
@@ -61,6 +69,14 @@ export default function App() {
.loadWorkspace()
.then((ws) => !disposed && setWorkspace(ws))
.catch((e) => !disposed && setError(e instanceof Error ? e.message : String(e)));
void api
.describeSidecarCapabilities()
.then((capabilities) => !disposed && setSidecarCapabilities(capabilities))
.catch((e) => {
if (!disposed) {
console.warn('Failed to load sidecar capabilities', e);
}
});
const offWorkspace = api.onWorkspaceUpdated((ws) => {
setWorkspace(ws);
@@ -97,6 +113,10 @@ export default function App() {
: undefined,
[selectedSession, workspace?.projects],
);
const availableModels = useMemo(
() => buildAvailableModelCatalog(sidecarCapabilities?.models),
[sidecarCapabilities?.models],
);
const patternForSession = useMemo(() => {
if (!selectedSession) {
return undefined;
@@ -107,10 +127,13 @@ export default function App() {
return undefined;
}
return projectForSession && isScratchpadProject(projectForSession)
? applyScratchpadSessionConfig(basePattern, selectedSession)
: basePattern;
}, [projectForSession, selectedSession, workspace?.patterns]);
const patternWithSessionConfig =
projectForSession && isScratchpadProject(projectForSession)
? applyScratchpadSessionConfig(basePattern, selectedSession)
: basePattern;
return normalizePatternModels(patternWithSessionConfig, availableModels);
}, [availableModels, projectForSession, selectedSession, workspace?.patterns]);
const activityForSession = useMemo(
() => (selectedSession ? sessionActivities[selectedSession.id] : undefined),
[selectedSession, sessionActivities],
@@ -152,6 +175,7 @@ export default function App() {
reasoningEffort: config.reasoningEffort,
})
}
availableModels={availableModels}
pattern={patternForSession}
project={projectForSession}
session={selectedSession}
@@ -177,12 +201,20 @@ export default function App() {
// Settings overlay
const overlay = showSettings ? (
<SettingsPanel
onClose={() => setShowSettings(false)}
<SettingsPanel
availableModels={availableModels}
onClose={() => setShowSettings(false)}
onDeletePattern={async (id) => {
await api.deletePattern(id);
}}
onNewPattern={createDraftPattern}
onNewPattern={() => {
const defaultModel = availableModels[0] ?? findModel('gpt-5.4', availableModels) ?? findModel('gpt-5.4');
return createDraftPattern(
defaultModel?.id ?? 'gpt-5.4',
resolveReasoningEffort(defaultModel, 'high'),
);
}}
onSavePattern={async (pattern) => {
await api.savePattern({ pattern });
}}