Skip to content

Commit 3725905

Browse files
committed
feat: settings support electron-store
1 parent 99bfc47 commit 3725905

File tree

13 files changed

+75
-161
lines changed

13 files changed

+75
-161
lines changed

apps/agent-tars/src/main/ipcRoutes/index.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import { actionRoute } from './action';
55
import { browserRoute } from './browser';
66
import { fileSystemRoute } from './filesystem';
77
import { searchRoute } from './search';
8-
8+
import { settingsRoute } from './settings';
99
const t = initIpc.create();
1010

1111
export const ipcRoutes = t.router({
@@ -15,6 +15,7 @@ export const ipcRoutes = t.router({
1515
...browserRoute,
1616
...fileSystemRoute,
1717
...searchRoute,
18+
...settingsRoute,
1819
});
1920
export type Router = typeof ipcRoutes;
2021

apps/agent-tars/src/main/ipcRoutes/llm.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ function getLLMProviderConfig(settings: ModelSettings): LLMConfig {
2323
model,
2424
apiKey,
2525
apiVersion,
26+
// TODO: baseURL || endpoint
2627
baseURL: endpoint,
2728
};
2829
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
import { AppSettings } from '@agent-infra/shared';
2+
import { SettingStore } from '@main/store/setting';
3+
import { initIpc } from '@ui-tars/electron-ipc/main';
4+
5+
const t = initIpc.create();
6+
7+
export const settingsRoute = t.router({
8+
getSettings: t.procedure.input<void>().handle(async () => {
9+
return SettingStore.getStore();
10+
}),
11+
getFileSystemSettings: t.procedure.input<void>().handle(async () => {
12+
return SettingStore.get('fileSystem');
13+
}),
14+
updateAppSettings: t.procedure
15+
.input<AppSettings>()
16+
.handle(async ({ input }) => {
17+
SettingStore.setStore(input);
18+
return true;
19+
}),
20+
updateFileSystemSettings: t.procedure
21+
.input<AppSettings['fileSystem']>()
22+
.handle(async ({ input }) => {
23+
SettingStore.set('fileSystem', input);
24+
return true;
25+
}),
26+
});

apps/agent-tars/src/renderer/src/agent/AgentFlow.ts

Lines changed: 0 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@ import { Greeter } from './Greeter';
1717
import { extractHistoryEvents } from '@renderer/utils/extractHistoryEvents';
1818
import { EventItem, EventType } from '@renderer/type/event';
1919
import { SNAPSHOT_BROWSER_ACTIONS } from '@renderer/constants';
20-
import { loadLLMSettings } from '@renderer/services/llmSettings';
2120

2221
export interface AgentContext {
2322
plan: PlanTask[];
@@ -40,23 +39,6 @@ export class AgentFlow {
4039
private loadingStatusTip = '';
4140

4241
constructor(private appContext: AppContext) {
43-
// Load LLM settings and update the configuration
44-
const llmSettings = loadLLMSettings();
45-
if (llmSettings) {
46-
// Update LLM configuration when starting the agent flow
47-
ipcClient
48-
.updateLLMConfig({
49-
configName: llmSettings.provider,
50-
model: llmSettings.model,
51-
apiKey: llmSettings.apiKey,
52-
apiVersion: llmSettings.apiVersion,
53-
baseURL: llmSettings.endpoint,
54-
})
55-
.catch((error) => {
56-
console.error('Failed to update LLM configuration:', error);
57-
});
58-
}
59-
6042
const omegaHistoryEvents = this.parseHistoryEvents();
6143
this.eventManager = new EventManager(omegaHistoryEvents);
6244
this.abortController = new AbortController();

apps/agent-tars/src/renderer/src/api/fileSystemInterceptor.ts

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -87,14 +87,18 @@ export async function interceptToolCalls(
8787
toolName === ToolCallType.DirectoryTree ||
8888
toolName === ToolCallType.GetFileInfo
8989
) {
90-
updatedParams.path = normalizePath(params.path);
90+
updatedParams.path = await normalizePath(params.path);
9191
} else if (toolName === ToolCallType.ReadMultipleFiles) {
92-
updatedParams.paths = (params.paths || []).map(normalizePath);
92+
updatedParams.paths = await Promise.all(
93+
(params.paths || []).map((path: string) => {
94+
return normalizePath(path);
95+
}),
96+
);
9397
} else if (toolName === ToolCallType.MoveFile) {
94-
updatedParams.source = normalizePath(params.source);
95-
updatedParams.destination = normalizePath(params.destination);
98+
updatedParams.source = await normalizePath(params.source);
99+
updatedParams.destination = await normalizePath(params.destination);
96100
} else if (toolName === ToolCallType.SearchFiles) {
97-
updatedParams.path = normalizePath(params.path);
101+
updatedParams.path = await normalizePath(params.path);
98102
}
99103

100104
// Update the tool call with normalized paths

apps/agent-tars/src/renderer/src/components/FilePermissionModal/index.tsx

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,6 @@ import {
1010
} from '@nextui-org/react';
1111
import { IoWarningOutline } from 'react-icons/io5';
1212
import { ipcClient } from '@renderer/api';
13-
import {
14-
loadFileSystemSettings,
15-
saveFileSystemSettings,
16-
} from '@renderer/services/fileSystemSettings';
1713
import path from 'path-browserify';
1814
import { resolvePermission } from '@renderer/services/filePermissionService';
1915
import { useAppSettings } from '../LeftSidebar/Settings/useAppSettings';
@@ -35,12 +31,13 @@ export function FilePermissionModal({
3531
setIsProcessing(true);
3632
try {
3733
// Add this directory to allowed directories
38-
const settings = loadFileSystemSettings() || {
34+
const settings = (await ipcClient.getFileSystemSettings()) || {
3935
availableDirectories: [],
4036
};
37+
4138
if (!settings.availableDirectories.includes(directoryPath)) {
4239
settings.availableDirectories.push(directoryPath);
43-
saveFileSystemSettings(settings);
40+
await ipcClient.updateFileSystemSettings(settings);
4441
setSettings((appSettings) => {
4542
return {
4643
...appSettings,

apps/agent-tars/src/renderer/src/components/LeftSidebar/Settings/useAppSettings.ts

Lines changed: 12 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -7,22 +7,9 @@ import {
77
SearchSettings,
88
SearchProvider,
99
} from '@agent-infra/shared';
10-
import {
11-
loadLLMSettings,
12-
saveLLMSettings,
13-
} from '../../../services/llmSettings';
14-
import { updateLLMConfig } from '../../../api/llmConfig';
15-
import {
16-
loadFileSystemSettings,
17-
saveFileSystemSettings,
18-
} from '../../../services/fileSystemSettings';
1910
import { ipcClient } from '@renderer/api';
2011
import { atom, useAtom } from 'jotai';
2112
import toast from 'react-hot-toast';
22-
import {
23-
loadSearchSettings,
24-
saveSearchSettings,
25-
} from '../../../services/searchSettings';
2613

2714
const DEFAULT_MODEL_SETTINGS: ModelSettings = {
2815
provider: ModelProvider.OPENAI,
@@ -50,17 +37,18 @@ export const appSettingsAtom = atom<AppSettings>({
5037
export function useAppSettings() {
5138
const [settings, setSettings] = useAtom<AppSettings>(appSettingsAtom);
5239

53-
// Load settings from localStorage on mount
40+
// Load settings from store on mount
5441
useEffect(() => {
55-
const savedModelSettings = loadLLMSettings();
56-
const savedFileSystemSettings = loadFileSystemSettings();
57-
const savedSearchSettings = loadSearchSettings();
58-
59-
setSettings({
60-
model: savedModelSettings || DEFAULT_MODEL_SETTINGS,
61-
fileSystem: savedFileSystemSettings || DEFAULT_FILESYSTEM_SETTINGS,
62-
search: savedSearchSettings || DEFAULT_SEARCH_SETTINGS,
63-
});
42+
async function loadSettings() {
43+
const settings = await ipcClient.getSettings();
44+
45+
setSettings({
46+
model: settings.model || DEFAULT_MODEL_SETTINGS,
47+
fileSystem: settings.fileSystem || DEFAULT_FILESYSTEM_SETTINGS,
48+
search: settings.search || DEFAULT_SEARCH_SETTINGS,
49+
});
50+
}
51+
loadSettings();
6452
}, []);
6553

6654
const validateModelSettings = (
@@ -125,14 +113,7 @@ export function useAppSettings() {
125113

126114
try {
127115
// Save all settings
128-
saveLLMSettings(settings.model);
129-
await updateLLMConfig(settings.model);
130-
131-
saveFileSystemSettings(settings.fileSystem);
132-
await ipcClient.updateFileSystemConfig(settings.fileSystem);
133-
134-
saveSearchSettings(settings.search);
135-
await ipcClient.updateSearchConfig(settings.search);
116+
await ipcClient.updateAppSettings(settings);
136117

137118
toast.success('Settings saved successfully');
138119
return true;

apps/agent-tars/src/renderer/src/components/LeftSidebar/Settings/useModelSettings.ts

Lines changed: 6 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,7 @@
11
import { useState, useEffect } from 'react';
2-
import {
3-
loadLLMSettings,
4-
saveLLMSettings,
5-
} from '../../../services/llmSettings';
62
import { updateLLMConfig } from '../../../api/llmConfig';
73
import { ModelProvider, ModelSettings } from '@agent-infra/shared';
4+
import { ipcClient } from '@renderer/api';
85

96
export function useModelSettings() {
107
const [settings, setSettings] = useState<ModelSettings>({
@@ -15,21 +12,19 @@ export function useModelSettings() {
1512
endpoint: '',
1613
});
1714

18-
// Load settings from localStorage on mount
15+
// Load settings from store on mount
1916
useEffect(() => {
20-
const savedSettings = loadLLMSettings();
21-
if (savedSettings) {
22-
setSettings(savedSettings);
17+
async function loadSettings() {
18+
const settings = await ipcClient.getSettings();
19+
setSettings(settings.model);
2320
}
21+
loadSettings();
2422
}, []);
2523

2624
const saveSettings = async () => {
2725
// Save settings directly without modifying the model field
2826
const finalSettings = { ...settings };
2927

30-
// Save to localStorage
31-
saveLLMSettings(finalSettings);
32-
3328
// Update LLM configuration in main process
3429
await updateLLMConfig(finalSettings);
3530
};

apps/agent-tars/src/renderer/src/hooks/useFileSystemSettings.ts

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,5 @@
11
import { useEffect, useState } from 'react';
22
import { ipcClient } from '@renderer/api';
3-
import {
4-
loadFileSystemSettings,
5-
saveFileSystemSettings,
6-
} from '@renderer/services/fileSystemSettings';
73

84
export function useFileSystemSettings() {
95
const [initialized, setInitialized] = useState(false);
@@ -14,12 +10,15 @@ export function useFileSystemSettings() {
1410
// Get current allowed directories from main process
1511
const allowedDirectories = await ipcClient.getAllowedDirectories();
1612

17-
// Load settings from localStorage
18-
const settings = loadFileSystemSettings();
13+
// Load settings from store
14+
const appSettings = await ipcClient.getSettings();
15+
const settings = appSettings?.fileSystem;
1916

2017
// If no settings exist, create them with the allowed directories
2118
if (!settings) {
22-
saveFileSystemSettings({ availableDirectories: allowedDirectories });
19+
await ipcClient.updateFileSystemSettings({
20+
availableDirectories: allowedDirectories,
21+
});
2322
} else {
2423
// Make sure the settings match the main process
2524
const updatedSettings = {
@@ -33,7 +32,7 @@ export function useFileSystemSettings() {
3332
};
3433

3534
// Save updated settings
36-
saveFileSystemSettings(updatedSettings);
35+
await ipcClient.updateFileSystemSettings(updatedSettings);
3736

3837
// Update main process if needed
3938
if (

apps/agent-tars/src/renderer/src/services/filePermissionService.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,14 +18,14 @@ export const pendingPermissionRequestAtom = atom<PermissionRequest | null>(
1818
* @param filePath The file path to normalize
1919
* @returns Normalized path (absolute)
2020
*/
21-
export function normalizePath(filePath: string): string {
21+
export async function normalizePath(filePath: string): Promise<string> {
2222
// If it's already an absolute path, return it
2323
if (filePath.startsWith('/')) {
2424
return filePath;
2525
}
2626

2727
// Otherwise, make it relative to the default directory
28-
const defaultDir = getDefaultDirectory();
28+
const defaultDir = await getDefaultDirectory();
2929
if (!defaultDir) {
3030
throw new Error('No default directory configured');
3131
}
@@ -40,10 +40,10 @@ export function normalizePath(filePath: string): string {
4040
*/
4141
export async function checkPathPermission(filePath: string): Promise<boolean> {
4242
// Normalize path first
43-
const normalizedPath = normalizePath(filePath);
43+
const normalizedPath = await normalizePath(filePath);
4444

4545
// If path is allowed, return immediately
46-
if (isPathAllowed(normalizedPath)) {
46+
if (await isPathAllowed(normalizedPath)) {
4747
return true;
4848
}
4949

apps/agent-tars/src/renderer/src/services/fileSystemSettings.ts

Lines changed: 5 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,36 +1,15 @@
1-
import { FileSystemSettings } from '@agent-infra/shared';
1+
import { ipcClient } from '@renderer/api';
22

3-
const FILE_SYSTEM_SETTINGS_KEY = 'omega-filesystem-settings';
4-
5-
export function loadFileSystemSettings(): FileSystemSettings | null {
6-
try {
7-
const settingsJson = localStorage.getItem(FILE_SYSTEM_SETTINGS_KEY);
8-
if (!settingsJson) return null;
9-
return JSON.parse(settingsJson) as FileSystemSettings;
10-
} catch (error) {
11-
console.error('Failed to load file system settings:', error);
12-
return null;
13-
}
14-
}
15-
16-
export function saveFileSystemSettings(settings: FileSystemSettings): void {
17-
try {
18-
localStorage.setItem(FILE_SYSTEM_SETTINGS_KEY, JSON.stringify(settings));
19-
} catch (error) {
20-
console.error('Failed to save file system settings:', error);
21-
}
22-
}
23-
24-
export function getDefaultDirectory(): string | null {
25-
const settings = loadFileSystemSettings();
3+
export async function getDefaultDirectory(): Promise<string | null> {
4+
const settings = await ipcClient.getFileSystemSettings();
265
if (settings && settings.availableDirectories.length > 0) {
276
return settings.availableDirectories[0];
287
}
298
return null;
309
}
3110

32-
export function isPathAllowed(path: string): boolean {
33-
const settings = loadFileSystemSettings();
11+
export async function isPathAllowed(path: string): Promise<boolean> {
12+
const settings = await ipcClient.getFileSystemSettings();
3413
if (!settings || !settings.availableDirectories.length) return false;
3514

3615
// If path is not absolute, it's allowed (will be relative to default dir)

apps/agent-tars/src/renderer/src/services/llmSettings.ts

Lines changed: 0 additions & 29 deletions
This file was deleted.

0 commit comments

Comments
 (0)