Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,12 @@ and versions follow [Semantic Versioning](https://semver.org/).
## [Unreleased]

### Added
- **Backups and restore:** Settings > Backups backs up everything Sentient keeps (chats, memory, tasks, settings,
skills and files) to one file, in a folder you pick, by hand or every day or week. Restore one from the list or from
a file: you see what is in it and confirm, Sentient keeps a snapshot of what you have now, then restarts with the
backup. Passwords, API keys and sign-ins stay in your computer's keychain and are never in a backup; after a restore
Sentient lists the ones to sign in to again. Sentient also takes a snapshot on its own before it updates its
database, before a Hermes import and before a restore, keeps the last five, and any of them can be restored.
- **One local model job at a time, your chats first:** a local Ollama model now works on one thing at a time, so
background work no longer pushes it off the graphics card and slows your chat to a crawl. Your chat always goes
next; tasks, suggestions, memory upkeep and chat titles wait while you are chatting (and for 30 seconds after), and
Expand Down
12 changes: 9 additions & 3 deletions desktop/electron/main/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import type {
DictationStatus,
NativeNotification,
OpenPathTarget,
PickFilesOptions,
ShellPrefs,
ShortcutId
} from '../../src/types/bridge'
Expand Down Expand Up @@ -361,15 +362,20 @@ function registerIpc(): void {
platform: process.platform,
arch: process.arch
}))
ipcMain.handle(CH.pickFiles, async (_e, options?: { multiple?: boolean; directory?: boolean }) => {
ipcMain.handle(CH.pickFiles, async (_e, options?: PickFilesOptions) => {
const parent = win ?? undefined
const props: Array<'openFile' | 'openDirectory' | 'multiSelections' | 'showHiddenFiles'> = options?.directory
? ['openDirectory', 'showHiddenFiles']
: ['openFile']
if (options?.multiple !== false) props.push('multiSelections')
const filters = Array.isArray(options?.filters)
? options.filters
.filter((f) => typeof f?.name === 'string' && Array.isArray(f.extensions))
.map((f) => ({ name: f.name, extensions: f.extensions.filter((x) => typeof x === 'string' && /^[a-z0-9]{1,10}$/i.test(x)) }))
: undefined
const result = parent
? await dialog.showOpenDialog(parent, { properties: props })
: await dialog.showOpenDialog({ properties: props })
? await dialog.showOpenDialog(parent, { properties: props, filters })
: await dialog.showOpenDialog({ properties: props, filters })
return result.canceled ? [] : result.filePaths
})
ipcMain.on(CH.readyForScreenshot, () => smokeRunner?.ready())
Expand Down
3 changes: 2 additions & 1 deletion desktop/electron/main/paths.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@ export const homePaths = {
logs: () => join(sentientHome(), 'logs'),
files: () => join(sentientHome(), 'files'),
workspace: () => join(sentientHome(), 'workspace'),
skills: () => join(sentientHome(), 'skills')
skills: () => join(sentientHome(), 'skills'),
backups: () => join(sentientHome(), 'backups')
}

/**
Expand Down
4 changes: 4 additions & 0 deletions desktop/src/features/settings/SchemaForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,10 @@ export const LABELS: Record<string, FieldLabel> = {
'models.background_quiet_s': { label: 'Background work waits after you chat', unit: 's' },
'models.background_on_battery': { label: 'Background work on battery' },
// tasks
'backups.schedule': { label: 'Back up automatically' },
'backups.keep': { label: 'Automatic backups to keep', unit: 'backups' },
'backups.snapshots_keep': { label: 'Snapshots to keep', unit: 'snapshots' },

'tasks.tick_seconds': { label: 'Scheduler check interval', unit: 's' },
'tasks.max_concurrent_runs': { label: 'Runs at the same time' },
'tasks.run_timeout_minutes': { label: 'Stop a run after', unit: 'min' },
Expand Down
2 changes: 2 additions & 0 deletions desktop/src/features/settings/SettingsPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { cn } from '@/lib/utils'
import { schemaMatches } from './SchemaForm'
import { SETTINGS_SECTIONS, sectionById } from './sections'
import { AdvancedSection } from './sections/Advanced'
import { BackupsSection } from './sections/Backups'
import { GeneralSection } from './sections/General'
import { ModelsSection } from './sections/Models'
import { PersonalitySection } from './sections/Personality'
Expand Down Expand Up @@ -36,6 +37,7 @@ const SECTION_COMPONENTS: Record<string, ComponentType<SectionProps>> = {
terminal: TerminalSection,
browser: BrowserSection,
subagents: SubagentsSection,
backups: BackupsSection,
advanced: AdvancedSection
}

Expand Down
9 changes: 9 additions & 0 deletions desktop/src/features/settings/sections.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import {
IconArchive,
IconBolt,
IconBrain,
IconChartBar,
Expand Down Expand Up @@ -145,6 +146,14 @@ export const SETTINGS_SECTIONS: SettingsSectionMeta[] = [
icon: IconChartBar,
keywords: ['tokens', 'cost', 'insights', 'statistics']
},
{
id: 'backups',
label: 'Backups',
description: 'Back up and restore your data, and snapshots taken before updates.',
icon: IconArchive,
keywords: ['backup', 'back up', 'restore', 'snapshot', 'export', 'copy', 'undo', 'schedule', 'new computer', 'move'],
schemaSections: ['backups']
},
{
id: 'advanced',
label: 'Advanced',
Expand Down
Loading
Loading