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 ( - - - Browse Files & Folders - - - - setManualPath(e.target.value)} - onKeyDown={handleKeyDown} - size="small" - fullWidth - placeholder="Type a path..." - sx={{ - '& .MuiOutlinedInput-root': { - bgcolor: c.bg.page, - fontSize: '0.85rem', - fontFamily: c.font.mono, - }, - }} - /> - - - - - - - - {selected - ? `Selected: ${selected.name}` - : 'Click to select, double-click folders to open'} - - - - - - - - ); -}; - -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;