feat(copilot): add raw settings support to useCopilot hook

Add CopilotRawSettings interface and API functions for reading/writing
copilot.settings.json with conflict detection via expectedMtime.
This commit is contained in:
kaitranntt
2025-12-18 00:21:33 -05:00
parent a3e2153498
commit 882792a4fb
+57
View File
@@ -30,6 +30,10 @@ export interface CopilotConfig {
rate_limit: number | null;
wait_on_limit: boolean;
model: string;
// Model mapping for Claude tiers
opus_model?: string;
sonnet_model?: string;
haiku_model?: string;
}
export interface CopilotModel {
@@ -40,6 +44,15 @@ export interface CopilotModel {
isCurrent?: boolean;
}
export interface CopilotRawSettings {
settings: {
env?: Record<string, string>;
};
mtime: number;
path: string;
exists: boolean;
}
// API functions
async function fetchCopilotStatus(): Promise<CopilotStatus> {
const res = await fetch(`${API_BASE}/copilot/status`);
@@ -59,6 +72,12 @@ async function fetchCopilotModels(): Promise<{ models: CopilotModel[]; current:
return res.json();
}
async function fetchCopilotRawSettings(): Promise<CopilotRawSettings> {
const res = await fetch(`${API_BASE}/copilot/settings/raw`);
if (!res.ok) throw new Error('Failed to fetch copilot raw settings');
return res.json();
}
async function updateCopilotConfig(config: Partial<CopilotConfig>): Promise<{ success: boolean }> {
const res = await fetch(`${API_BASE}/copilot/config`, {
method: 'PUT',
@@ -69,6 +88,20 @@ async function updateCopilotConfig(config: Partial<CopilotConfig>): Promise<{ su
return res.json();
}
async function saveCopilotRawSettings(data: {
settings: CopilotRawSettings['settings'];
expectedMtime?: number;
}): Promise<{ success: boolean; mtime: number }> {
const res = await fetch(`${API_BASE}/copilot/settings/raw`, {
method: 'PUT',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(data),
});
if (res.status === 409) throw new Error('CONFLICT');
if (!res.ok) throw new Error('Failed to save copilot raw settings');
return res.json();
}
async function startCopilotAuth(): Promise<{ success: boolean; error?: string }> {
const res = await fetch(`${API_BASE}/copilot/auth/start`, { method: 'POST' });
if (!res.ok) throw new Error('Failed to start auth');
@@ -108,12 +141,27 @@ export function useCopilot() {
queryFn: fetchCopilotModels,
});
const rawSettingsQuery = useQuery({
queryKey: ['copilot-raw-settings'],
queryFn: fetchCopilotRawSettings,
});
// Mutations
const updateConfigMutation = useMutation({
mutationFn: updateCopilotConfig,
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: ['copilot-status'] });
queryClient.invalidateQueries({ queryKey: ['copilot-config'] });
queryClient.invalidateQueries({ queryKey: ['copilot-raw-settings'] });
},
});
const saveRawSettingsMutation = useMutation({
mutationFn: saveCopilotRawSettings,
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: ['copilot-status'] });
queryClient.invalidateQueries({ queryKey: ['copilot-config'] });
queryClient.invalidateQueries({ queryKey: ['copilot-raw-settings'] });
},
});
@@ -157,11 +205,20 @@ export function useCopilot() {
currentModel: modelsQuery.data?.current,
modelsLoading: modelsQuery.isLoading,
// Raw Settings
rawSettings: rawSettingsQuery.data,
rawSettingsLoading: rawSettingsQuery.isLoading,
refetchRawSettings: rawSettingsQuery.refetch,
// Mutations
updateConfig: updateConfigMutation.mutate,
updateConfigAsync: updateConfigMutation.mutateAsync,
isUpdating: updateConfigMutation.isPending,
saveRawSettings: saveRawSettingsMutation.mutate,
saveRawSettingsAsync: saveRawSettingsMutation.mutateAsync,
isSavingRawSettings: saveRawSettingsMutation.isPending,
startAuth: startAuthMutation.mutate,
isAuthenticating: startAuthMutation.isPending,