diff --git a/electron/main.js b/electron/main.js
index c01c61a8..dba35ec2 100644
--- a/electron/main.js
+++ b/electron/main.js
@@ -1,4 +1,4 @@
-const { app, components, BrowserWindow, ipcMain, shell, session } = require('electron');
+const { app, components, BrowserWindow, ipcMain, shell, session, dialog } = require('electron');
let autoUpdater;
try { autoUpdater = require('electron-updater').autoUpdater; } catch (_) {}
const path = require('path');
@@ -558,3 +558,8 @@ ipcMain.handle('open-external', (_event, url) => {
shell.openExternal(url);
}
});
+
+ipcMain.handle('show-open-dialog', async (_event, options) => {
+ const win = BrowserWindow.getFocusedWindow();
+ return dialog.showOpenDialog(win || BrowserWindow.getAllWindows()[0], options || {});
+});
diff --git a/electron/preload.js b/electron/preload.js
index 534c540f..f29e9568 100644
--- a/electron/preload.js
+++ b/electron/preload.js
@@ -13,6 +13,7 @@ const { contextBridge, ipcRenderer } = require('electron');
getAppVersion: () => ipcRenderer.invoke('get-app-version'),
openExternal: (url) => ipcRenderer.invoke('open-external', url),
capturePage: (rect) => ipcRenderer.invoke('capture-page', rect),
+ showOpenDialog: (options) => ipcRenderer.invoke('show-open-dialog', options),
getUpdateStatus: () => ipcRenderer.invoke('get-update-status'),
checkForUpdates: () => ipcRenderer.invoke('check-for-updates'),
downloadUpdate: () => ipcRenderer.invoke('download-update'),
diff --git a/frontend/src/app/Main.tsx b/frontend/src/app/Main.tsx
index 383ce02a..d8c3d80b 100644
--- a/frontend/src/app/Main.tsx
+++ b/frontend/src/app/Main.tsx
@@ -22,7 +22,6 @@ import Tools from './pages/Tools/Tools';
import Modes from './pages/Modes/Modes';
import Views from './pages/Views/Views';
import Customization from './pages/Customization/Customization';
-import Analytics from './pages/Analytics/Analytics';
import OnboardingModal from './components/OnboardingModal';
import { useKeyboardShortcuts } from '@/shared/hooks/useKeyboardShortcuts';
import KeyboardShortcutsHelp from './components/KeyboardShortcutsHelp';
@@ -109,7 +108,6 @@ const ThemedApp: React.FC = () => {
} />
} />
} />
- } />
diff --git a/frontend/src/app/components/DirectoryBrowser.tsx b/frontend/src/app/components/DirectoryBrowser.tsx
deleted file mode 100644
index 8b64e986..00000000
--- a/frontend/src/app/components/DirectoryBrowser.tsx
+++ /dev/null
@@ -1,197 +0,0 @@
-import React, { useState, useEffect, useCallback } from 'react';
-import Dialog from '@mui/material/Dialog';
-import DialogTitle from '@mui/material/DialogTitle';
-import DialogContent from '@mui/material/DialogContent';
-import DialogActions from '@mui/material/DialogActions';
-import Button from '@mui/material/Button';
-import Box from '@mui/material/Box';
-import Typography from '@mui/material/Typography';
-import TextField from '@mui/material/TextField';
-import { useClaudeTokens } from '@/shared/styles/ThemeContext';
-import { BrowseResult } from '@/shared/state/settingsSlice';
-import { API_BASE } from '@/shared/config';
-import DirectoryFileList from './DirectoryFileList';
-
-const SETTINGS_API = `${API_BASE}/settings`;
-
-export interface ContextPath {
- path: string;
- type: 'file' | 'directory';
-}
-
-interface DirectoryBrowserProps {
- open: boolean;
- onClose: () => void;
- onSelect: (item: ContextPath) => void;
- initialPath?: string;
-}
-
-const DirectoryBrowser: React.FC = ({ open, onClose, onSelect, initialPath }) => {
- const c = useClaudeTokens();
- const [browseData, setBrowseData] = useState(null);
- const [loading, setLoading] = useState(false);
- const [error, setError] = useState(null);
- const [manualPath, setManualPath] = useState('');
- const [selected, setSelected] = useState<{ name: string; type: 'file' | 'directory' } | null>(null);
-
- const browse = useCallback(async (path: string) => {
- setLoading(true);
- setError(null);
- setSelected(null);
- try {
- const res = await fetch(`${SETTINGS_API}/browse-directories?path=${encodeURIComponent(path)}`);
- if (!res.ok) {
- const data = await res.json();
- throw new Error(data.detail || 'Failed to browse');
- }
- const data: BrowseResult = await res.json();
- setBrowseData(data);
- setManualPath(data.current);
- } catch (e: any) {
- setError(e.message);
- } finally {
- setLoading(false);
- }
- }, []);
-
- useEffect(() => {
- if (open) {
- setSelected(null);
- browse(initialPath || '');
- }
- }, [open, initialPath, browse]);
-
- const handleNavigate = (dir: string) => {
- if (browseData) browse(`${browseData.current}/${dir}`);
- };
-
- const handleGoUp = () => {
- if (browseData?.parent) browse(browseData.parent);
- };
-
- const handleManualGo = () => {
- if (manualPath.trim()) browse(manualPath.trim());
- };
-
- const handleKeyDown = (e: React.KeyboardEvent) => {
- if (e.key === 'Enter') handleManualGo();
- };
-
- const handleConfirm = () => {
- if (!browseData) return;
- if (selected) {
- const fullPath = `${browseData.current}/${selected.name}`;
- onSelect({ path: fullPath, type: selected.type });
- } else {
- onSelect({ path: browseData.current, type: 'directory' });
- }
- onClose();
- };
-
- return (
-
- );
-};
-
-export default DirectoryBrowser;
diff --git a/frontend/src/app/components/DirectoryFileList.tsx b/frontend/src/app/components/DirectoryFileList.tsx
deleted file mode 100644
index b0c14964..00000000
--- a/frontend/src/app/components/DirectoryFileList.tsx
+++ /dev/null
@@ -1,177 +0,0 @@
-import React from 'react';
-import Box from '@mui/material/Box';
-import Typography from '@mui/material/Typography';
-import List from '@mui/material/List';
-import ListItemButton from '@mui/material/ListItemButton';
-import ListItemIcon from '@mui/material/ListItemIcon';
-import ListItemText from '@mui/material/ListItemText';
-import CircularProgress from '@mui/material/CircularProgress';
-import IconButton from '@mui/material/IconButton';
-import Breadcrumbs from '@mui/material/Breadcrumbs';
-import Link from '@mui/material/Link';
-import FolderIcon from '@mui/icons-material/Folder';
-import InsertDriveFileOutlinedIcon from '@mui/icons-material/InsertDriveFileOutlined';
-import ArrowUpwardIcon from '@mui/icons-material/ArrowUpward';
-import { useClaudeTokens } from '@/shared/styles/ThemeContext';
-import { BrowseResult } from '@/shared/state/settingsSlice';
-
-interface DirectoryFileListProps {
- browseData: BrowseResult | null;
- selected: { name: string; type: 'file' | 'directory' } | null;
- loading: boolean;
- error: string | null;
- onBrowse: (path: string) => void;
- onNavigate: (dir: string) => void;
- onGoUp: () => void;
- onSelect: (item: { name: string; type: 'file' | 'directory' } | null) => void;
-}
-
-const DirectoryFileList: React.FC = ({
- browseData, selected, loading, error, onBrowse, onNavigate, onGoUp, onSelect,
-}) => {
- const c = useClaudeTokens();
- const pathSegments = browseData?.current.split('/').filter(Boolean) ?? [];
- const hasEntries = (browseData?.directories.length ?? 0) + (browseData?.files.length ?? 0) > 0;
-
- return (
- <>
- {browseData && (
-
-
-
-
-
- onBrowse('/')}
- sx={{ color: c.text.tertiary, fontSize: '0.78rem' }}
- >
- /
-
- {pathSegments.map((seg, i) => {
- const fullPath = '/' + pathSegments.slice(0, i + 1).join('/');
- const isLast = i === pathSegments.length - 1;
- return isLast ? (
-
- {seg}
-
- ) : (
- onBrowse(fullPath)}
- sx={{ color: c.text.tertiary, fontSize: '0.78rem' }}
- >
- {seg}
-
- );
- })}
-
-
- )}
-
- {error && (
-
- {error}
-
- )}
-
-
- {loading ? (
-
-
-
- ) : !hasEntries ? (
-
-
- Empty directory
-
-
- ) : (
-
- {browseData?.directories.map((dir) => (
- onNavigate(dir)}
- onClick={() =>
- onSelect(
- selected?.name === dir && selected.type === 'directory' ? null : { name: dir, type: 'directory' },
- )
- }
- sx={{
- py: 0.75,
- '&.Mui-selected': { bgcolor: `${c.accent.primary}0c` },
- '&:hover': { bgcolor: `${c.accent.primary}08` },
- }}
- >
-
-
-
-
-
- ))}
- {browseData?.files.map((file) => (
-
- onSelect(
- selected?.name === file && selected.type === 'file' ? null : { name: file, type: 'file' },
- )
- }
- sx={{
- py: 0.75,
- '&.Mui-selected': { bgcolor: `${c.accent.primary}0c` },
- '&:hover': { bgcolor: `${c.accent.primary}08` },
- }}
- >
-
-
-
-
-
- ))}
-
- )}
-
- >
- );
-};
-
-export default DirectoryFileList;
diff --git a/frontend/src/app/pages/AgentChat/AgentChat.tsx b/frontend/src/app/pages/AgentChat/AgentChat.tsx
index ad89fb26..bd444956 100644
--- a/frontend/src/app/pages/AgentChat/AgentChat.tsx
+++ b/frontend/src/app/pages/AgentChat/AgentChat.tsx
@@ -10,7 +10,7 @@ import OpenSwarmComposer from './composer/OpenSwarmComposer';
import { useAgentChat } from './hooks/useAgentChat';
import { useOpenSwarmRuntime, type ComposerExtras, type DispatchableMessage } from './runtime/useOpenSwarmRuntime';
import { toolkit } from './toolkit';
-import type { ContextPath } from '@/app/components/DirectoryBrowser';
+import type { ContextPath } from '@/shared/state/agentsTypes';
import { useClaudeTokens } from '@/shared/styles/ThemeContext';
interface AgentChatProps {
diff --git a/frontend/src/app/pages/AgentChat/AttachmentChips.tsx b/frontend/src/app/pages/AgentChat/AttachmentChips.tsx
index 4564243e..cc7c3d87 100644
--- a/frontend/src/app/pages/AgentChat/AttachmentChips.tsx
+++ b/frontend/src/app/pages/AgentChat/AttachmentChips.tsx
@@ -7,7 +7,7 @@ import InsertDriveFileOutlinedIcon from '@mui/icons-material/InsertDriveFileOutl
import AdsClickIcon from '@mui/icons-material/AdsClick';
import { getToolGroupIcon } from '@/app/components/CommandPicker';
import type { SelectedElement } from '@/app/components/ElementSelectionContext';
-import type { ContextPath } from '@/app/components/DirectoryBrowser';
+import type { ContextPath } from '@/shared/state/agentsTypes';
export interface ForcedToolGroup {
label: string;
diff --git a/frontend/src/app/pages/AgentChat/ChatInput.tsx b/frontend/src/app/pages/AgentChat/ChatInput.tsx
index 50d60106..f6552da2 100644
--- a/frontend/src/app/pages/AgentChat/ChatInput.tsx
+++ b/frontend/src/app/pages/AgentChat/ChatInput.tsx
@@ -5,7 +5,7 @@ import CircularProgress from '@mui/material/CircularProgress';
import AttachFileIcon from '@mui/icons-material/AttachFile';
import CommandPicker from '@/app/components/CommandPicker';
import { useElementSelection } from '@/app/components/ElementSelectionContext';
-import type { ContextPath } from '@/app/components/DirectoryBrowser';
+import type { ContextPath } from '@/shared/state/agentsTypes';
import { type AttachedSkill, type TriggerState, EMPTY_TRIGGER, serializeEditorContent } from '@/app/components/richEditorUtils';
import { useAppSelector } from '@/shared/hooks';
import { useClaudeTokens } from '@/shared/styles/ThemeContext';
diff --git a/frontend/src/app/pages/AgentChat/composer/OpenSwarmComposer.tsx b/frontend/src/app/pages/AgentChat/composer/OpenSwarmComposer.tsx
index 7b358afb..11d49fb2 100644
--- a/frontend/src/app/pages/AgentChat/composer/OpenSwarmComposer.tsx
+++ b/frontend/src/app/pages/AgentChat/composer/OpenSwarmComposer.tsx
@@ -4,7 +4,7 @@ import { LexicalComposerInput } from '@assistant-ui/react-lexical';
import type { Unstable_MentionItem } from '@assistant-ui/core';
import { useAppSelector } from '@/shared/hooks';
import type { ComposerExtras } from '../runtime/useOpenSwarmRuntime';
-import type { ContextPath } from '@/app/components/DirectoryBrowser';
+import type { ContextPath } from '@/shared/state/agentsTypes';
import { useOpenSwarmMentionAdapter, type MentionItemMetadata } from './OpenSwarmMentionAdapter';
import { useComposerAttachments } from './useComposerAttachments';
import { MentionSelectOverride, MentionPopover, ComposerAttachmentChips } from './ComposerParts';
diff --git a/frontend/src/app/pages/AgentChat/composer/useComposerAttachments.ts b/frontend/src/app/pages/AgentChat/composer/useComposerAttachments.ts
index 3f451ad8..6a74db4c 100644
--- a/frontend/src/app/pages/AgentChat/composer/useComposerAttachments.ts
+++ b/frontend/src/app/pages/AgentChat/composer/useComposerAttachments.ts
@@ -1,6 +1,6 @@
import { useState, useCallback, useRef } from 'react';
import { API_BASE } from '@/shared/config';
-import type { ContextPath } from '@/app/components/DirectoryBrowser';
+import type { ContextPath } from '@/shared/state/agentsTypes';
interface AttachedImage {
data: string;
diff --git a/frontend/src/app/pages/AgentChat/hooks/useChatSubmit.ts b/frontend/src/app/pages/AgentChat/hooks/useChatSubmit.ts
index 8c6a5432..ca134667 100644
--- a/frontend/src/app/pages/AgentChat/hooks/useChatSubmit.ts
+++ b/frontend/src/app/pages/AgentChat/hooks/useChatSubmit.ts
@@ -4,7 +4,7 @@ import { useElementSelection, type SelectedElement } from '@/app/components/Elem
import { getClipboardCards, clearClipboard } from '@/shared/dashboardClipboard';
import { getWebview } from '@/shared/browserRegistry';
import { API_BASE } from '@/shared/config';
-import type { ContextPath } from '@/app/components/DirectoryBrowser';
+import type { ContextPath } from '@/shared/state/agentsTypes';
import {
SKILL_PILL_ATTR, type AttachedSkill, createSkillPillElement,
serializeEditorContent, type TriggerState, detectEditorTrigger,
diff --git a/frontend/src/app/pages/Analytics/Analytics.tsx b/frontend/src/app/pages/Analytics/Analytics.tsx
deleted file mode 100644
index 1c10703e..00000000
--- a/frontend/src/app/pages/Analytics/Analytics.tsx
+++ /dev/null
@@ -1,63 +0,0 @@
-import React from 'react';
-import Box from '@mui/material/Box';
-import Typography from '@mui/material/Typography';
-import Paper from '@mui/material/Paper';
-import { useClaudeTokens } from '@/shared/styles/ThemeContext';
-
-const Analytics: React.FC = () => {
- const c = useClaudeTokens();
-
- return (
-
-
-
- Analytics
-
-
-
-
-
-
-
- Analytics powered by PostHog
-
-
- Usage data is automatically collected — sessions, costs, tool usage, model distribution, and task categories.
- All data is anonymous and can be disabled in Settings.
-
-
-
- {[
- { label: 'Sessions & Usage', desc: 'How often agents are launched, session duration, completion rates' },
- { label: 'Cost Tracking', desc: 'Spend by model, provider, and time period' },
- { label: 'Task Categories', desc: 'What users do — coding, email, research, social, browsing' },
- { label: 'Model Distribution', desc: 'Which models and providers are most popular' },
- { label: 'Tool Usage', desc: 'Most used MCP tools, execution times, approval rates' },
- { label: 'Retention & Funnels', desc: 'User engagement, feature adoption, onboarding flow' },
- ].map((item) => (
-
-
- {item.label}
-
-
- {item.desc}
-
-
- ))}
-
-
-
-
- );
-};
-
-export default Analytics;
diff --git a/frontend/src/app/pages/Dashboard/hooks/useToolbarActions.ts b/frontend/src/app/pages/Dashboard/hooks/useToolbarActions.ts
index d23d6a53..a89c21d6 100644
--- a/frontend/src/app/pages/Dashboard/hooks/useToolbarActions.ts
+++ b/frontend/src/app/pages/Dashboard/hooks/useToolbarActions.ts
@@ -23,7 +23,7 @@ import {
BrowserCardPosition
} from '@/shared/state/dashboardLayoutSlice';
import { GENERATE_DASHBOARD_NAME } from '@/shared/backend-bridge/apps/dashboards';
-import type { ContextPath } from '@/app/components/DirectoryBrowser';
+import type { ContextPath } from '@/shared/state/agentsTypes';
import type { CanvasActions } from '../useCanvasControls';
interface ToolbarDeps {
diff --git a/frontend/src/app/pages/Dashboard/toolbarShared.tsx b/frontend/src/app/pages/Dashboard/toolbarShared.tsx
index d9aafcec..5d9df182 100644
--- a/frontend/src/app/pages/Dashboard/toolbarShared.tsx
+++ b/frontend/src/app/pages/Dashboard/toolbarShared.tsx
@@ -3,7 +3,7 @@ import Tooltip, { tooltipClasses } from '@mui/material/Tooltip';
import { styled } from '@mui/material/styles';
import { motion } from 'framer-motion';
import type { ClaudeTokens } from '@/shared/styles/claudeTokens';
-import type { ContextPath } from '@/app/components/DirectoryBrowser';
+import type { ContextPath } from '@/shared/state/agentsTypes';
export interface Props {
inputOpen: boolean;
diff --git a/frontend/src/app/pages/Dashboard/useDashboardToolbar.ts b/frontend/src/app/pages/Dashboard/useDashboardToolbar.ts
index e3d3831b..c288b73f 100644
--- a/frontend/src/app/pages/Dashboard/useDashboardToolbar.ts
+++ b/frontend/src/app/pages/Dashboard/useDashboardToolbar.ts
@@ -1,5 +1,5 @@
import { useState, useRef, useEffect, useCallback, useMemo } from 'react';
-import type { ContextPath } from '@/app/components/DirectoryBrowser';
+import type { ContextPath } from '@/shared/state/agentsTypes';
import { useElementSelection } from '@/app/components/ElementSelectionContext';
import { useClaudeTokens } from '@/shared/styles/ThemeContext';
import { useAppDispatch, useAppSelector } from '@/shared/hooks';
diff --git a/frontend/src/app/pages/Modes/ModeFormDialog.tsx b/frontend/src/app/pages/Modes/ModeFormDialog.tsx
index b03d5974..bd1b850a 100644
--- a/frontend/src/app/pages/Modes/ModeFormDialog.tsx
+++ b/frontend/src/app/pages/Modes/ModeFormDialog.tsx
@@ -16,7 +16,6 @@ import FolderOpenIcon from '@mui/icons-material/FolderOpen';
import RestoreIcon from '@mui/icons-material/Restore';
import { Mode } from '@/shared/state/modesSlice';
import RichPromptEditor from '@/app/components/RichPromptEditor';
-import DirectoryBrowser from '@/app/components/DirectoryBrowser';
import { ModeForm, ICON_MAP, ICON_OPTIONS, COLOR_OPTIONS } from './modesConstants';
import ToolsSelector from './ToolsSelector';
@@ -32,15 +31,14 @@ interface ModeFormDialogProps {
onReset: () => void;
otherModes: Mode[];
mcpToolNames: string[];
- browseOpen: boolean;
- setBrowseOpen: React.Dispatch>;
+ browseFolder: () => void;
c: any;
}
const ModeFormDialog: React.FC = ({
open, onClose, editingId, editingIsBuiltin, hasDiverged,
form, setForm, onSave, onReset, otherModes, mcpToolNames,
- browseOpen, setBrowseOpen, c,
+ browseFolder, c,
}) => (
<>
-
- setBrowseOpen(false)}
- onSelect={(item) => setForm({ ...form, default_folder: item.path })}
- initialPath={form.default_folder || ''}
- />
>
);
diff --git a/frontend/src/app/pages/Modes/Modes.tsx b/frontend/src/app/pages/Modes/Modes.tsx
index 29183d8e..2202d3d8 100644
--- a/frontend/src/app/pages/Modes/Modes.tsx
+++ b/frontend/src/app/pages/Modes/Modes.tsx
@@ -15,7 +15,7 @@ const Modes: React.FC = () => {
const {
modes, items, loading,
dialogOpen, setDialogOpen, editingId,
- form, setForm, browseOpen, setBrowseOpen,
+ form, setForm, browseFolder,
openCreate, openEdit, handleSave, handleDelete,
editingIsBuiltin, hasDiverged, handleReset,
otherModes, mcpToolNames,
@@ -99,8 +99,7 @@ const Modes: React.FC = () => {
onReset={handleReset}
otherModes={otherModes}
mcpToolNames={mcpToolNames}
- browseOpen={browseOpen}
- setBrowseOpen={setBrowseOpen}
+ browseFolder={browseFolder}
c={c}
/>
diff --git a/frontend/src/app/pages/Modes/hooks/useModes.ts b/frontend/src/app/pages/Modes/hooks/useModes.ts
index 491dd900..1597e360 100644
--- a/frontend/src/app/pages/Modes/hooks/useModes.ts
+++ b/frontend/src/app/pages/Modes/hooks/useModes.ts
@@ -27,7 +27,15 @@ export function useModes() {
const [dialogOpen, setDialogOpen] = useState(false);
const [editingId, setEditingId] = useState(null);
const [form, setForm] = useState(emptyForm);
- const [browseOpen, setBrowseOpen] = useState(false);
+ const browseFolder = async () => {
+ const result = await (window as any).openswarm?.showOpenDialog({
+ properties: ['openDirectory'],
+ defaultPath: form.default_folder || undefined,
+ });
+ if (result && !result.canceled && result.filePaths?.length > 0) {
+ setForm((prev) => ({ ...prev, default_folder: result.filePaths[0] }));
+ }
+ };
useEffect(() => {
dispatch(LIST_MODES());
@@ -132,8 +140,7 @@ export function useModes() {
editingId,
form,
setForm,
- browseOpen,
- setBrowseOpen,
+ browseFolder,
openCreate,
openEdit,
handleSave,
diff --git a/frontend/src/app/pages/Settings/GeneralTab.tsx b/frontend/src/app/pages/Settings/GeneralTab.tsx
index 4202860e..2567bf97 100644
--- a/frontend/src/app/pages/Settings/GeneralTab.tsx
+++ b/frontend/src/app/pages/Settings/GeneralTab.tsx
@@ -17,7 +17,7 @@ import AboutSection from './AboutSection';
import type { UseSettingsReturn } from './hooks/useSettings';
const GeneralTab: React.FC<{ s: UseSettingsReturn }> = ({ s }) => {
- const { form, setForm, c, dispatch, modesList, setBrowseOpen,
+ const { form, setForm, c, dispatch, modesList, browseFolder,
fieldSx, sectionSx, rowSx, rowLastSx, inlineRowSx, inlineRowLastSx, labelSx, descSx } = s;
return (
@@ -88,7 +88,7 @@ const GeneralTab: React.FC<{ s: UseSettingsReturn }> = ({ s }) => {
/>
)}
- setBrowseOpen(false)}
- onSelect={(item) => setForm({ ...form, default_folder: item.path })}
- initialPath={form.default_folder ?? ''}
- />
('general');
const [form, setForm] = useState({ ...settings });
const [showApiKey, setShowApiKey] = useState(false);
- const [browseOpen, setBrowseOpen] = useState(false);
const [saved, setSaved] = useState(false);
const [recordingShortcut, setRecordingShortcut] = useState(false);
const [confirmDiscard, setConfirmDiscard] = useState(false);
@@ -68,6 +67,15 @@ export function useSettings() {
try { await (window as any).openswarm?.downloadUpdate(); } catch {}
};
const handleInstallUpdate = () => { (window as any).openswarm?.installUpdate(); };
+ const browseFolder = async () => {
+ const result = await (window as any).openswarm?.showOpenDialog({
+ properties: ['openDirectory'],
+ defaultPath: form.default_folder || undefined,
+ });
+ if (result && !result.canceled && result.filePaths?.length > 0) {
+ setForm({ ...form, default_folder: result.filePaths[0] });
+ }
+ };
const fieldSx = { '& .MuiOutlinedInput-root': { fontSize: '0.85rem' } };
const sectionSx = { fontSize: '0.7rem', fontWeight: 600, letterSpacing: '0.06em', textTransform: 'uppercase' as const, color: c.text.tertiary, mb: 0.5, mt: 0.5 };
const rowSx = { py: 2, borderBottom: `1px solid ${c.border.subtle}` };
@@ -79,7 +87,7 @@ export function useSettings() {
return {
c, dispatch, open, settings, modesList,
activeTab, setActiveTab, form, setForm,
- showApiKey, setShowApiKey, browseOpen, setBrowseOpen,
+ showApiKey, setShowApiKey, browseFolder,
saved, setSaved, recordingShortcut, setRecordingShortcut,
confirmDiscard, setConfirmDiscard, showApiHelp, setShowApiHelp,
hasChanges, handleSave, handleRequestClose, handleConfirmDiscard,
diff --git a/frontend/src/shared/state/agentsTypes.ts b/frontend/src/shared/state/agentsTypes.ts
index 861ed071..eb525b82 100644
--- a/frontend/src/shared/state/agentsTypes.ts
+++ b/frontend/src/shared/state/agentsTypes.ts
@@ -81,6 +81,11 @@ export interface AgentConfig {
dashboard_id?: string;
}
+export interface ContextPath {
+ path: string;
+ type: 'file' | 'directory';
+}
+
export interface SendMessagePayload {
sessionId: string;
prompt: string;
@@ -88,7 +93,7 @@ export interface SendMessagePayload {
model?: string;
provider?: string;
images?: Array<{ data: string; media_type: string }>;
- contextPaths?: Array<{ path: string; type: 'file' | 'directory' }>;
+ contextPaths?: Array;
forcedTools?: string[];
attachedSkills?: Array<{ id: string; name: string; content: string }>;
hidden?: boolean;
@@ -103,7 +108,7 @@ export interface LaunchAndSendPayload {
model: string;
provider?: string;
images?: Array<{ data: string; media_type: string }>;
- contextPaths?: Array<{ path: string; type: 'file' | 'directory' }>;
+ contextPaths?: Array;
forcedTools?: string[];
attachedSkills?: Array<{ id: string; name: string; content: string }>;
expand?: boolean;
diff --git a/frontend/src/shared/state/settingsSlice.ts b/frontend/src/shared/state/settingsSlice.ts
index b01800dd..a02b1e82 100644
--- a/frontend/src/shared/state/settingsSlice.ts
+++ b/frontend/src/shared/state/settingsSlice.ts
@@ -23,13 +23,6 @@ export const DEFAULT_SYSTEM_PROMPT =
`make reasonable assumptions and act. If you need to ask, use the AskUserQuestion tool.\n` +
`Do not over-explain what you are about to do. Just do it and show the results.`;
-export interface BrowseResult {
- current: string;
- parent: string | null;
- directories: string[];
- files: string[];
-}
-
interface SettingsState {
data: AppSettings;
loading: boolean;