From 3c8dc45b1d5be5de47b2b7e4c9262febaf8a9355 Mon Sep 17 00:00:00 2001 From: Rodrigo Gomes da Silva Date: Tue, 31 Mar 2026 18:47:46 -0300 Subject: [PATCH 01/33] feat: add persistent conversation feature with cross-platform file restoration Implement "Remember Conversation" toggle that persists chat sessions across app restarts using IndexedDB (idb-keyval). Three platform strategies: Electron file paths, Chromium FileSystemFileHandle, and fallback reselect for Firefox/Safari. New components: RestoreSessionModal, ReselectFileModal, Toast, Modal. Stores metadata, bookmarks, transcriptions, settings (~1MB). Never stores the ZIP file itself. --- AI_HANDOFF.md | 417 +++++ electron/main.cjs | 18 + electron/preload.cjs | 4 + messages/de.json | 21 +- messages/en.json | 20 +- messages/es.json | 21 +- messages/fr.json | 21 +- messages/it.json | 21 +- messages/ja.json | 21 +- messages/nl.json | 21 +- messages/pt.json | 21 +- messages/ru.json | 21 +- messages/zh.json | 21 +- package-lock.json | 1541 +++++++---------- package.json | 1 + src/app.css | 9 + src/app.d.ts | 8 + src/lib/bookmarks.svelte.ts | 5 + src/lib/components/ChatList.svelte | 31 + src/lib/components/Modal.svelte | 9 +- src/lib/components/ModalContent.svelte | 2 +- src/lib/components/ReselectFileModal.svelte | 157 ++ src/lib/components/RestoreSessionModal.svelte | 227 +++ src/lib/components/Toast.svelte | 104 ++ src/lib/components/index.ts | 2 + src/lib/persistence.svelte.ts | 610 +++++++ src/lib/transcription.svelte.ts | 37 + src/routes/+page.svelte | 475 ++++- 28 files changed, 2968 insertions(+), 898 deletions(-) create mode 100644 AI_HANDOFF.md create mode 100644 src/lib/components/ReselectFileModal.svelte create mode 100644 src/lib/components/RestoreSessionModal.svelte create mode 100644 src/lib/components/Toast.svelte create mode 100644 src/lib/persistence.svelte.ts diff --git a/AI_HANDOFF.md b/AI_HANDOFF.md new file mode 100644 index 0000000..c898f45 --- /dev/null +++ b/AI_HANDOFF.md @@ -0,0 +1,417 @@ +# AI Handoff: Persistent Conversation Feature Implementation + +## Problem Statement +We're implementing a "Remember Conversation" feature that allows users to persist chat sessions across app restarts. **Current Issue**: The feature still shows "Please Re-select File" modal every time, even after supposedly storing file handles or paths. + +## Repository Context +- **Repo**: rodrigogs/whats-reader +- **Branch**: copilot/add-persistent-conversation-feature +- **Tech Stack**: SvelteKit (Svelte 5 with runes), TypeScript, Electron, IndexedDB (via idb-keyval) +- **Build**: Hybrid app - runs as both web app (GitHub Pages) and Electron desktop app + +## What Has Been Implemented + +### 1. Core Files Created + +#### `src/lib/persistence.svelte.ts` (460+ lines) +Core persistence module with: +- `PersistedChatMetadata` interface for storing chat metadata +- `savePersistedChat()` - Save a chat for persistence +- `getPersistedChats()` - Get all persisted chats +- `removePersistedChat()` - Remove a persisted chat +- `updatePersistedChat()` - Update existing persisted chat metadata +- `restoreChat()` - Attempt to restore a chat (handles all platform logic) +- `validateRestoredFile()` - Validate file matches saved metadata +- File handle storage/retrieval functions +- Permission verification functions + +#### `src/lib/components/RestoreSessionModal.svelte` +Modal shown on app load when persisted chats exist: +- Lists all persisted chats sorted by updatedAt +- Checkboxes to select which chats to restore +- "Restore Selected" and "Start Fresh" buttons +- "Don't show this again" checkbox + +#### `src/lib/components/ReselectFileModal.svelte` +Modal prompting user to re-select a file when needed: +- Shows expected filename +- File drop zone / file picker +- Validates selected file against saved metadata + +#### `src/lib/components/Toast.svelte` +Toast notification component for user feedback. + +#### `src/lib/components/Modal.svelte` & `ModalContent.svelte` +Base modal components with backdrop, animations, and responsive design. + +### 2. Files Modified + +#### `src/routes/+page.svelte` +- Added restoration flow on app load +- Integrated RestoreSessionModal and ReselectFileModal +- Tracks persisted chats in `rememberedChatIds` Set +- `handleToggleRemember()` - Toggle remember state, request file handles +- `handleRestoreChats()` - Restore selected conversations +- `handleReselectFile()` - Handle file reselection + +#### `src/lib/components/ChatList.svelte` +- Added "Remember Conversation" toggle to context menu +- Shows checkmark when chat is remembered + +#### `src/lib/bookmarks.svelte.ts` +- Added `getBookmarksForChatAsExport()` method + +#### `src/lib/transcription.svelte.ts` +- Added `getTranscriptionsForChat()` method +- Added `setTranscriptionsForChat()` method + +#### `electron/main.cjs` +- Added IPC handlers: `fs:fileExists`, `fs:readFileFromPath` + +#### `electron/preload.cjs` +- Exposed file APIs to renderer + +#### `src/app.d.ts` +- Added TypeScript types for Electron APIs + +#### `src/app.css` +- Added cursor:pointer for all buttons + +### 3. Dependencies Added +- `idb-keyval` (v6.2.1) - Simple IndexedDB key-value storage + +### 4. i18n Strings Added +All persistence-related strings in all 10 languages (en, de, es, fr, it, ja, nl, pt, ru, zh) + +## Current Problem: File Restoration Not Working + +### Symptoms +User reports: "It doesn't matter which browser or electron I try. I always ask me 'Please Re-select File'" + +### Intended Flow + +#### **For Electron:** +1. User drops/selects ZIP file +2. User toggles "Remember Conversation" +3. File path is stored in metadata: `{ type: 'electron-path', filePath: '/absolute/path/to/file.zip' }` +4. On restore: Read file directly from disk using `window.electronAPI.readFileFromPath(filePath)` + +#### **For Web (Chromium with File System Access API):** +1. User drops/selects ZIP file +2. User toggles "Remember Conversation" +3. File picker appears (to get FileSystemFileHandle) +4. Handle stored in IndexedDB +5. Metadata updated: `{ type: 'file-handle', handleId: 'unique-id' }` +6. On restore: Retrieve handle, check permission, read file automatically + +#### **For Web (Firefox/Safari - no File System Access API):** +1. User drops/selects ZIP file +2. User toggles "Remember Conversation" +3. Metadata saved: `{ type: 'reselect-required' }` +4. On restore: Show ReselectFileModal (expected behavior) + +### Likely Issues to Debug + +#### Issue 1: File Reference Not Being Stored Correctly +**Check in `+page.svelte` line ~789:** +```typescript +async function handleToggleRemember(chatId: string) { + // ... + if (!isRemembered) { + // Saving... + const persistedId = await savePersistedChat(/* ... */); + + // For web with File System Access API + if (!isElectron && isFileSystemAccessSupported()) { + const fileHandle = await promptForFileHandle(file.name); + if (fileHandle) { + const handleId = await storeFileHandle(fileHandle); + await updatePersistedChat(persistedId, { + fileReference: { type: 'file-handle', handleId } + }); + } + } + } +} +``` + +**Potential Problems:** +- `file` might not be available in this scope +- `fileHandle` might be null/undefined +- `storeFileHandle()` might be failing +- `updatePersistedChat()` might not be updating correctly +- For Electron, file path might not be captured correctly + +#### Issue 2: Restoration Logic Not Finding File Reference +**Check in `src/lib/persistence.svelte.ts` line ~450:** +```typescript +export async function restoreChat(persistedChat: PersistedChatMetadata): Promise { + const { fileReference } = persistedChat; + + // Check what fileReference type is being received + console.log('Restoring with fileReference:', fileReference); + + if (fileReference.type === 'electron-path') { + // Electron path logic + } else if (fileReference.type === 'file-handle') { + // File handle logic + } else { + // Falls back to reselect-required + return { success: false, needsReselect: true }; + } +} +``` + +**Potential Problems:** +- `fileReference.type` might always be 'reselect-required' +- Electron file path not being passed to `savePersistedChat()` +- File handle not being stored correctly + +#### Issue 3: Electron File Path Not Being Captured +**Check in `+page.svelte` where `handleFilesSelected` is called:** +```typescript +async function handleFilesSelected(files: File[]) { + for (const file of files) { + // For Electron, we need to get the file path + // But File object from file input doesn't have path property + // Need to use window.electronAPI to get the actual file path + } +} +``` + +**Potential Problems:** +- When user drops file in Electron, we get a File object but not the actual file path +- Need to use Electron's dialog.showOpenFilePicker to get the real path +- Current implementation might not be capturing Electron file paths at all + +## Debug Steps to Take + +### Step 1: Add Console Logging +Add debug logging throughout the flow: + +**In `+page.svelte` - handleToggleRemember:** +```typescript +console.log('Toggle remember - isElectron:', isElectron); +console.log('Toggle remember - file:', file); +console.log('Toggle remember - fileRef from Map:', fileRef); +console.log('Persisted ID:', persistedId); +``` + +**In `persistence.svelte.ts` - savePersistedChat:** +```typescript +console.log('Saving with fileReference:', metadata.fileReference); +``` + +**In `persistence.svelte.ts` - restoreChat:** +```typescript +console.log('Restoring with fileReference:', persistedChat.fileReference); +``` + +**In `persistence.svelte.ts` - getPersistedChats:** +```typescript +const chats = await get('persisted-chats') || []; +console.log('Retrieved persisted chats:', chats.map(c => ({ + id: c.id, + title: c.chatTitle, + fileRef: c.fileReference +}))); +``` + +### Step 2: Check IndexedDB Directly +Open browser DevTools → Application → IndexedDB → Look for stored data: +- Check if `persisted-chats` key exists +- Check if file handles are stored +- Verify fileReference type in stored metadata + +### Step 3: Fix Electron File Path Capture + +The main issue is likely that we're not capturing the file path in Electron. When a user drops a file, we get a File object but not the actual path. + +**Solution for Electron:** +```typescript +// In +page.svelte +async function handleToggleRemember(chatId: string) { + // ... + if (isElectron) { + // Need to prompt user to select file again to get the path + // Or store the path when they originally selected it + const filePath = await window.electronAPI?.getFilePath(); + if (filePath) { + const persistedId = await savePersistedChat( + chat, + file, + // ... other params + { type: 'electron-path', filePath } + ); + } + } +} +``` + +Need to add `getFilePath()` to Electron IPC: +```javascript +// In electron/main.cjs +ipcMain.handle('fs:getFilePath', async () => { + const result = await dialog.showOpenDialog({ + properties: ['openFile'], + filters: [{ name: 'ZIP Files', extensions: ['zip'] }] + }); + return result.filePaths[0]; +}); +``` + +### Step 4: Verify File Handle Storage and Retrieval + +**Test in Chrome DevTools Console:** +```javascript +// Check if File System Access API is available +console.log('showOpenFilePicker' in window); + +// Test storing a handle +const [handle] = await window.showOpenFilePicker(); +await idb.set('test-handle', handle); +const retrieved = await idb.get('test-handle'); +console.log('Retrieved handle:', retrieved); + +// Test permission +const permission = await retrieved.queryPermission({ mode: 'read' }); +console.log('Permission:', permission); +``` + +## Key Code Locations + +### File Reference Flow +1. **Capture**: `+page.svelte` line ~789 in `handleToggleRemember()` +2. **Storage**: `persistence.svelte.ts` line ~100 in `savePersistedChat()` +3. **Retrieval**: `persistence.svelte.ts` line ~190 in `getPersistedChats()` +4. **Restoration**: `persistence.svelte.ts` line ~450 in `restoreChat()` + +### Electron IPC +1. **Main Process**: `electron/main.cjs` lines 220-250 +2. **Preload**: `electron/preload.cjs` lines 50-80 +3. **Usage**: `+page.svelte` and `persistence.svelte.ts` + +## Technical Constraints + +### Svelte 5 Runes (CRITICAL) +- **Use `$state`, `$derived`, `$effect`** - NOT Svelte 4 stores +- **Use `$props()`** for component props +- **Use callback props** for events (not createEventDispatcher) + +### File System Access API +- Only available in Chromium browsers (Chrome 86+, Edge 86+) +- `requestPermission()` REQUIRES user gesture +- Can't call during automated restoration +- Permissions may expire + +### Electron +- File paths are absolute paths on disk +- Use `fs.existsSync()` and `fs.readFileSync()` +- IPC communication between main and renderer process + +## Next Steps for AI Agent + +1. **Add comprehensive debug logging** to trace the exact flow +2. **Test in actual browser/Electron** to see console output +3. **Verify IndexedDB contents** to see what's actually stored +4. **Fix the root cause** - likely that file references aren't being captured/stored correctly +5. **Specific focus areas:** + - Electron: Ensure file path is captured when toggling remember + - Web: Ensure file handle is stored AND metadata is updated + - Verify `updatePersistedChat()` actually updates IndexedDB + +## Commands to Run + +```bash +# Build +npm run build + +# Lint +npm run lint + +# Run dev server (web) +npm run dev + +# Run Electron +npm run electron:dev + +# Type check +npm run check +``` + +## Files to Focus On + +1. **`src/routes/+page.svelte`** - lines 750-850 (handleToggleRemember, file reference capture) +2. **`src/lib/persistence.svelte.ts`** - lines 100-150 (savePersistedChat), lines 450-550 (restoreChat) +3. **`electron/main.cjs`** - lines 220-250 (file operations) + +## Expected Outcome + +After fixing: +- **Electron**: Toggle remember → close app → reopen → conversations restore automatically (no reselect modal) +- **Chrome/Edge**: Toggle remember → grant permission → close → reopen → conversations restore automatically +- **Firefox/Safari**: Toggle remember → close → reopen → shows reselect modal (expected, no API support) + +## Contact for Questions +Repository: https://github.com/rodrigogs/whats-reader +Branch: copilot/add-persistent-conversation-feature + +--- + +## Prompt for Another AI Tool + +Copy everything below to start working with another AI: + +--- + +I'm working on the rodrigogs/whats-reader repository on branch `copilot/add-persistent-conversation-feature`. + +**Problem**: I've implemented a "Remember Conversation" feature that should persist chat sessions across app restarts, but the file restoration isn't working. Users always see the "Please Re-select File" modal even after supposedly storing file handles or paths. + +**Repository Structure**: +- Hybrid SvelteKit + Electron app +- Uses Svelte 5 runes ($state, $derived, $effect) - NOT Svelte 4 stores +- TypeScript throughout +- IndexedDB storage via idb-keyval +- File System Access API for web, file paths for Electron + +**What I've implemented**: +- `src/lib/persistence.svelte.ts` - Core persistence module with save/restore/validate functions +- `src/lib/components/RestoreSessionModal.svelte` - Modal for selecting conversations to restore +- `src/lib/components/ReselectFileModal.svelte` - Modal for re-selecting files +- Modified `src/routes/+page.svelte` to add restoration flow +- Modified `src/lib/components/ChatList.svelte` to add "Remember Conversation" toggle +- Added Electron IPC handlers for file operations in `electron/main.cjs` and `electron/preload.cjs` + +**The Bug**: +The file reference (either Electron path or web file handle) is not being stored or retrieved correctly. Every restoration shows the reselect modal. + +**Likely Root Causes**: +1. For Electron: File path not being captured when user toggles "Remember Conversation" +2. For Web: File handle not being stored in IndexedDB or metadata not being updated +3. The `fileReference` in persisted metadata always shows `{ type: 'reselect-required' }` + +**Debug This**: +1. Add console.log statements in `+page.svelte` handleToggleRemember() to see what file reference is being captured +2. Add console.log in `persistence.svelte.ts` savePersistedChat() and restoreChat() to trace file reference flow +3. Check browser DevTools → Application → IndexedDB to see what's actually stored +4. For Electron: Verify file path is being obtained (might need to add getFilePath() IPC handler) +5. For Web: Verify file handle is stored AND metadata is updated with handleId + +**Key files to check**: +- `src/routes/+page.svelte` lines 750-850 (handleToggleRemember) +- `src/lib/persistence.svelte.ts` lines 100-150 (savePersistedChat), 450-550 (restoreChat) +- `electron/main.cjs` lines 220-250 (IPC handlers) + +**Commands**: +- `npm run build` - Build the app +- `npm run lint` - Lint code +- `npm run dev` - Dev server +- `npm run electron:dev` - Run in Electron + +Please debug and fix the file reference storage/retrieval so that: +- Electron: Automatically restores from file path +- Chrome/Edge: Automatically restores from file handle (after permission granted) +- Firefox/Safari: Shows reselect modal (expected - no File System Access API) + +Start by adding debug logging to trace where the file reference is lost, then fix the root cause. diff --git a/electron/main.cjs b/electron/main.cjs index fc4c8c1..b5cf37d 100644 --- a/electron/main.cjs +++ b/electron/main.cjs @@ -227,6 +227,24 @@ ipcMain.handle('fs:fileExists', async (_event, filePath) => { return fs.existsSync(filePath); }); +// Read file from absolute path (for persistence) +ipcMain.handle('file:readFromPath', async (_event, filePath) => { + try { + const content = fs.readFileSync(filePath); + const fileName = path.basename(filePath); + return { + success: true, + buffer: content.buffer, + name: fileName, + }; + } catch (error) { + return { + success: false, + error: error.message, + }; + } +}); + ipcMain.handle('shell:openExternal', async (_event, url) => { // Validate URL before opening if (!url.startsWith('https://github.com/rodrigogs/whats-reader')) { diff --git a/electron/preload.cjs b/electron/preload.cjs index 2d42d89..8aa55e7 100644 --- a/electron/preload.cjs +++ b/electron/preload.cjs @@ -12,6 +12,10 @@ contextBridge.exposeInMainWorld('electronAPI', { readDir: (dirPath) => ipcRenderer.invoke('fs:readDir', dirPath), fileExists: (filePath) => ipcRenderer.invoke('fs:fileExists', filePath), + // Persistence file operations + readFileFromPath: (filePath) => + ipcRenderer.invoke('file:readFromPath', filePath), + // External links openExternal: (url) => ipcRenderer.invoke('shell:openExternal', url), diff --git a/messages/de.json b/messages/de.json index fec2c18..057e7ed 100644 --- a/messages/de.json +++ b/messages/de.json @@ -241,5 +241,22 @@ "media_gallery_type_other": "Andere", "media_gallery_clear_filter": "Filter löschen", "media_gallery_participant_search_placeholder": "Suche nach Name oder Nummer...", - "media_gallery_participant_no_match": "Kein Teilnehmer entspricht \"{query}\"" -} + "persistence_remember_conversation": "Remember Conversation", + "persistence_conversation_saved": "Conversation will be remembered", + "persistence_conversation_removed": "Conversation removed from saved sessions", + "persistence_restore_title": "Restore Saved Conversations", + "persistence_restore_description": "You have saved conversations from previous sessions:", + "persistence_restore_button": "Restore Selected ({count})", + "persistence_start_fresh": "Start Fresh", + "persistence_dont_show_again": "Don't show this again", + "persistence_last_opened": "Last opened: {date}", + "persistence_message_count": "{count} messages", + "persistence_reselect_title": "Please Re-select File", + "persistence_reselect_description": "To restore \"{chatTitle}\", please select the original file:", + "persistence_reselect_expected_file": "Expected file: {fileName}", + "persistence_skip": "Skip", + "persistence_validation_failed": "This file doesn't match the saved conversation", + "persistence_validation_confirm": "This might be the correct file, but we couldn't fully verify. Continue anyway?", + "persistence_file_not_found": "The original file was moved or deleted", + "persistence_restoring": "Restoring conversations..." +} \ No newline at end of file diff --git a/messages/en.json b/messages/en.json index dcc7388..1a97f8a 100644 --- a/messages/en.json +++ b/messages/en.json @@ -241,5 +241,23 @@ "media_gallery_type_other": "Other", "media_gallery_clear_filter": "Clear filter", "media_gallery_participant_search_placeholder": "Search by name or number...", - "media_gallery_participant_no_match": "No participant matches \"{query}\"" + "media_gallery_participant_no_match": "No participant matches \"{query}\"", + "persistence_remember_conversation": "Remember Conversation", + "persistence_conversation_saved": "Conversation will be remembered", + "persistence_conversation_removed": "Conversation removed from saved sessions", + "persistence_restore_title": "Restore Saved Conversations", + "persistence_restore_description": "You have saved conversations from previous sessions:", + "persistence_restore_button": "Restore Selected ({count})", + "persistence_start_fresh": "Start Fresh", + "persistence_dont_show_again": "Don't show this again", + "persistence_last_opened": "Last opened: {date}", + "persistence_message_count": "{count} messages", + "persistence_reselect_title": "Please Re-select File", + "persistence_reselect_description": "To restore \"{chatTitle}\", please select the original file:", + "persistence_reselect_expected_file": "Expected file: {fileName}", + "persistence_skip": "Skip", + "persistence_validation_failed": "This file doesn't match the saved conversation", + "persistence_validation_confirm": "This might be the correct file, but we couldn't fully verify. Continue anyway?", + "persistence_file_not_found": "The original file was moved or deleted", + "persistence_restoring": "Restoring conversations..." } diff --git a/messages/es.json b/messages/es.json index 06862b9..8c9526f 100644 --- a/messages/es.json +++ b/messages/es.json @@ -241,5 +241,22 @@ "media_gallery_type_other": "Otro", "media_gallery_clear_filter": "Limpiar filtro", "media_gallery_participant_search_placeholder": "Buscar por nombre o número...", - "media_gallery_participant_no_match": "Ningún participante coincide con \"{query}\"" -} + "persistence_remember_conversation": "Remember Conversation", + "persistence_conversation_saved": "Conversation will be remembered", + "persistence_conversation_removed": "Conversation removed from saved sessions", + "persistence_restore_title": "Restore Saved Conversations", + "persistence_restore_description": "You have saved conversations from previous sessions:", + "persistence_restore_button": "Restore Selected ({count})", + "persistence_start_fresh": "Start Fresh", + "persistence_dont_show_again": "Don't show this again", + "persistence_last_opened": "Last opened: {date}", + "persistence_message_count": "{count} messages", + "persistence_reselect_title": "Please Re-select File", + "persistence_reselect_description": "To restore \"{chatTitle}\", please select the original file:", + "persistence_reselect_expected_file": "Expected file: {fileName}", + "persistence_skip": "Skip", + "persistence_validation_failed": "This file doesn't match the saved conversation", + "persistence_validation_confirm": "This might be the correct file, but we couldn't fully verify. Continue anyway?", + "persistence_file_not_found": "The original file was moved or deleted", + "persistence_restoring": "Restoring conversations..." +} \ No newline at end of file diff --git a/messages/fr.json b/messages/fr.json index 7810134..8571c4e 100644 --- a/messages/fr.json +++ b/messages/fr.json @@ -241,5 +241,22 @@ "media_gallery_type_other": "Autre", "media_gallery_clear_filter": "Effacer le filtre", "media_gallery_participant_search_placeholder": "Recherche par nom ou numéro...", - "media_gallery_participant_no_match": "Aucun participant ne correspond à \"{query}\"" -} + "persistence_remember_conversation": "Remember Conversation", + "persistence_conversation_saved": "Conversation will be remembered", + "persistence_conversation_removed": "Conversation removed from saved sessions", + "persistence_restore_title": "Restore Saved Conversations", + "persistence_restore_description": "You have saved conversations from previous sessions:", + "persistence_restore_button": "Restore Selected ({count})", + "persistence_start_fresh": "Start Fresh", + "persistence_dont_show_again": "Don't show this again", + "persistence_last_opened": "Last opened: {date}", + "persistence_message_count": "{count} messages", + "persistence_reselect_title": "Please Re-select File", + "persistence_reselect_description": "To restore \"{chatTitle}\", please select the original file:", + "persistence_reselect_expected_file": "Expected file: {fileName}", + "persistence_skip": "Skip", + "persistence_validation_failed": "This file doesn't match the saved conversation", + "persistence_validation_confirm": "This might be the correct file, but we couldn't fully verify. Continue anyway?", + "persistence_file_not_found": "The original file was moved or deleted", + "persistence_restoring": "Restoring conversations..." +} \ No newline at end of file diff --git a/messages/it.json b/messages/it.json index c1d9749..158ee69 100644 --- a/messages/it.json +++ b/messages/it.json @@ -241,5 +241,22 @@ "media_gallery_type_other": "Altro", "media_gallery_clear_filter": "Cancella filtro", "media_gallery_participant_search_placeholder": "Cerca per nome o numero...", - "media_gallery_participant_no_match": "Nessun partecipante corrisponde a \"{query}\"" -} + "persistence_remember_conversation": "Remember Conversation", + "persistence_conversation_saved": "Conversation will be remembered", + "persistence_conversation_removed": "Conversation removed from saved sessions", + "persistence_restore_title": "Restore Saved Conversations", + "persistence_restore_description": "You have saved conversations from previous sessions:", + "persistence_restore_button": "Restore Selected ({count})", + "persistence_start_fresh": "Start Fresh", + "persistence_dont_show_again": "Don't show this again", + "persistence_last_opened": "Last opened: {date}", + "persistence_message_count": "{count} messages", + "persistence_reselect_title": "Please Re-select File", + "persistence_reselect_description": "To restore \"{chatTitle}\", please select the original file:", + "persistence_reselect_expected_file": "Expected file: {fileName}", + "persistence_skip": "Skip", + "persistence_validation_failed": "This file doesn't match the saved conversation", + "persistence_validation_confirm": "This might be the correct file, but we couldn't fully verify. Continue anyway?", + "persistence_file_not_found": "The original file was moved or deleted", + "persistence_restoring": "Restoring conversations..." +} \ No newline at end of file diff --git a/messages/ja.json b/messages/ja.json index fed388d..e853e0c 100644 --- a/messages/ja.json +++ b/messages/ja.json @@ -241,5 +241,22 @@ "media_gallery_type_other": "他の", "media_gallery_clear_filter": "フィルターをクリア", "media_gallery_participant_search_placeholder": "名前または番号で検索...", - "media_gallery_participant_no_match": "「{query}」に一致する参加者はいません" -} + "persistence_remember_conversation": "Remember Conversation", + "persistence_conversation_saved": "Conversation will be remembered", + "persistence_conversation_removed": "Conversation removed from saved sessions", + "persistence_restore_title": "Restore Saved Conversations", + "persistence_restore_description": "You have saved conversations from previous sessions:", + "persistence_restore_button": "Restore Selected ({count})", + "persistence_start_fresh": "Start Fresh", + "persistence_dont_show_again": "Don't show this again", + "persistence_last_opened": "Last opened: {date}", + "persistence_message_count": "{count} messages", + "persistence_reselect_title": "Please Re-select File", + "persistence_reselect_description": "To restore \"{chatTitle}\", please select the original file:", + "persistence_reselect_expected_file": "Expected file: {fileName}", + "persistence_skip": "Skip", + "persistence_validation_failed": "This file doesn't match the saved conversation", + "persistence_validation_confirm": "This might be the correct file, but we couldn't fully verify. Continue anyway?", + "persistence_file_not_found": "The original file was moved or deleted", + "persistence_restoring": "Restoring conversations..." +} \ No newline at end of file diff --git a/messages/nl.json b/messages/nl.json index 9556db4..0e4e1db 100644 --- a/messages/nl.json +++ b/messages/nl.json @@ -241,5 +241,22 @@ "media_gallery_type_other": "Ander", "media_gallery_clear_filter": "Filter wissen", "media_gallery_participant_search_placeholder": "Zoeken op naam of nummer...", - "media_gallery_participant_no_match": "Geen deelnemer komt overeen met \"{query}\"" -} + "persistence_remember_conversation": "Remember Conversation", + "persistence_conversation_saved": "Conversation will be remembered", + "persistence_conversation_removed": "Conversation removed from saved sessions", + "persistence_restore_title": "Restore Saved Conversations", + "persistence_restore_description": "You have saved conversations from previous sessions:", + "persistence_restore_button": "Restore Selected ({count})", + "persistence_start_fresh": "Start Fresh", + "persistence_dont_show_again": "Don't show this again", + "persistence_last_opened": "Last opened: {date}", + "persistence_message_count": "{count} messages", + "persistence_reselect_title": "Please Re-select File", + "persistence_reselect_description": "To restore \"{chatTitle}\", please select the original file:", + "persistence_reselect_expected_file": "Expected file: {fileName}", + "persistence_skip": "Skip", + "persistence_validation_failed": "This file doesn't match the saved conversation", + "persistence_validation_confirm": "This might be the correct file, but we couldn't fully verify. Continue anyway?", + "persistence_file_not_found": "The original file was moved or deleted", + "persistence_restoring": "Restoring conversations..." +} \ No newline at end of file diff --git a/messages/pt.json b/messages/pt.json index 18d91b2..d26e0c8 100644 --- a/messages/pt.json +++ b/messages/pt.json @@ -241,5 +241,22 @@ "media_gallery_type_other": "Outro", "media_gallery_clear_filter": "Limpar filtro", "media_gallery_participant_search_placeholder": "Pesquisar por nome ou número...", - "media_gallery_participant_no_match": "Nenhum participante corresponde a \"{query}\"" -} + "persistence_remember_conversation": "Remember Conversation", + "persistence_conversation_saved": "Conversation will be remembered", + "persistence_conversation_removed": "Conversation removed from saved sessions", + "persistence_restore_title": "Restore Saved Conversations", + "persistence_restore_description": "You have saved conversations from previous sessions:", + "persistence_restore_button": "Restore Selected ({count})", + "persistence_start_fresh": "Start Fresh", + "persistence_dont_show_again": "Don't show this again", + "persistence_last_opened": "Last opened: {date}", + "persistence_message_count": "{count} messages", + "persistence_reselect_title": "Please Re-select File", + "persistence_reselect_description": "To restore \"{chatTitle}\", please select the original file:", + "persistence_reselect_expected_file": "Expected file: {fileName}", + "persistence_skip": "Skip", + "persistence_validation_failed": "This file doesn't match the saved conversation", + "persistence_validation_confirm": "This might be the correct file, but we couldn't fully verify. Continue anyway?", + "persistence_file_not_found": "The original file was moved or deleted", + "persistence_restoring": "Restoring conversations..." +} \ No newline at end of file diff --git a/messages/ru.json b/messages/ru.json index 7c76d60..b323769 100644 --- a/messages/ru.json +++ b/messages/ru.json @@ -241,5 +241,22 @@ "media_gallery_type_other": "Другой", "media_gallery_clear_filter": "Очистить фильтр", "media_gallery_participant_search_placeholder": "Поиск по имени или номеру...", - "media_gallery_participant_no_match": "Ни один участник не соответствует \"{query}\"" -} + "persistence_remember_conversation": "Remember Conversation", + "persistence_conversation_saved": "Conversation will be remembered", + "persistence_conversation_removed": "Conversation removed from saved sessions", + "persistence_restore_title": "Restore Saved Conversations", + "persistence_restore_description": "You have saved conversations from previous sessions:", + "persistence_restore_button": "Restore Selected ({count})", + "persistence_start_fresh": "Start Fresh", + "persistence_dont_show_again": "Don't show this again", + "persistence_last_opened": "Last opened: {date}", + "persistence_message_count": "{count} messages", + "persistence_reselect_title": "Please Re-select File", + "persistence_reselect_description": "To restore \"{chatTitle}\", please select the original file:", + "persistence_reselect_expected_file": "Expected file: {fileName}", + "persistence_skip": "Skip", + "persistence_validation_failed": "This file doesn't match the saved conversation", + "persistence_validation_confirm": "This might be the correct file, but we couldn't fully verify. Continue anyway?", + "persistence_file_not_found": "The original file was moved or deleted", + "persistence_restoring": "Restoring conversations..." +} \ No newline at end of file diff --git a/messages/zh.json b/messages/zh.json index 76e59ce..0804ff7 100644 --- a/messages/zh.json +++ b/messages/zh.json @@ -241,5 +241,22 @@ "media_gallery_type_other": "其他", "media_gallery_clear_filter": "清除过滤器", "media_gallery_participant_search_placeholder": "按名称或编号搜索……", - "media_gallery_participant_no_match": "没有参与者匹配\"{query}\"" -} + "persistence_remember_conversation": "Remember Conversation", + "persistence_conversation_saved": "Conversation will be remembered", + "persistence_conversation_removed": "Conversation removed from saved sessions", + "persistence_restore_title": "Restore Saved Conversations", + "persistence_restore_description": "You have saved conversations from previous sessions:", + "persistence_restore_button": "Restore Selected ({count})", + "persistence_start_fresh": "Start Fresh", + "persistence_dont_show_again": "Don't show this again", + "persistence_last_opened": "Last opened: {date}", + "persistence_message_count": "{count} messages", + "persistence_reselect_title": "Please Re-select File", + "persistence_reselect_description": "To restore \"{chatTitle}\", please select the original file:", + "persistence_reselect_expected_file": "Expected file: {fileName}", + "persistence_skip": "Skip", + "persistence_validation_failed": "This file doesn't match the saved conversation", + "persistence_validation_confirm": "This might be the correct file, but we couldn't fully verify. Continue anyway?", + "persistence_file_not_found": "The original file was moved or deleted", + "persistence_restoring": "Restoring conversations..." +} \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index a81bf53..4f065f6 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,6 +12,7 @@ "@floating-ui/dom": "^1.7.4", "@huggingface/transformers": "^3.8.1", "electron-updater": "^6.6.2", + "idb-keyval": "^6.2.2", "jszip": "^3.10.1" }, "devDependencies": { @@ -61,27 +62,24 @@ } }, "node_modules/@actions/http-client": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@actions/http-client/-/http-client-3.0.0.tgz", - "integrity": "sha512-1s3tXAfVMSz9a4ZEBkXXRQD4QhY3+GAsWSbaYpeknPOKEeyRiU3lH+bHiLMZdo2x/fIeQ/hscL1wCkDLVM2DZQ==", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@actions/http-client/-/http-client-3.0.2.tgz", + "integrity": "sha512-JP38FYYpyqvUsz+Igqlc/JG6YO9PaKuvqjM3iGvaLqFnJ7TFmcLyy2IDrY0bI0qCQug8E9K+elv5ZNfw62ZJzA==", "dev": true, "license": "MIT", "dependencies": { "tunnel": "^0.0.6", - "undici": "^5.28.5" + "undici": "^6.23.0" } }, "node_modules/@actions/http-client/node_modules/undici": { - "version": "5.29.0", - "resolved": "https://registry.npmjs.org/undici/-/undici-5.29.0.tgz", - "integrity": "sha512-raqeBD6NQK4SkWhQzeYKd1KmIG6dllBOTt55Rmkt4HtI9mwdWtJljnrXjAFUBLTSN67HWrOIZ3EPF4kjUw80Bg==", + "version": "6.23.0", + "resolved": "https://registry.npmjs.org/undici/-/undici-6.23.0.tgz", + "integrity": "sha512-VfQPToRA5FZs/qJxLIinmU59u0r7LXqoJkCzinq3ckNJp3vKEh7jTWN589YQ5+aoAC/TGRLyJLCPKcLQbM8r9g==", "dev": true, "license": "MIT", - "dependencies": { - "@fastify/busboy": "^2.0.0" - }, "engines": { - "node": ">=14.0" + "node": ">=18.17" } }, "node_modules/@actions/io": { @@ -309,9 +307,9 @@ } }, "node_modules/@electron/asar": { - "version": "3.2.18", - "resolved": "https://registry.npmjs.org/@electron/asar/-/asar-3.2.18.tgz", - "integrity": "sha512-2XyvMe3N3Nrs8cV39IKELRHTYUWFKrmqqSY1U+GMlc0jvqjIVnoxhNd2H4JolWQncbJi1DCvb5TNxZuI2fEjWg==", + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/@electron/asar/-/asar-3.4.1.tgz", + "integrity": "sha512-i4/rNPRS84t0vSRa2HorerGRXWyF4vThfHesw0dmcWHp+cspK743UanA0suA5Q5y8kzY2y6YKrvbIUn69BCAiA==", "dev": true, "license": "MIT", "dependencies": { @@ -437,88 +435,6 @@ "node": ">= 4.0.0" } }, - "node_modules/@electron/node-gyp": { - "version": "10.2.0-electron.1", - "resolved": "git+ssh://git@github.com/electron/node-gyp.git#06b29aafb7708acef8b3669835c8a7857ebc92d2", - "integrity": "sha512-CrYo6TntjpoMO1SHjl5Pa/JoUsECNqNdB7Kx49WLQpWzPw53eEITJ2Hs9fh/ryUYDn4pxZz11StaBYBrLFJdqg==", - "dev": true, - "license": "MIT", - "dependencies": { - "env-paths": "^2.2.0", - "exponential-backoff": "^3.1.1", - "glob": "^8.1.0", - "graceful-fs": "^4.2.6", - "make-fetch-happen": "^10.2.1", - "nopt": "^6.0.0", - "proc-log": "^2.0.1", - "semver": "^7.3.5", - "tar": "^6.2.1", - "which": "^2.0.2" - }, - "bin": { - "node-gyp": "bin/node-gyp.js" - }, - "engines": { - "node": ">=12.13.0" - } - }, - "node_modules/@electron/node-gyp/node_modules/brace-expansion": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", - "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "node_modules/@electron/node-gyp/node_modules/glob": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", - "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", - "deprecated": "Glob versions prior to v9 are no longer supported", - "dev": true, - "license": "ISC", - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^5.0.1", - "once": "^1.3.0" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/@electron/node-gyp/node_modules/minimatch": { - "version": "5.1.6", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", - "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", - "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/@electron/node-gyp/node_modules/semver": { - "version": "7.7.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz", - "integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/@electron/notarize": { "version": "2.5.0", "resolved": "https://registry.npmjs.org/@electron/notarize/-/notarize-2.5.0.tgz", @@ -551,9 +467,9 @@ } }, "node_modules/@electron/osx-sign": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/@electron/osx-sign/-/osx-sign-1.3.1.tgz", - "integrity": "sha512-BAfviURMHpmb1Yb50YbCxnOY0wfwaLXH5KJ4+80zS0gUkzDX3ec23naTlEqKsN+PwYn+a1cCzM7BJ4Wcd3sGzw==", + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/@electron/osx-sign/-/osx-sign-1.3.3.tgz", + "integrity": "sha512-KZ8mhXvWv2rIEgMbWZ4y33bDHyUKMXnx4M0sTyPNK/vcB81ImdeY9Ggdqy0SWbMDgmbqyQ+phgejh6V3R2QuSg==", "dev": true, "license": "BSD-2-Clause", "dependencies": { @@ -601,47 +517,31 @@ } }, "node_modules/@electron/rebuild": { - "version": "3.7.0", - "resolved": "https://registry.npmjs.org/@electron/rebuild/-/rebuild-3.7.0.tgz", - "integrity": "sha512-VW++CNSlZwMYP7MyXEbrKjpzEwhB5kDNbzGtiPEjwYysqyTCF+YbNJ210Dj3AjWsGSV4iEEwNkmJN9yGZmVvmw==", + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/@electron/rebuild/-/rebuild-4.0.3.tgz", + "integrity": "sha512-u9vpTHRMkOYCs/1FLiSVAFZ7FbjsXK+bQuzviJZa+lG7BHZl1nz52/IcGvwa3sk80/fc3llutBkbCq10Vh8WQA==", "dev": true, "license": "MIT", "dependencies": { - "@electron/node-gyp": "git+https://github.com/electron/node-gyp.git#06b29aafb7708acef8b3669835c8a7857ebc92d2", "@malept/cross-spawn-promise": "^2.0.0", - "chalk": "^4.0.0", "debug": "^4.1.1", "detect-libc": "^2.0.1", - "fs-extra": "^10.0.0", "got": "^11.7.0", - "node-abi": "^3.45.0", - "node-api-version": "^0.2.0", + "graceful-fs": "^4.2.11", + "node-abi": "^4.2.0", + "node-api-version": "^0.2.1", + "node-gyp": "^11.2.0", "ora": "^5.1.0", "read-binary-file-arch": "^1.0.6", "semver": "^7.3.5", - "tar": "^6.0.5", + "tar": "^7.5.6", "yargs": "^17.0.1" }, "bin": { "electron-rebuild": "lib/cli.js" }, "engines": { - "node": ">=12.13.0" - } - }, - "node_modules/@electron/rebuild/node_modules/fs-extra": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", - "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - }, - "engines": { - "node": ">=12" + "node": ">=22.12.0" } }, "node_modules/@electron/rebuild/node_modules/semver": { @@ -658,13 +558,13 @@ } }, "node_modules/@electron/universal": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@electron/universal/-/universal-2.0.1.tgz", - "integrity": "sha512-fKpv9kg4SPmt+hY7SVBnIYULE9QJl8L3sCfcBsnqbJwwBwAeTLokJ9TRt9y7bK0JAzIW2y78TVVjvnQEms/yyA==", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@electron/universal/-/universal-2.0.3.tgz", + "integrity": "sha512-Wn9sPYIVFRFl5HmwMJkARCCf7rqK/EurkfQ/rJZ14mHP3iYTjZSIOSVonEAnhWeAXwtw7zOekGRlc6yTtZ0t+g==", "dev": true, "license": "MIT", "dependencies": { - "@electron/asar": "^3.2.7", + "@electron/asar": "^3.3.1", "@malept/cross-spawn-promise": "^2.0.0", "debug": "^4.3.1", "dir-compare": "^4.2.0", @@ -1183,16 +1083,6 @@ "node": ">=18" } }, - "node_modules/@fastify/busboy": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/@fastify/busboy/-/busboy-2.1.1.tgz", - "integrity": "sha512-vBZP4NlzfOlerQTnba4aqZoMhE/a9HY7HRqoOPaETQcSQuWEIyZMHGfVu6w9wGtGK5fED5qRs2DteVCjOH60sA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=14" - } - }, "node_modules/@floating-ui/core": { "version": "1.7.3", "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.7.3.tgz", @@ -1218,13 +1108,6 @@ "integrity": "sha512-aGTxbpbg8/b5JfU1HXSrbH3wXZuLPJcNEcZQFMxLs3oSzgtVu6nFPkbbGGUvBcUjKV2YyB9Wxxabo+HEH9tcRQ==", "license": "MIT" }, - "node_modules/@gar/promisify": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/@gar/promisify/-/promisify-1.1.3.tgz", - "integrity": "sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw==", - "dev": true, - "license": "MIT" - }, "node_modules/@hapi/address": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/@hapi/address/-/address-5.1.1.tgz", @@ -1857,9 +1740,9 @@ } }, "node_modules/@isaacs/brace-expansion": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/@isaacs/brace-expansion/-/brace-expansion-5.0.0.tgz", - "integrity": "sha512-ZT55BDLV0yv0RBm2czMiZ+SqCGO7AvmOM3G/w2xhVPH+te0aKgFjmBvGlL1dH+ql2tgGO3MVrbb3jCKyvpgnxA==", + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/@isaacs/brace-expansion/-/brace-expansion-5.0.1.tgz", + "integrity": "sha512-WMz71T1JS624nWj2n2fnYAuPovhv7EUhk69R6i9dsVyzxt5eM3bjwvgk9L+APE1TRscGysAVMANkB0jh0LQZrQ==", "dev": true, "license": "MIT", "dependencies": { @@ -1971,15 +1854,6 @@ "node": ">=18.0.0" } }, - "node_modules/@isaacs/fs-minipass/node_modules/minipass": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", - "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", - "license": "ISC", - "engines": { - "node": ">=16 || 14 >=14.17" - } - }, "node_modules/@jridgewell/gen-mapping": { "version": "0.3.13", "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", @@ -2111,18 +1985,41 @@ "node": ">=10" } }, + "node_modules/@npmcli/agent": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@npmcli/agent/-/agent-3.0.0.tgz", + "integrity": "sha512-S79NdEgDQd/NGCay6TCoVzXSj74skRZIKJcpJjC5lOq34SZzyI6MqtiiWoiVWoVrTcGjNeC4ipbh1VIHlpfF5Q==", + "dev": true, + "license": "ISC", + "dependencies": { + "agent-base": "^7.1.0", + "http-proxy-agent": "^7.0.0", + "https-proxy-agent": "^7.0.1", + "lru-cache": "^10.0.1", + "socks-proxy-agent": "^8.0.3" + }, + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/@npmcli/agent/node_modules/lru-cache": { + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", + "dev": true, + "license": "ISC" + }, "node_modules/@npmcli/fs": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-2.1.2.tgz", - "integrity": "sha512-yOJKRvohFOaLqipNtwYB9WugyZKhC/DZC4VYPmpaCzDBrA8YpK3qHZ8/HGscMnE4GqbkLNuVcCnxkeQEdGt6LQ==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-4.0.0.tgz", + "integrity": "sha512-/xGlezI6xfGO9NwuJlnwz/K14qD1kCSAGtacBHnGzeAIuJGazcp45KP5NuyARXoKb7cwulAGWVsbeSxdG/cb0Q==", "dev": true, "license": "ISC", "dependencies": { - "@gar/promisify": "^1.1.3", "semver": "^7.3.5" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + "node": "^18.17.0 || >=20.5.0" } }, "node_modules/@npmcli/fs/node_modules/semver": { @@ -2138,21 +2035,6 @@ "node": ">=10" } }, - "node_modules/@npmcli/move-file": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@npmcli/move-file/-/move-file-2.0.1.tgz", - "integrity": "sha512-mJd2Z5TjYWq/ttPLLGqArdtnC74J6bOzg4rMDnN+p1xTacZ2yPRCk2y0oSWQtygLR9YVQXgOcONrwtnk3JupxQ==", - "deprecated": "This functionality has been moved to @npmcli/fs", - "dev": true, - "license": "MIT", - "dependencies": { - "mkdirp": "^1.0.4", - "rimraf": "^3.0.2" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, "node_modules/@octokit/auth-token": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-6.0.0.tgz", @@ -3430,9 +3312,9 @@ } }, "node_modules/@sveltejs/kit": { - "version": "2.49.2", - "resolved": "https://registry.npmjs.org/@sveltejs/kit/-/kit-2.49.2.tgz", - "integrity": "sha512-Vp3zX/qlwerQmHMP6x0Ry1oY7eKKRcOWGc2P59srOp4zcqyn+etJyQpELgOi4+ZSUgteX8Y387NuwruLgGXLUQ==", + "version": "2.50.2", + "resolved": "https://registry.npmjs.org/@sveltejs/kit/-/kit-2.50.2.tgz", + "integrity": "sha512-875hTUkEbz+MyJIxWbQjfMaekqdmEKUUfR7JyKcpfMRZqcGyrO9Gd+iS1D/Dx8LpE5FEtutWGOtlAh4ReSAiOA==", "dev": true, "license": "MIT", "dependencies": { @@ -3441,13 +3323,13 @@ "@types/cookie": "^0.6.0", "acorn": "^8.14.1", "cookie": "^0.6.0", - "devalue": "^5.3.2", + "devalue": "^5.6.2", "esm-env": "^1.2.2", "kleur": "^4.1.5", "magic-string": "^0.30.5", "mrmime": "^2.0.0", "sade": "^1.8.1", - "set-cookie-parser": "^2.6.0", + "set-cookie-parser": "^3.0.0", "sirv": "^3.0.0" }, "bin": { @@ -3460,11 +3342,15 @@ "@opentelemetry/api": "^1.0.0", "@sveltejs/vite-plugin-svelte": "^3.0.0 || ^4.0.0-next.1 || ^5.0.0 || ^6.0.0-next.0", "svelte": "^4.0.0 || ^5.0.0-next.0", + "typescript": "^5.3.3", "vite": "^5.0.3 || ^6.0.0 || ^7.0.0-beta.0" }, "peerDependenciesMeta": { "@opentelemetry/api": { "optional": true + }, + "typescript": { + "optional": true } } }, @@ -3792,16 +3678,6 @@ "vite": "^5.2.0 || ^6 || ^7" } }, - "node_modules/@tootallnate/once": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz", - "integrity": "sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 10" - } - }, "node_modules/@types/cacheable-request": { "version": "6.0.3", "resolved": "https://registry.npmjs.org/@types/cacheable-request/-/cacheable-request-6.0.3.tgz", @@ -3948,11 +3824,14 @@ "license": "MIT" }, "node_modules/abbrev": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", - "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-3.0.1.tgz", + "integrity": "sha512-AO2ac6pjRB3SJmGJo+v5/aK6Omggp6fsLrs6wN9bd35ulu4cCwaAU9+7ZhXjeqHVkaHThLuzH0nZr0YpCDhygg==", "dev": true, - "license": "ISC" + "license": "ISC", + "engines": { + "node": "^18.17.0 || >=20.5.0" + } }, "node_modules/acorn": { "version": "8.15.0", @@ -3977,19 +3856,6 @@ "node": ">= 14" } }, - "node_modules/agentkeepalive": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-4.6.0.tgz", - "integrity": "sha512-kja8j7PjmncONqaTsB8fQ+wE2mSU2DJ9D4XKoJ5PFWIdRMa6SLSN1ff4mOr4jCbfRSsxR4keIiySJU0N9T5hIQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "humanize-ms": "^1.2.1" - }, - "engines": { - "node": ">= 8.0.0" - } - }, "node_modules/aggregate-error": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", @@ -4091,52 +3957,152 @@ "license": "MIT" }, "node_modules/app-builder-lib": { - "version": "26.0.12", - "resolved": "https://registry.npmjs.org/app-builder-lib/-/app-builder-lib-26.0.12.tgz", - "integrity": "sha512-+/CEPH1fVKf6HowBUs6LcAIoRcjeqgvAeoSE+cl7Y7LndyQ9ViGPYibNk7wmhMHzNgHIuIbw4nWADPO+4mjgWw==", + "version": "26.7.0", + "resolved": "https://registry.npmjs.org/app-builder-lib/-/app-builder-lib-26.7.0.tgz", + "integrity": "sha512-/UgCD8VrO79Wv8aBNpjMfsS1pIUfIPURoRn0Ik6tMe5avdZF+vQgl/juJgipcMmH3YS0BD573lCdCHyoi84USg==", "dev": true, "license": "MIT", "dependencies": { "@develar/schema-utils": "~2.6.5", - "@electron/asar": "3.2.18", + "@electron/asar": "3.4.1", "@electron/fuses": "^1.8.0", + "@electron/get": "^3.0.0", "@electron/notarize": "2.5.0", - "@electron/osx-sign": "1.3.1", - "@electron/rebuild": "3.7.0", - "@electron/universal": "2.0.1", + "@electron/osx-sign": "1.3.3", + "@electron/rebuild": "^4.0.3", + "@electron/universal": "2.0.3", "@malept/flatpak-bundler": "^0.4.0", "@types/fs-extra": "9.0.13", "async-exit-hook": "^2.0.1", - "builder-util": "26.0.11", - "builder-util-runtime": "9.3.1", + "builder-util": "26.4.1", + "builder-util-runtime": "9.5.1", "chromium-pickle-js": "^0.2.0", - "config-file-ts": "0.2.8-rc1", + "ci-info": "4.3.1", "debug": "^4.3.4", "dotenv": "^16.4.5", "dotenv-expand": "^11.0.6", "ejs": "^3.1.8", - "electron-publish": "26.0.11", + "electron-publish": "26.6.0", "fs-extra": "^10.1.0", "hosted-git-info": "^4.1.0", - "is-ci": "^3.0.0", "isbinaryfile": "^5.0.0", + "jiti": "^2.4.2", "js-yaml": "^4.1.0", "json5": "^2.2.3", "lazy-val": "^1.0.5", - "minimatch": "^10.0.0", + "minimatch": "^10.0.3", "plist": "3.1.0", + "proper-lockfile": "^4.1.2", "resedit": "^1.7.0", - "semver": "^7.3.8", - "tar": "^6.1.12", + "semver": "~7.7.3", + "tar": "^7.5.7", "temp-file": "^3.4.0", - "tiny-async-pool": "1.3.0" + "tiny-async-pool": "1.3.0", + "which": "^5.0.0" }, "engines": { "node": ">=14.0.0" }, "peerDependencies": { - "dmg-builder": "26.0.12", - "electron-builder-squirrel-windows": "26.0.12" + "dmg-builder": "26.7.0", + "electron-builder-squirrel-windows": "26.7.0" + } + }, + "node_modules/app-builder-lib/node_modules/@electron/get": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@electron/get/-/get-3.1.0.tgz", + "integrity": "sha512-F+nKc0xW+kVbBRhFzaMgPy3KwmuNTYX1fx6+FxxoSnNgwYX6LD7AKBTWkU0MQ6IBoe7dz069CNkR673sPAgkCQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "^4.1.1", + "env-paths": "^2.2.0", + "fs-extra": "^8.1.0", + "got": "^11.8.5", + "progress": "^2.0.3", + "semver": "^6.2.0", + "sumchecker": "^3.0.1" + }, + "engines": { + "node": ">=14" + }, + "optionalDependencies": { + "global-agent": "^3.0.0" + } + }, + "node_modules/app-builder-lib/node_modules/@electron/get/node_modules/fs-extra": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", + "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", + "dev": true, + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + }, + "engines": { + "node": ">=6 <7 || >=8" + } + }, + "node_modules/app-builder-lib/node_modules/@electron/get/node_modules/jsonfile": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==", + "dev": true, + "license": "MIT", + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/app-builder-lib/node_modules/@electron/get/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/app-builder-lib/node_modules/@electron/get/node_modules/universalify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/app-builder-lib/node_modules/builder-util-runtime": { + "version": "9.5.1", + "resolved": "https://registry.npmjs.org/builder-util-runtime/-/builder-util-runtime-9.5.1.tgz", + "integrity": "sha512-qt41tMfgHTllhResqM5DcnHyDIWNgzHvuY2jDcYP9iaGpkWxTUzV6GQjDeLnlR1/DtdlcsWQbA7sByMpmJFTLQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "^4.3.4", + "sax": "^1.2.4" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/app-builder-lib/node_modules/ci-info": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-4.3.1.tgz", + "integrity": "sha512-Wdy2Igu8OcBpI2pZePZ5oWjPC38tmDVx5WKUXKwlLYkA0ozo85sLsLvkBbBn/sZaSCMFOGZJ14fvW9t5/d7kdA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], + "license": "MIT", + "engines": { + "node": ">=8" } }, "node_modules/app-builder-lib/node_modules/fs-extra": { @@ -4154,6 +4120,16 @@ "node": ">=12" } }, + "node_modules/app-builder-lib/node_modules/isexe": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-3.1.1.tgz", + "integrity": "sha512-LpB/54B+/2J5hqQ7imZHfdU31OlgQqx7ZicVlkm9kzg9/w8GKLEcFfJl/t7DCEDueOyBAD6zCCwTO6Fzs0NoEQ==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=16" + } + }, "node_modules/app-builder-lib/node_modules/semver": { "version": "7.7.3", "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz", @@ -4167,6 +4143,22 @@ "node": ">=10" } }, + "node_modules/app-builder-lib/node_modules/which": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/which/-/which-5.0.0.tgz", + "integrity": "sha512-JEdGzHwwkrbWoGOlIHqQ5gtprKGOenpDHpxE9zVR1bWbOtYRyPPHMe9FaP6x61CmNaTThSkb0DAJte5jD+DmzQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "isexe": "^3.1.1" + }, + "bin": { + "node-which": "bin/which.js" + }, + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, "node_modules/argparse": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", @@ -4425,23 +4417,22 @@ "license": "MIT" }, "node_modules/builder-util": { - "version": "26.0.11", - "resolved": "https://registry.npmjs.org/builder-util/-/builder-util-26.0.11.tgz", - "integrity": "sha512-xNjXfsldUEe153h1DraD0XvDOpqGR0L5eKFkdReB7eFW5HqysDZFfly4rckda6y9dF39N3pkPlOblcfHKGw+uA==", + "version": "26.4.1", + "resolved": "https://registry.npmjs.org/builder-util/-/builder-util-26.4.1.tgz", + "integrity": "sha512-FlgH43XZ50w3UtS1RVGDWOz8v9qMXPC7upMtKMtBEnYdt1OVoS61NYhKm/4x+cIaWqJTXua0+VVPI+fSPGXNIw==", "dev": true, "license": "MIT", "dependencies": { "@types/debug": "^4.1.6", "7zip-bin": "~5.2.0", "app-builder-bin": "5.0.0-alpha.12", - "builder-util-runtime": "9.3.1", + "builder-util-runtime": "9.5.1", "chalk": "^4.1.2", "cross-spawn": "^7.0.6", "debug": "^4.3.4", "fs-extra": "^10.1.0", "http-proxy-agent": "^7.0.0", "https-proxy-agent": "^7.0.0", - "is-ci": "^3.0.0", "js-yaml": "^4.1.0", "sanitize-filename": "^1.6.3", "source-map-support": "^0.5.19", @@ -4463,6 +4454,20 @@ "node": ">=12.0.0" } }, + "node_modules/builder-util/node_modules/builder-util-runtime": { + "version": "9.5.1", + "resolved": "https://registry.npmjs.org/builder-util-runtime/-/builder-util-runtime-9.5.1.tgz", + "integrity": "sha512-qt41tMfgHTllhResqM5DcnHyDIWNgzHvuY2jDcYP9iaGpkWxTUzV6GQjDeLnlR1/DtdlcsWQbA7sByMpmJFTLQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "^4.3.4", + "sax": "^1.2.4" + }, + "engines": { + "node": ">=12.0.0" + } + }, "node_modules/builder-util/node_modules/fs-extra": { "version": "10.1.0", "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", @@ -4479,33 +4484,27 @@ } }, "node_modules/cacache": { - "version": "16.1.3", - "resolved": "https://registry.npmjs.org/cacache/-/cacache-16.1.3.tgz", - "integrity": "sha512-/+Emcj9DAXxX4cwlLmRI9c166RuL3w30zp4R7Joiv2cQTtTtA+jeuCAjH3ZlGnYS3tKENSrKhAzVVP9GVyzeYQ==", + "version": "19.0.1", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-19.0.1.tgz", + "integrity": "sha512-hdsUxulXCi5STId78vRVYEtDAjq99ICAUktLTeTYsLoTE6Z8dS0c8pWNCxwdrk9YfJeobDZc2Y186hD/5ZQgFQ==", "dev": true, "license": "ISC", "dependencies": { - "@npmcli/fs": "^2.1.0", - "@npmcli/move-file": "^2.0.0", - "chownr": "^2.0.0", - "fs-minipass": "^2.1.0", - "glob": "^8.0.1", - "infer-owner": "^1.0.4", - "lru-cache": "^7.7.1", - "minipass": "^3.1.6", - "minipass-collect": "^1.0.2", + "@npmcli/fs": "^4.0.0", + "fs-minipass": "^3.0.0", + "glob": "^10.2.2", + "lru-cache": "^10.0.1", + "minipass": "^7.0.3", + "minipass-collect": "^2.0.1", "minipass-flush": "^1.0.5", "minipass-pipeline": "^1.2.4", - "mkdirp": "^1.0.4", - "p-map": "^4.0.0", - "promise-inflight": "^1.0.1", - "rimraf": "^3.0.2", - "ssri": "^9.0.0", - "tar": "^6.1.11", - "unique-filename": "^2.0.0" + "p-map": "^7.0.2", + "ssri": "^12.0.0", + "tar": "^7.4.3", + "unique-filename": "^4.0.0" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + "node": "^18.17.0 || >=20.5.0" } }, "node_modules/cacache/node_modules/brace-expansion": { @@ -4519,47 +4518,48 @@ } }, "node_modules/cacache/node_modules/glob": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", - "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", - "deprecated": "Glob versions prior to v9 are no longer supported", + "version": "10.5.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.5.0.tgz", + "integrity": "sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg==", + "deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me", "dev": true, "license": "ISC", "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^5.0.1", - "once": "^1.3.0" + "foreground-child": "^3.1.0", + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^1.11.1" }, - "engines": { - "node": ">=12" + "bin": { + "glob": "dist/esm/bin.mjs" }, "funding": { "url": "https://github.com/sponsors/isaacs" } }, "node_modules/cacache/node_modules/lru-cache": { - "version": "7.18.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", - "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", "dev": true, - "license": "ISC", - "engines": { - "node": ">=12" - } + "license": "ISC" }, "node_modules/cacache/node_modules/minimatch": { - "version": "5.1.6", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", - "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", "dev": true, "license": "ISC", "dependencies": { "brace-expansion": "^2.0.1" }, "engines": { - "node": ">=10" + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, "node_modules/cacheable-lookup": { @@ -4688,13 +4688,12 @@ } }, "node_modules/chownr": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", - "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", - "dev": true, - "license": "ISC", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-3.0.0.tgz", + "integrity": "sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g==", + "license": "BlueOak-1.0.0", "engines": { - "node": ">=10" + "node": ">=18" } }, "node_modules/chromium-pickle-js": { @@ -4705,9 +4704,9 @@ "license": "MIT" }, "node_modules/ci-info": { - "version": "3.9.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", - "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-4.4.0.tgz", + "integrity": "sha512-77PSwercCZU2Fc4sX94eF8k8Pxte6JAwL4/ICZLFjJLqegs7kCuAsqqj/70NQF6TvDpgFjkubQB2FW2ZZddvQg==", "dev": true, "funding": [ { @@ -5018,77 +5017,9 @@ "integrity": "sha512-qj+f8APARXHrM0hraqXYb2/bOVSV4PvJQlNZ/DVj0QrmNM2q2euizkeuVckQ57J+W0mRH6Hvi+k50M4Jul2VRQ==", "dev": true, "license": "MIT", - "dependencies": { - "ini": "^1.3.4", - "proto-list": "~1.2.1" - } - }, - "node_modules/config-file-ts": { - "version": "0.2.8-rc1", - "resolved": "https://registry.npmjs.org/config-file-ts/-/config-file-ts-0.2.8-rc1.tgz", - "integrity": "sha512-GtNECbVI82bT4RiDIzBSVuTKoSHufnU7Ce7/42bkWZJZFLjmDF2WBpVsvRkhKCfKBnTBb3qZrBwPpFBU/Myvhg==", - "dev": true, - "license": "MIT", - "dependencies": { - "glob": "^10.3.12", - "typescript": "^5.4.3" - } - }, - "node_modules/config-file-ts/node_modules/brace-expansion": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", - "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "node_modules/config-file-ts/node_modules/glob": { - "version": "10.5.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.5.0.tgz", - "integrity": "sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg==", - "dev": true, - "license": "ISC", - "dependencies": { - "foreground-child": "^3.1.0", - "jackspeak": "^3.1.2", - "minimatch": "^9.0.4", - "minipass": "^7.1.2", - "package-json-from-dist": "^1.0.0", - "path-scurry": "^1.11.1" - }, - "bin": { - "glob": "dist/esm/bin.mjs" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/config-file-ts/node_modules/minimatch": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", - "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", - "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/config-file-ts/node_modules/minipass": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", - "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", - "dev": true, - "license": "ISC", - "engines": { - "node": ">=16 || 14 >=14.17" + "dependencies": { + "ini": "^1.3.4", + "proto-list": "~1.2.1" } }, "node_modules/consola": { @@ -5474,9 +5405,9 @@ "license": "MIT" }, "node_modules/devalue": { - "version": "5.6.1", - "resolved": "https://registry.npmjs.org/devalue/-/devalue-5.6.1.tgz", - "integrity": "sha512-jDwizj+IlEZBunHcOuuFVBnIMPAEHvTsJj0BcIp94xYguLRVBcXO853px/MyIJvbVzWdsGvrRweIUWJw8hBP7A==", + "version": "5.6.2", + "resolved": "https://registry.npmjs.org/devalue/-/devalue-5.6.2.tgz", + "integrity": "sha512-nPRkjWzzDQlsejL1WVifk5rvcFi/y1onBRxjaFMjZeR9mFpqu2gmAZ9xUB9/IEanEP/vBtGeGganC/GO1fmufg==", "dev": true, "license": "MIT" }, @@ -5518,15 +5449,14 @@ } }, "node_modules/dmg-builder": { - "version": "26.0.12", - "resolved": "https://registry.npmjs.org/dmg-builder/-/dmg-builder-26.0.12.tgz", - "integrity": "sha512-59CAAjAhTaIMCN8y9kD573vDkxbs1uhDcrFLHSgutYdPcGOU35Rf95725snvzEOy4BFB7+eLJ8djCNPmGwG67w==", + "version": "26.7.0", + "resolved": "https://registry.npmjs.org/dmg-builder/-/dmg-builder-26.7.0.tgz", + "integrity": "sha512-uOOBA3f+kW3o4KpSoMQ6SNpdXU7WtxlJRb9vCZgOvqhTz4b3GjcoWKstdisizNZLsylhTMv8TLHFPFW0Uxsj/g==", "dev": true, "license": "MIT", "dependencies": { - "app-builder-lib": "26.0.12", - "builder-util": "26.0.11", - "builder-util-runtime": "9.3.1", + "app-builder-lib": "26.7.0", + "builder-util": "26.4.1", "fs-extra": "^10.1.0", "iconv-lite": "^0.6.2", "js-yaml": "^4.1.0" @@ -5687,19 +5617,19 @@ } }, "node_modules/electron-builder": { - "version": "26.0.12", - "resolved": "https://registry.npmjs.org/electron-builder/-/electron-builder-26.0.12.tgz", - "integrity": "sha512-cD1kz5g2sgPTMFHjLxfMjUK5JABq3//J4jPswi93tOPFz6btzXYtK5NrDt717NRbukCUDOrrvmYVOWERlqoiXA==", + "version": "26.7.0", + "resolved": "https://registry.npmjs.org/electron-builder/-/electron-builder-26.7.0.tgz", + "integrity": "sha512-LoXbCvSFxLesPneQ/fM7FB4OheIDA2tjqCdUkKlObV5ZKGhYgi5VHPHO/6UUOUodAlg7SrkPx7BZJPby+Vrtbg==", "dev": true, "license": "MIT", "dependencies": { - "app-builder-lib": "26.0.12", - "builder-util": "26.0.11", - "builder-util-runtime": "9.3.1", + "app-builder-lib": "26.7.0", + "builder-util": "26.4.1", + "builder-util-runtime": "9.5.1", "chalk": "^4.1.2", - "dmg-builder": "26.0.12", + "ci-info": "^4.2.0", + "dmg-builder": "26.7.0", "fs-extra": "^10.1.0", - "is-ci": "^3.0.0", "lazy-val": "^1.0.5", "simple-update-notifier": "2.0.0", "yargs": "^17.6.2" @@ -5713,18 +5643,32 @@ } }, "node_modules/electron-builder-squirrel-windows": { - "version": "26.0.12", - "resolved": "https://registry.npmjs.org/electron-builder-squirrel-windows/-/electron-builder-squirrel-windows-26.0.12.tgz", - "integrity": "sha512-kpwXM7c/ayRUbYVErQbsZ0nQZX4aLHQrPEG9C4h9vuJCXylwFH8a7Jgi2VpKIObzCXO7LKHiCw4KdioFLFOgqA==", + "version": "26.7.0", + "resolved": "https://registry.npmjs.org/electron-builder-squirrel-windows/-/electron-builder-squirrel-windows-26.7.0.tgz", + "integrity": "sha512-3EqkQK+q0kGshdPSKEPb2p5F75TENMKu6Fe5aTdeaPfdzFK4Yjp5L0d6S7K8iyvqIsGQ/ei4bnpyX9wt+kVCKQ==", "dev": true, "license": "MIT", "peer": true, "dependencies": { - "app-builder-lib": "26.0.12", - "builder-util": "26.0.11", + "app-builder-lib": "26.7.0", + "builder-util": "26.4.1", "electron-winstaller": "5.4.0" } }, + "node_modules/electron-builder/node_modules/builder-util-runtime": { + "version": "9.5.1", + "resolved": "https://registry.npmjs.org/builder-util-runtime/-/builder-util-runtime-9.5.1.tgz", + "integrity": "sha512-qt41tMfgHTllhResqM5DcnHyDIWNgzHvuY2jDcYP9iaGpkWxTUzV6GQjDeLnlR1/DtdlcsWQbA7sByMpmJFTLQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "^4.3.4", + "sax": "^1.2.4" + }, + "engines": { + "node": ">=12.0.0" + } + }, "node_modules/electron-builder/node_modules/fs-extra": { "version": "10.1.0", "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", @@ -5741,22 +5685,36 @@ } }, "node_modules/electron-publish": { - "version": "26.0.11", - "resolved": "https://registry.npmjs.org/electron-publish/-/electron-publish-26.0.11.tgz", - "integrity": "sha512-a8QRH0rAPIWH9WyyS5LbNvW9Ark6qe63/LqDB7vu2JXYpi0Gma5Q60Dh4tmTqhOBQt0xsrzD8qE7C+D7j+B24A==", + "version": "26.6.0", + "resolved": "https://registry.npmjs.org/electron-publish/-/electron-publish-26.6.0.tgz", + "integrity": "sha512-LsyHMMqbvJ2vsOvuWJ19OezgF2ANdCiHpIucDHNiLhuI+/F3eW98ouzWSRmXXi82ZOPZXC07jnIravY4YYwCLQ==", "dev": true, "license": "MIT", "dependencies": { "@types/fs-extra": "^9.0.11", - "builder-util": "26.0.11", - "builder-util-runtime": "9.3.1", + "builder-util": "26.4.1", + "builder-util-runtime": "9.5.1", "chalk": "^4.1.2", - "form-data": "^4.0.0", + "form-data": "^4.0.5", "fs-extra": "^10.1.0", "lazy-val": "^1.0.5", "mime": "^2.5.2" } }, + "node_modules/electron-publish/node_modules/builder-util-runtime": { + "version": "9.5.1", + "resolved": "https://registry.npmjs.org/builder-util-runtime/-/builder-util-runtime-9.5.1.tgz", + "integrity": "sha512-qt41tMfgHTllhResqM5DcnHyDIWNgzHvuY2jDcYP9iaGpkWxTUzV6GQjDeLnlR1/DtdlcsWQbA7sByMpmJFTLQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "^4.3.4", + "sax": "^1.2.4" + }, + "engines": { + "node": ">=12.0.0" + } + }, "node_modules/electron-publish/node_modules/fs-extra": { "version": "10.1.0", "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", @@ -6273,9 +6231,9 @@ } }, "node_modules/esrap": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/esrap/-/esrap-2.2.1.tgz", - "integrity": "sha512-GiYWG34AN/4CUyaWAgunGt0Rxvr1PTMlGC0vvEov/uOQYWne2bpN03Um+k8jT+q3op33mKouP2zeJ6OlM+qeUg==", + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/esrap/-/esrap-2.2.2.tgz", + "integrity": "sha512-zA6497ha+qKvoWIK+WM9NAh5ni17sKZKhbS5B3PoYbBvaYHZWoS33zmFybmyqpn07RLUxSmn+RCls2/XF+d0oQ==", "dev": true, "license": "MIT", "dependencies": { @@ -6634,16 +6592,16 @@ } }, "node_modules/fs-minipass": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", - "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-3.0.3.tgz", + "integrity": "sha512-XUBA9XClHbnJWSfBzjkm6RvPsyg3sryZt06BEQoXcF7EK/xpGaQYJgQKDJSUH5SGZ76Y7pFx1QBnXz09rU5Fbw==", "dev": true, "license": "ISC", "dependencies": { - "minipass": "^3.0.0" + "minipass": "^7.0.3" }, "engines": { - "node": ">= 8" + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, "node_modules/fs.realpath": { @@ -6785,7 +6743,7 @@ "version": "7.2.3", "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "deprecated": "Glob versions prior to v9 are no longer supported", + "deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me", "dev": true, "license": "ISC", "dependencies": { @@ -7102,16 +7060,6 @@ "node": ">=10.17.0" } }, - "node_modules/humanize-ms": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/humanize-ms/-/humanize-ms-1.2.1.tgz", - "integrity": "sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "ms": "^2.0.0" - } - }, "node_modules/iconv-corefoundation": { "version": "1.1.7", "resolved": "https://registry.npmjs.org/iconv-corefoundation/-/iconv-corefoundation-1.1.7.tgz", @@ -7143,6 +7091,12 @@ "node": ">=0.10.0" } }, + "node_modules/idb-keyval": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/idb-keyval/-/idb-keyval-6.2.2.tgz", + "integrity": "sha512-yjD9nARJ/jb1g+CvD0tlhUHOrJ9Sy0P8T9MF3YaLlHnSRpwPfpTX0XIvpmw3gAJUmEu3FiICLBDPXVwyEvrleg==", + "license": "Apache-2.0" + }, "node_modules/ieee754": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", @@ -7255,13 +7209,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/infer-owner": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/infer-owner/-/infer-owner-1.0.4.tgz", - "integrity": "sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A==", - "dev": true, - "license": "ISC" - }, "node_modules/inflight": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", @@ -7321,19 +7268,6 @@ "dev": true, "license": "MIT" }, - "node_modules/is-ci": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-3.0.1.tgz", - "integrity": "sha512-ZYvCgrefwqoQ6yTyYUbQu64HsITZ3NfKX1lzaEYdkTDcfKzzCI/wthRRYKkdjHKFVgNiXKAKm65Zo1pk2as/QQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "ci-info": "^3.2.0" - }, - "bin": { - "is-ci": "bin.js" - } - }, "node_modules/is-fullwidth-code-point": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", @@ -7354,13 +7288,6 @@ "node": ">=8" } }, - "node_modules/is-lambda": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-lambda/-/is-lambda-1.0.1.tgz", - "integrity": "sha512-z7CMFGNrENq5iFB9Bqo64Xk6Y9sg+epq1myIcdHaGnbMTYOxvzsEtdYqQUylB7LxfkvgrrjP32T6Ywciio9UIQ==", - "dev": true, - "license": "MIT" - }, "node_modules/is-number": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", @@ -8008,16 +7935,16 @@ } }, "node_modules/lodash": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "version": "4.17.23", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.23.tgz", + "integrity": "sha512-LgVTMpQtIopCi79SJeDiP0TfWi5CNEc/L/aRdTh3yIvmZXTnheWpKjSZhnvMl8iXbC1tFg9gdHHDMLoV7CnG+w==", "dev": true, "license": "MIT" }, "node_modules/lodash-es": { - "version": "4.17.22", - "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.22.tgz", - "integrity": "sha512-XEawp1t0gxSi9x01glktRZ5HDy0HXqrM0x5pXQM98EaI0NxO6jVM7omDOxsuEo5UIASAnm2bRp1Jt/e0a2XU8Q==", + "version": "4.17.23", + "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.23.tgz", + "integrity": "sha512-kVI48u3PZr38HdYz98UmfPnXl2DXrpdctLrFLCd3kOx1xUkOmpFPx7gCWWM5MPkL/fD8zb+Ph0QzjGFs4+hHWg==", "dev": true, "license": "MIT" }, @@ -8150,83 +8077,26 @@ } }, "node_modules/make-fetch-happen": { - "version": "10.2.1", - "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-10.2.1.tgz", - "integrity": "sha512-NgOPbRiaQM10DYXvN3/hhGVI2M5MtITFryzBGxHM5p4wnFxsVCbxkrBrDsk+EZ5OB4jEOT7AjDxtdF+KVEFT7w==", - "dev": true, - "license": "ISC", - "dependencies": { - "agentkeepalive": "^4.2.1", - "cacache": "^16.1.0", - "http-cache-semantics": "^4.1.0", - "http-proxy-agent": "^5.0.0", - "https-proxy-agent": "^5.0.0", - "is-lambda": "^1.0.1", - "lru-cache": "^7.7.1", - "minipass": "^3.1.6", - "minipass-collect": "^1.0.2", - "minipass-fetch": "^2.0.3", + "version": "14.0.3", + "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-14.0.3.tgz", + "integrity": "sha512-QMjGbFTP0blj97EeidG5hk/QhKQ3T4ICckQGLgz38QF7Vgbk6e6FTARN8KhKxyBbWn8R0HU+bnw8aSoFPD4qtQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "@npmcli/agent": "^3.0.0", + "cacache": "^19.0.1", + "http-cache-semantics": "^4.1.1", + "minipass": "^7.0.2", + "minipass-fetch": "^4.0.0", "minipass-flush": "^1.0.5", "minipass-pipeline": "^1.2.4", - "negotiator": "^0.6.3", + "negotiator": "^1.0.0", + "proc-log": "^5.0.0", "promise-retry": "^2.0.1", - "socks-proxy-agent": "^7.0.0", - "ssri": "^9.0.0" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/make-fetch-happen/node_modules/agent-base": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", - "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "debug": "4" - }, - "engines": { - "node": ">= 6.0.0" - } - }, - "node_modules/make-fetch-happen/node_modules/http-proxy-agent": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz", - "integrity": "sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==", - "dev": true, - "license": "MIT", - "dependencies": { - "@tootallnate/once": "2", - "agent-base": "6", - "debug": "4" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/make-fetch-happen/node_modules/https-proxy-agent": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", - "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", - "dev": true, - "license": "MIT", - "dependencies": { - "agent-base": "6", - "debug": "4" + "ssri": "^12.0.0" }, "engines": { - "node": ">= 6" - } - }, - "node_modules/make-fetch-happen/node_modules/lru-cache": { - "version": "7.18.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", - "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", - "dev": true, - "license": "ISC", - "engines": { - "node": ">=12" + "node": "^18.17.0 || >=20.5.0" } }, "node_modules/marked": { @@ -8390,13 +8260,13 @@ } }, "node_modules/minimatch": { - "version": "10.1.1", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.1.1.tgz", - "integrity": "sha512-enIvLvRAFZYXJzkCYG5RKmPfrFArdLv+R+lbQ53BmIMLIry74bjKzX6iHAm8WYamJkhSSEabrWN5D97XnKObjQ==", + "version": "10.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.1.2.tgz", + "integrity": "sha512-fu656aJ0n2kcXwsnwnv9g24tkU5uSmOlTjd6WyyaKm2Z+h1qmY6bAjrcaIxF/BslFqbZ8UBtbJi7KgQOZD2PTw==", "dev": true, "license": "BlueOak-1.0.0", "dependencies": { - "@isaacs/brace-expansion": "^5.0.0" + "@isaacs/brace-expansion": "^5.0.1" }, "engines": { "node": "20 || >=22" @@ -8416,44 +8286,40 @@ } }, "node_modules/minipass": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", - "dev": true, + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", + "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", "license": "ISC", - "dependencies": { - "yallist": "^4.0.0" - }, "engines": { - "node": ">=8" + "node": ">=16 || 14 >=14.17" } }, "node_modules/minipass-collect": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/minipass-collect/-/minipass-collect-1.0.2.tgz", - "integrity": "sha512-6T6lH0H8OG9kITm/Jm6tdooIbogG9e0tLgpY6mphXSm/A9u8Nq1ryBG+Qspiub9LjWlBPsPS3tWQ/Botq4FdxA==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/minipass-collect/-/minipass-collect-2.0.1.tgz", + "integrity": "sha512-D7V8PO9oaz7PWGLbCACuI1qEOsq7UKfLotx/C0Aet43fCUB/wfQ7DYeq2oR/svFJGYDHPr38SHATeaj/ZoKHKw==", "dev": true, "license": "ISC", "dependencies": { - "minipass": "^3.0.0" + "minipass": "^7.0.3" }, "engines": { - "node": ">= 8" + "node": ">=16 || 14 >=14.17" } }, "node_modules/minipass-fetch": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-2.1.2.tgz", - "integrity": "sha512-LT49Zi2/WMROHYoqGgdlQIZh8mLPZmOrN2NdJjMXxYe4nkN6FUyuPuOAOedNJDrx0IRGg9+4guZewtp8hE6TxA==", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-4.0.1.tgz", + "integrity": "sha512-j7U11C5HXigVuutxebFadoYBbd7VSdZWggSe64NVdvWNBqGAiXPL2QVCehjmw7lY1oF9gOllYbORh+hiNgfPgQ==", "dev": true, "license": "MIT", "dependencies": { - "minipass": "^3.1.6", + "minipass": "^7.0.3", "minipass-sized": "^1.0.3", - "minizlib": "^2.1.2" + "minizlib": "^3.0.1" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + "node": "^18.17.0 || >=20.5.0" }, "optionalDependencies": { "encoding": "^0.1.13" @@ -8472,6 +8338,19 @@ "node": ">= 8" } }, + "node_modules/minipass-flush/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dev": true, + "license": "ISC", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/minipass-pipeline": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/minipass-pipeline/-/minipass-pipeline-1.2.4.tgz", @@ -8485,6 +8364,19 @@ "node": ">=8" } }, + "node_modules/minipass-pipeline/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dev": true, + "license": "ISC", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/minipass-sized": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/minipass-sized/-/minipass-sized-1.0.3.tgz", @@ -8498,31 +8390,43 @@ "node": ">=8" } }, - "node_modules/minizlib": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", - "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", + "node_modules/minipass-sized/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", "dev": true, - "license": "MIT", + "license": "ISC", "dependencies": { - "minipass": "^3.0.0", "yallist": "^4.0.0" }, "engines": { - "node": ">= 8" + "node": ">=8" + } + }, + "node_modules/minizlib": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-3.1.0.tgz", + "integrity": "sha512-KZxYo1BUkWD2TVFLr0MQoM8vUUigWD3LlD83a/75BqC+4qE0Hb1Vo5v1FgcfaNXvfXzr+5EhQ6ing/CaBijTlw==", + "license": "MIT", + "dependencies": { + "minipass": "^7.1.2" + }, + "engines": { + "node": ">= 18" } }, "node_modules/mkdirp": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", + "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", "dev": true, "license": "MIT", + "peer": true, + "dependencies": { + "minimist": "^1.2.6" + }, "bin": { "mkdirp": "bin/cmd.js" - }, - "engines": { - "node": ">=10" } }, "node_modules/mri": { @@ -8583,9 +8487,9 @@ } }, "node_modules/negotiator": { - "version": "0.6.4", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.4.tgz", - "integrity": "sha512-myRT3DiWPHqho5PrJaIRyaMv2kgYf0mUVgBNOYMuCH5Ki1yEiQaf/ZJuQ62nvpc44wL5WDbTX7yGJi1Neevw8w==", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-1.0.0.tgz", + "integrity": "sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg==", "dev": true, "license": "MIT", "engines": { @@ -8607,16 +8511,16 @@ "license": "MIT" }, "node_modules/node-abi": { - "version": "3.85.0", - "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.85.0.tgz", - "integrity": "sha512-zsFhmbkAzwhTft6nd3VxcG0cvJsT70rL+BIGHWVq5fi6MwGrHwzqKaxXE+Hl2GmnGItnDKPPkO5/LQqjVkIdFg==", + "version": "4.26.0", + "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-4.26.0.tgz", + "integrity": "sha512-8QwIZqikRvDIkXS2S93LjzhsSPJuIbfaMETWH+Bx8oOT9Sa9UsUtBFQlc3gBNd1+QINjaTloitXr1W3dQLi9Iw==", "dev": true, "license": "MIT", "dependencies": { - "semver": "^7.3.5" + "semver": "^7.6.3" }, "engines": { - "node": ">=10" + "node": ">=22.12.0" } }, "node_modules/node-abi/node_modules/semver": { @@ -8679,20 +8583,84 @@ "node": ">=18" } }, + "node_modules/node-gyp": { + "version": "11.5.0", + "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-11.5.0.tgz", + "integrity": "sha512-ra7Kvlhxn5V9Slyus0ygMa2h+UqExPqUIkfk7Pc8QTLT956JLSy51uWFwHtIYy0vI8cB4BDhc/S03+880My/LQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "env-paths": "^2.2.0", + "exponential-backoff": "^3.1.1", + "graceful-fs": "^4.2.6", + "make-fetch-happen": "^14.0.3", + "nopt": "^8.0.0", + "proc-log": "^5.0.0", + "semver": "^7.3.5", + "tar": "^7.4.3", + "tinyglobby": "^0.2.12", + "which": "^5.0.0" + }, + "bin": { + "node-gyp": "bin/node-gyp.js" + }, + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/node-gyp/node_modules/isexe": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-3.1.1.tgz", + "integrity": "sha512-LpB/54B+/2J5hqQ7imZHfdU31OlgQqx7ZicVlkm9kzg9/w8GKLEcFfJl/t7DCEDueOyBAD6zCCwTO6Fzs0NoEQ==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=16" + } + }, + "node_modules/node-gyp/node_modules/semver": { + "version": "7.7.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz", + "integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/node-gyp/node_modules/which": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/which/-/which-5.0.0.tgz", + "integrity": "sha512-JEdGzHwwkrbWoGOlIHqQ5gtprKGOenpDHpxE9zVR1bWbOtYRyPPHMe9FaP6x61CmNaTThSkb0DAJte5jD+DmzQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "isexe": "^3.1.1" + }, + "bin": { + "node-which": "bin/which.js" + }, + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, "node_modules/nopt": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-6.0.0.tgz", - "integrity": "sha512-ZwLpbTgdhuZUnZzjd7nb1ZV+4DoiC6/sfiVKok72ym/4Tlf+DFdlHYmT2JPmcNNWV6Pi3SDf1kT+A4r9RTuT9g==", + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-8.1.0.tgz", + "integrity": "sha512-ieGu42u/Qsa4TFktmaKEwM6MQH0pOWnaB3htzh0JRtx84+Mebc0cbZYN5bC+6WTZ4+77xrL9Pn5m7CV6VIkV7A==", "dev": true, "license": "ISC", "dependencies": { - "abbrev": "^1.0.0" + "abbrev": "^3.0.0" }, "bin": { "nopt": "bin/nopt.js" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + "node": "^18.17.0 || >=20.5.0" } }, "node_modules/normalize-package-data": { @@ -8760,9 +8728,9 @@ } }, "node_modules/npm": { - "version": "11.7.0", - "resolved": "https://registry.npmjs.org/npm/-/npm-11.7.0.tgz", - "integrity": "sha512-wiCZpv/41bIobCoJ31NStIWKfAxxYyD1iYnWCtiyns8s5v3+l8y0HCP/sScuH6B5+GhIfda4HQKiqeGZwJWhFw==", + "version": "11.9.0", + "resolved": "https://registry.npmjs.org/npm/-/npm-11.9.0.tgz", + "integrity": "sha512-BBZoU926FCypj4b7V7ElinxsWcy4Kss88UG3ejFYmKyq7Uc5XnT34Me2nEhgCOaL5qY4HvGu5aI92C4OYd7NaA==", "bundleDependencies": [ "@isaacs/string-locale-compare", "@npmcli/arborist", @@ -8842,8 +8810,8 @@ ], "dependencies": { "@isaacs/string-locale-compare": "^1.1.0", - "@npmcli/arborist": "^9.1.9", - "@npmcli/config": "^10.4.5", + "@npmcli/arborist": "^9.2.0", + "@npmcli/config": "^10.6.0", "@npmcli/fs": "^5.0.0", "@npmcli/map-workspaces": "^5.0.3", "@npmcli/metavuln-calculator": "^9.0.3", @@ -8851,12 +8819,12 @@ "@npmcli/promise-spawn": "^9.0.1", "@npmcli/redact": "^4.0.0", "@npmcli/run-script": "^10.0.3", - "@sigstore/tuf": "^4.0.0", + "@sigstore/tuf": "^4.0.1", "abbrev": "^4.0.0", "archy": "~1.0.0", "cacache": "^20.0.3", "chalk": "^5.6.2", - "ci-info": "^4.3.1", + "ci-info": "^4.4.0", "cli-columns": "^4.0.0", "fastest-levenshtein": "^1.0.16", "fs-minipass": "^3.0.3", @@ -8868,11 +8836,11 @@ "is-cidr": "^6.0.1", "json-parse-even-better-errors": "^5.0.0", "libnpmaccess": "^10.0.3", - "libnpmdiff": "^8.0.12", - "libnpmexec": "^10.1.11", - "libnpmfund": "^7.0.12", + "libnpmdiff": "^8.1.0", + "libnpmexec": "^10.2.0", + "libnpmfund": "^7.0.14", "libnpmorg": "^8.0.1", - "libnpmpack": "^9.0.12", + "libnpmpack": "^9.1.0", "libnpmpublish": "^11.1.3", "libnpmsearch": "^9.0.1", "libnpmteam": "^8.0.2", @@ -8882,7 +8850,7 @@ "minipass": "^7.1.1", "minipass-pipeline": "^1.2.4", "ms": "^2.1.2", - "node-gyp": "^12.1.0", + "node-gyp": "^12.2.0", "nopt": "^9.0.0", "npm-audit-report": "^7.0.0", "npm-install-checks": "^8.0.0", @@ -8892,7 +8860,7 @@ "npm-registry-fetch": "^19.1.1", "npm-user-validate": "^4.0.0", "p-map": "^7.0.4", - "pacote": "^21.0.4", + "pacote": "^21.1.0", "parse-conflict-json": "^5.0.1", "proc-log": "^6.1.0", "qrcode-terminal": "^0.12.0", @@ -8901,11 +8869,11 @@ "spdx-expression-parse": "^4.0.0", "ssri": "^13.0.0", "supports-color": "^10.2.2", - "tar": "^7.5.2", + "tar": "^7.5.7", "text-table": "~0.2.0", "tiny-relative-date": "^2.0.2", "treeverse": "^3.0.0", - "validate-npm-package-name": "^7.0.0", + "validate-npm-package-name": "^7.0.2", "which": "^6.0.0" }, "bin": { @@ -8939,7 +8907,7 @@ } }, "node_modules/npm/node_modules/@isaacs/brace-expansion": { - "version": "5.0.0", + "version": "5.0.1", "dev": true, "inBundle": true, "license": "MIT", @@ -8985,7 +8953,7 @@ } }, "node_modules/npm/node_modules/@npmcli/arborist": { - "version": "9.1.9", + "version": "9.2.0", "dev": true, "inBundle": true, "license": "ISC", @@ -9003,7 +8971,7 @@ "@npmcli/run-script": "^10.0.0", "bin-links": "^6.0.0", "cacache": "^20.0.1", - "common-ancestor-path": "^1.0.1", + "common-ancestor-path": "^2.0.0", "hosted-git-info": "^9.0.0", "json-stringify-nice": "^1.1.4", "lru-cache": "^11.2.1", @@ -9032,7 +9000,7 @@ } }, "node_modules/npm/node_modules/@npmcli/config": { - "version": "10.4.5", + "version": "10.6.0", "dev": true, "inBundle": true, "license": "ISC", @@ -9227,7 +9195,7 @@ } }, "node_modules/npm/node_modules/@sigstore/core": { - "version": "3.0.0", + "version": "3.1.0", "dev": true, "inBundle": true, "license": "Apache-2.0", @@ -9245,52 +9213,43 @@ } }, "node_modules/npm/node_modules/@sigstore/sign": { - "version": "4.0.1", + "version": "4.1.0", "dev": true, "inBundle": true, "license": "Apache-2.0", "dependencies": { "@sigstore/bundle": "^4.0.0", - "@sigstore/core": "^3.0.0", + "@sigstore/core": "^3.1.0", "@sigstore/protobuf-specs": "^0.5.0", - "make-fetch-happen": "^15.0.2", - "proc-log": "^5.0.0", + "make-fetch-happen": "^15.0.3", + "proc-log": "^6.1.0", "promise-retry": "^2.0.1" }, "engines": { - "node": "^20.17.0 || >=22.9.0" - } - }, - "node_modules/npm/node_modules/@sigstore/sign/node_modules/proc-log": { - "version": "5.0.0", - "dev": true, - "inBundle": true, - "license": "ISC", - "engines": { - "node": "^18.17.0 || >=20.5.0" + "node": "^20.17.0 || >=22.9.0" } }, "node_modules/npm/node_modules/@sigstore/tuf": { - "version": "4.0.0", + "version": "4.0.1", "dev": true, "inBundle": true, "license": "Apache-2.0", "dependencies": { "@sigstore/protobuf-specs": "^0.5.0", - "tuf-js": "^4.0.0" + "tuf-js": "^4.1.0" }, "engines": { "node": "^20.17.0 || >=22.9.0" } }, "node_modules/npm/node_modules/@sigstore/verify": { - "version": "3.0.0", + "version": "3.1.0", "dev": true, "inBundle": true, "license": "Apache-2.0", "dependencies": { "@sigstore/bundle": "^4.0.0", - "@sigstore/core": "^3.0.0", + "@sigstore/core": "^3.1.0", "@sigstore/protobuf-specs": "^0.5.0" }, "engines": { @@ -9307,33 +9266,18 @@ } }, "node_modules/npm/node_modules/@tufjs/models": { - "version": "4.0.0", + "version": "4.1.0", "dev": true, "inBundle": true, "license": "MIT", "dependencies": { "@tufjs/canonical-json": "2.0.0", - "minimatch": "^9.0.5" + "minimatch": "^10.1.1" }, "engines": { "node": "^20.17.0 || >=22.9.0" } }, - "node_modules/npm/node_modules/@tufjs/models/node_modules/minimatch": { - "version": "9.0.5", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/npm/node_modules/abbrev": { "version": "4.0.0", "dev": true, @@ -9373,12 +9317,6 @@ "inBundle": true, "license": "MIT" }, - "node_modules/npm/node_modules/balanced-match": { - "version": "1.0.2", - "dev": true, - "inBundle": true, - "license": "MIT" - }, "node_modules/npm/node_modules/bin-links": { "version": "6.0.0", "dev": true, @@ -9407,15 +9345,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/npm/node_modules/brace-expansion": { - "version": "2.0.2", - "dev": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0" - } - }, "node_modules/npm/node_modules/cacache": { "version": "20.0.3", "dev": true, @@ -9460,7 +9389,7 @@ } }, "node_modules/npm/node_modules/ci-info": { - "version": "4.3.1", + "version": "4.4.0", "dev": true, "funding": [ { @@ -9509,10 +9438,13 @@ } }, "node_modules/npm/node_modules/common-ancestor-path": { - "version": "1.0.1", + "version": "2.0.0", "dev": true, "inBundle": true, - "license": "ISC" + "license": "BlueOak-1.0.0", + "engines": { + "node": ">= 18" + } }, "node_modules/npm/node_modules/cssesc": { "version": "3.0.0", @@ -9544,7 +9476,7 @@ } }, "node_modules/npm/node_modules/diff": { - "version": "8.0.2", + "version": "8.0.3", "dev": true, "inBundle": true, "license": "BSD-3-Clause", @@ -9611,12 +9543,12 @@ } }, "node_modules/npm/node_modules/glob": { - "version": "13.0.0", + "version": "13.0.1", "dev": true, "inBundle": true, "license": "BlueOak-1.0.0", "dependencies": { - "minimatch": "^10.1.1", + "minimatch": "^10.1.2", "minipass": "^7.1.2", "path-scurry": "^2.0.0" }, @@ -9739,7 +9671,7 @@ } }, "node_modules/npm/node_modules/ip-address": { - "version": "10.0.1", + "version": "10.1.0", "dev": true, "inBundle": true, "license": "MIT", @@ -9760,12 +9692,12 @@ } }, "node_modules/npm/node_modules/is-cidr": { - "version": "6.0.1", + "version": "6.0.2", "dev": true, "inBundle": true, "license": "BSD-2-Clause", "dependencies": { - "cidr-regex": "5.0.1" + "cidr-regex": "^5.0.1" }, "engines": { "node": ">=20" @@ -9842,12 +9774,12 @@ } }, "node_modules/npm/node_modules/libnpmdiff": { - "version": "8.0.12", + "version": "8.1.0", "dev": true, "inBundle": true, "license": "ISC", "dependencies": { - "@npmcli/arborist": "^9.1.9", + "@npmcli/arborist": "^9.2.0", "@npmcli/installed-package-contents": "^4.0.0", "binary-extensions": "^3.0.0", "diff": "^8.0.2", @@ -9861,12 +9793,12 @@ } }, "node_modules/npm/node_modules/libnpmexec": { - "version": "10.1.11", + "version": "10.2.0", "dev": true, "inBundle": true, "license": "ISC", "dependencies": { - "@npmcli/arborist": "^9.1.9", + "@npmcli/arborist": "^9.2.0", "@npmcli/package-json": "^7.0.0", "@npmcli/run-script": "^10.0.0", "ci-info": "^4.0.0", @@ -9884,12 +9816,12 @@ } }, "node_modules/npm/node_modules/libnpmfund": { - "version": "7.0.12", + "version": "7.0.14", "dev": true, "inBundle": true, "license": "ISC", "dependencies": { - "@npmcli/arborist": "^9.1.9" + "@npmcli/arborist": "^9.2.0" }, "engines": { "node": "^20.17.0 || >=22.9.0" @@ -9909,12 +9841,12 @@ } }, "node_modules/npm/node_modules/libnpmpack": { - "version": "9.0.12", + "version": "9.1.0", "dev": true, "inBundle": true, "license": "ISC", "dependencies": { - "@npmcli/arborist": "^9.1.9", + "@npmcli/arborist": "^9.2.0", "@npmcli/run-script": "^10.0.0", "npm-package-arg": "^13.0.0", "pacote": "^21.0.2" @@ -9984,10 +9916,10 @@ } }, "node_modules/npm/node_modules/lru-cache": { - "version": "11.2.2", + "version": "11.2.5", "dev": true, "inBundle": true, - "license": "ISC", + "license": "BlueOak-1.0.0", "engines": { "node": "20 || >=22" } @@ -10015,12 +9947,12 @@ } }, "node_modules/npm/node_modules/minimatch": { - "version": "10.1.1", + "version": "10.1.2", "dev": true, "inBundle": true, "license": "BlueOak-1.0.0", "dependencies": { - "@isaacs/brace-expansion": "^5.0.0" + "@isaacs/brace-expansion": "^5.0.1" }, "engines": { "node": "20 || >=22" @@ -10051,13 +9983,13 @@ } }, "node_modules/npm/node_modules/minipass-fetch": { - "version": "5.0.0", + "version": "5.0.1", "dev": true, "inBundle": true, "license": "MIT", "dependencies": { "minipass": "^7.0.3", - "minipass-sized": "^1.0.3", + "minipass-sized": "^2.0.0", "minizlib": "^3.0.1" }, "engines": { @@ -10116,24 +10048,12 @@ } }, "node_modules/npm/node_modules/minipass-sized": { - "version": "1.0.3", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "minipass": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/npm/node_modules/minipass-sized/node_modules/minipass": { - "version": "3.3.6", + "version": "2.0.0", "dev": true, "inBundle": true, "license": "ISC", "dependencies": { - "yallist": "^4.0.0" + "minipass": "^7.1.2" }, "engines": { "node": ">=8" @@ -10176,7 +10096,7 @@ } }, "node_modules/npm/node_modules/node-gyp": { - "version": "12.1.0", + "version": "12.2.0", "dev": true, "inBundle": true, "license": "MIT", @@ -10188,7 +10108,7 @@ "nopt": "^9.0.0", "proc-log": "^6.0.0", "semver": "^7.3.5", - "tar": "^7.5.2", + "tar": "^7.5.4", "tinyglobby": "^0.2.12", "which": "^6.0.0" }, @@ -10353,7 +10273,7 @@ } }, "node_modules/npm/node_modules/pacote": { - "version": "21.0.4", + "version": "21.1.0", "dev": true, "inBundle": true, "license": "ISC", @@ -10398,7 +10318,7 @@ } }, "node_modules/npm/node_modules/path-scurry": { - "version": "2.0.0", + "version": "2.0.1", "dev": true, "inBundle": true, "license": "BlueOak-1.0.0", @@ -10414,7 +10334,7 @@ } }, "node_modules/npm/node_modules/postcss-selector-parser": { - "version": "7.1.0", + "version": "7.1.1", "dev": true, "inBundle": true, "license": "MIT", @@ -10557,17 +10477,17 @@ } }, "node_modules/npm/node_modules/sigstore": { - "version": "4.0.0", + "version": "4.1.0", "dev": true, "inBundle": true, "license": "Apache-2.0", "dependencies": { "@sigstore/bundle": "^4.0.0", - "@sigstore/core": "^3.0.0", + "@sigstore/core": "^3.1.0", "@sigstore/protobuf-specs": "^0.5.0", - "@sigstore/sign": "^4.0.0", - "@sigstore/tuf": "^4.0.0", - "@sigstore/verify": "^3.0.0" + "@sigstore/sign": "^4.1.0", + "@sigstore/tuf": "^4.0.1", + "@sigstore/verify": "^3.1.0" }, "engines": { "node": "^20.17.0 || >=22.9.0" @@ -10704,7 +10624,7 @@ } }, "node_modules/npm/node_modules/tar": { - "version": "7.5.2", + "version": "7.5.7", "dev": true, "inBundle": true, "license": "BlueOak-1.0.0", @@ -10795,14 +10715,14 @@ } }, "node_modules/npm/node_modules/tuf-js": { - "version": "4.0.0", + "version": "4.1.0", "dev": true, "inBundle": true, "license": "MIT", "dependencies": { - "@tufjs/models": "4.0.0", - "debug": "^4.4.1", - "make-fetch-happen": "^15.0.0" + "@tufjs/models": "4.1.0", + "debug": "^4.4.3", + "make-fetch-happen": "^15.0.1" }, "engines": { "node": "^20.17.0 || >=22.9.0" @@ -10859,7 +10779,7 @@ } }, "node_modules/npm/node_modules/validate-npm-package-name": { - "version": "7.0.0", + "version": "7.0.2", "dev": true, "inBundle": true, "license": "ISC", @@ -10978,61 +10898,6 @@ "tar": "^7.0.1" } }, - "node_modules/onnxruntime-node/node_modules/chownr": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-3.0.0.tgz", - "integrity": "sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g==", - "license": "BlueOak-1.0.0", - "engines": { - "node": ">=18" - } - }, - "node_modules/onnxruntime-node/node_modules/minipass": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", - "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", - "license": "ISC", - "engines": { - "node": ">=16 || 14 >=14.17" - } - }, - "node_modules/onnxruntime-node/node_modules/minizlib": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-3.1.0.tgz", - "integrity": "sha512-KZxYo1BUkWD2TVFLr0MQoM8vUUigWD3LlD83a/75BqC+4qE0Hb1Vo5v1FgcfaNXvfXzr+5EhQ6ing/CaBijTlw==", - "license": "MIT", - "dependencies": { - "minipass": "^7.1.2" - }, - "engines": { - "node": ">= 18" - } - }, - "node_modules/onnxruntime-node/node_modules/tar": { - "version": "7.5.2", - "resolved": "https://registry.npmjs.org/tar/-/tar-7.5.2.tgz", - "integrity": "sha512-7NyxrTE4Anh8km8iEy7o0QYPs+0JKBTj5ZaqHg6B39erLg0qYXN3BijtShwbsNSvQ+LN75+KV+C4QR/f6Gwnpg==", - "license": "BlueOak-1.0.0", - "dependencies": { - "@isaacs/fs-minipass": "^4.0.0", - "chownr": "^3.0.0", - "minipass": "^7.1.2", - "minizlib": "^3.1.0", - "yallist": "^5.0.0" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/onnxruntime-node/node_modules/yallist": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-5.0.0.tgz", - "integrity": "sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw==", - "license": "BlueOak-1.0.0", - "engines": { - "node": ">=18" - } - }, "node_modules/onnxruntime-web": { "version": "1.22.0-dev.20250409-89f8206ba4", "resolved": "https://registry.npmjs.org/onnxruntime-web/-/onnxruntime-web-1.22.0-dev.20250409-89f8206ba4.tgz", @@ -11132,19 +10997,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/p-filter/node_modules/p-map": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/p-map/-/p-map-7.0.4.tgz", - "integrity": "sha512-tkAQEw8ysMzmkhgw8k+1U/iPhWNhykKnSk4Rd5zLoPJCuJaGRPo6YposrZgaxHKzDHdDWWZvE/Sk7hsL2X/CpQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/p-is-promise": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/p-is-promise/-/p-is-promise-3.0.0.tgz", @@ -11198,16 +11050,13 @@ } }, "node_modules/p-map": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", - "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-7.0.4.tgz", + "integrity": "sha512-tkAQEw8ysMzmkhgw8k+1U/iPhWNhykKnSk4Rd5zLoPJCuJaGRPo6YposrZgaxHKzDHdDWWZvE/Sk7hsL2X/CpQ==", "dev": true, "license": "MIT", - "dependencies": { - "aggregate-error": "^3.0.0" - }, "engines": { - "node": ">=10" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -11382,16 +11231,6 @@ "dev": true, "license": "ISC" }, - "node_modules/path-scurry/node_modules/minipass": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", - "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", - "dev": true, - "license": "ISC", - "engines": { - "node": ">=16 || 14 >=14.17" - } - }, "node_modules/path-type": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", @@ -11565,13 +11404,13 @@ } }, "node_modules/proc-log": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/proc-log/-/proc-log-2.0.1.tgz", - "integrity": "sha512-Kcmo2FhfDTXdcbfDH76N7uBYHINxc/8GW7UAVuVP9I+Va3uHSerrnKV6dLooga/gh7GlgzuCCr/eoldnL1muGw==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/proc-log/-/proc-log-5.0.0.tgz", + "integrity": "sha512-Azwzvl90HaF0aCz1JrDdXQykFakSSNPaPoiZ9fm5qJIMHioDZEi7OAdRwSm6rSoPtY3Qutnm3L7ogmg3dc+wbQ==", "dev": true, "license": "ISC", "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + "node": "^18.17.0 || >=20.5.0" } }, "node_modules/process-nextick-args": { @@ -11590,13 +11429,6 @@ "node": ">=0.4.0" } }, - "node_modules/promise-inflight": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz", - "integrity": "sha512-6zWPyEOFaQBJYcGMHBKTKJ3u6TBsnMFOIZSa6ce1e/ZrrsOlnHRHbabMjLiBYKp+n44X9eUI6VUPaukCXHuG4g==", - "dev": true, - "license": "ISC" - }, "node_modules/promise-retry": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/promise-retry/-/promise-retry-2.0.1.tgz", @@ -11611,6 +11443,18 @@ "node": ">=10" } }, + "node_modules/proper-lockfile": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/proper-lockfile/-/proper-lockfile-4.1.2.tgz", + "integrity": "sha512-TjNPblN4BwAWMXU8s9AEz4JmQxnD1NNL7bNOY/AKUzyamc379FWASUhc/K1pL2noVb+XmZKLL68cjzLsiOAMaA==", + "dev": true, + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.4", + "retry": "^0.12.0", + "signal-exit": "^3.0.2" + } + }, "node_modules/proto-list": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/proto-list/-/proto-list-1.2.4.tgz", @@ -11906,20 +11750,18 @@ } }, "node_modules/rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", + "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", "deprecated": "Rimraf versions prior to v4 are no longer supported", "dev": true, "license": "ISC", + "peer": true, "dependencies": { "glob": "^7.1.3" }, "bin": { "rimraf": "bin.js" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" } }, "node_modules/roarr": { @@ -12520,9 +12362,9 @@ } }, "node_modules/set-cookie-parser": { - "version": "2.7.2", - "resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-2.7.2.tgz", - "integrity": "sha512-oeM1lpU/UvhTxw+g3cIfxXHyJRc/uidd3yK1P242gzHds0udQBYzs3y8j4gCCW+ZJ7ad0yctld8RYO+bdurlvw==", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-3.0.1.tgz", + "integrity": "sha512-n7Z7dXZhJbwuAHhNzkTti6Aw9QDDjZtm3JTpTGATIdNzdQz5GuFs22w90BcvF4INfnrL5xrX3oGsuqO5Dx3A1Q==", "dev": true, "license": "MIT" }, @@ -12834,31 +12676,18 @@ } }, "node_modules/socks-proxy-agent": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-7.0.0.tgz", - "integrity": "sha512-Fgl0YPZ902wEsAyiQ+idGd1A7rSFx/ayC1CQVMw5P+EQx2V0SgpGtf6OKFhVjPflPUl9YMmEOnmfjCdMUsygww==", - "dev": true, - "license": "MIT", - "dependencies": { - "agent-base": "^6.0.2", - "debug": "^4.3.3", - "socks": "^2.6.2" - }, - "engines": { - "node": ">= 10" - } - }, - "node_modules/socks-proxy-agent/node_modules/agent-base": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", - "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "version": "8.0.5", + "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-8.0.5.tgz", + "integrity": "sha512-HehCEsotFqbPW9sJ8WVYB6UbmIMv7kUUORIF2Nncq4VQvBfNBLibW9YZR5dlYCSUhwcD628pRllm7n+E+YTzJw==", "dev": true, "license": "MIT", "dependencies": { - "debug": "4" + "agent-base": "^7.1.2", + "debug": "^4.3.4", + "socks": "^2.8.3" }, "engines": { - "node": ">= 6.0.0" + "node": ">= 14" } }, "node_modules/source-map": { @@ -12964,16 +12793,16 @@ } }, "node_modules/ssri": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/ssri/-/ssri-9.0.1.tgz", - "integrity": "sha512-o57Wcn66jMQvfHG1FlYbWeZWW/dHZhJXjpIcTfXldXEk5nz5lStPo3mK0OJQfGR3RbZUlbISexbljkJzuEj/8Q==", + "version": "12.0.0", + "resolved": "https://registry.npmjs.org/ssri/-/ssri-12.0.0.tgz", + "integrity": "sha512-S7iGNosepx9RadX82oimUkvr0Ct7IjJbEbs4mJcTxst8um95J3sDYU1RBEOvdu6oL1Wek2ODI5i4MAw+dZ6cAQ==", "dev": true, "license": "ISC", "dependencies": { - "minipass": "^3.1.1" + "minipass": "^7.0.3" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + "node": "^18.17.0 || >=20.5.0" } }, "node_modules/stat-mode": { @@ -13192,9 +13021,9 @@ } }, "node_modules/svelte": { - "version": "5.46.1", - "resolved": "https://registry.npmjs.org/svelte/-/svelte-5.46.1.tgz", - "integrity": "sha512-ynjfCHD3nP2el70kN5Pmg37sSi0EjOm9FgHYQdC4giWG/hzO3AatzXXJJgP305uIhGQxSufJLuYWtkY8uK/8RA==", + "version": "5.49.2", + "resolved": "https://registry.npmjs.org/svelte/-/svelte-5.49.2.tgz", + "integrity": "sha512-PYLwnngYzyhKzqDlGVlCH4z+NVI8mC0/bTv15vw25CcdOhxENsOHIbQ36oj5DIf3oBazM+STbCAvaskpxtBmWA==", "dev": true, "license": "MIT", "dependencies": { @@ -13206,9 +13035,9 @@ "aria-query": "^5.3.1", "axobject-query": "^4.1.0", "clsx": "^2.1.1", - "devalue": "^5.5.0", + "devalue": "^5.6.2", "esm-env": "^1.2.1", - "esrap": "^2.2.1", + "esrap": "^2.2.2", "is-reference": "^3.0.3", "locate-character": "^3.0.0", "magic-string": "^0.30.11", @@ -13295,31 +13124,28 @@ } }, "node_modules/tar": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.1.tgz", - "integrity": "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==", - "dev": true, - "license": "ISC", + "version": "7.5.7", + "resolved": "https://registry.npmjs.org/tar/-/tar-7.5.7.tgz", + "integrity": "sha512-fov56fJiRuThVFXD6o6/Q354S7pnWMJIVlDBYijsTNx6jKSE4pvrDTs6lUnmGvNyfJwFQQwWy3owKz1ucIhveQ==", + "license": "BlueOak-1.0.0", "dependencies": { - "chownr": "^2.0.0", - "fs-minipass": "^2.0.0", - "minipass": "^5.0.0", - "minizlib": "^2.1.1", - "mkdirp": "^1.0.3", - "yallist": "^4.0.0" + "@isaacs/fs-minipass": "^4.0.0", + "chownr": "^3.0.0", + "minipass": "^7.1.2", + "minizlib": "^3.1.0", + "yallist": "^5.0.0" }, "engines": { - "node": ">=10" + "node": ">=18" } }, - "node_modules/tar/node_modules/minipass": { + "node_modules/tar/node_modules/yallist": { "version": "5.0.0", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", - "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", - "dev": true, - "license": "ISC", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-5.0.0.tgz", + "integrity": "sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw==", + "license": "BlueOak-1.0.0", "engines": { - "node": ">=8" + "node": ">=18" } }, "node_modules/temp": { @@ -13373,35 +13199,6 @@ "node": ">=12" } }, - "node_modules/temp/node_modules/mkdirp": { - "version": "0.5.6", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", - "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "minimist": "^1.2.6" - }, - "bin": { - "mkdirp": "bin/cmd.js" - } - }, - "node_modules/temp/node_modules/rimraf": { - "version": "2.6.3", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", - "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", - "deprecated": "Rimraf versions prior to v4 are no longer supported", - "dev": true, - "license": "ISC", - "peer": true, - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - } - }, "node_modules/tempy": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/tempy/-/tempy-3.1.0.tgz", @@ -13709,9 +13506,9 @@ } }, "node_modules/undici": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/undici/-/undici-7.16.0.tgz", - "integrity": "sha512-QEg3HPMll0o3t2ourKwOeUAZ159Kn9mx5pnzHRQO8+Wixmh88YdZRiIwat0iNzNNXn0yoEtXJqFpyW7eM8BV7g==", + "version": "7.20.0", + "resolved": "https://registry.npmjs.org/undici/-/undici-7.20.0.tgz", + "integrity": "sha512-MJZrkjyd7DeC+uPZh+5/YaMDxFiiEEaDgbUSVMXayofAkDWF1088CDo+2RPg7B1BuS1qf1vgNE7xqwPxE0DuSQ==", "dev": true, "license": "MIT", "engines": { @@ -13748,29 +13545,29 @@ } }, "node_modules/unique-filename": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-2.0.1.tgz", - "integrity": "sha512-ODWHtkkdx3IAR+veKxFV+VBkUMcN+FaqzUUd7IZzt+0zhDZFPFxhlqwPF3YQvMHx1TD0tdgYl+kuPnJ8E6ql7A==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-4.0.0.tgz", + "integrity": "sha512-XSnEewXmQ+veP7xX2dS5Q4yZAvO40cBN2MWkJ7D/6sW4Dg6wYBNwM1Vrnz1FhH5AdeLIlUXRI9e28z1YZi71NQ==", "dev": true, "license": "ISC", "dependencies": { - "unique-slug": "^3.0.0" + "unique-slug": "^5.0.0" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + "node": "^18.17.0 || >=20.5.0" } }, "node_modules/unique-slug": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-3.0.0.tgz", - "integrity": "sha512-8EyMynh679x/0gqE9fT9oilG+qEt+ibFyqjuVTsZn1+CMxH+XLlpvr2UZx4nVcCwTpx81nICr2JQFkM+HPLq4w==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-5.0.0.tgz", + "integrity": "sha512-9OdaqO5kwqR+1kVgHAhsp5vPNU0hnxRa26rBFNfNgM7M6pNtgzeBn3s/xbyCQL3dcjzOatcef6UUHpB/6MaETg==", "dev": true, "license": "ISC", "dependencies": { "imurmurhash": "^0.1.4" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + "node": "^18.17.0 || >=20.5.0" } }, "node_modules/unique-string": { diff --git a/package.json b/package.json index 13c5c95..1fe7e85 100644 --- a/package.json +++ b/package.json @@ -41,6 +41,7 @@ "@floating-ui/dom": "^1.7.4", "@huggingface/transformers": "^3.8.1", "electron-updater": "^6.6.2", + "idb-keyval": "^6.2.2", "jszip": "^3.10.1" }, "overrides": { diff --git a/src/app.css b/src/app.css index 0ea4d3a..729116b 100644 --- a/src/app.css +++ b/src/app.css @@ -48,6 +48,15 @@ body { margin: 0; } +/* All buttons should show pointer cursor on hover */ +button { + cursor: pointer; +} + +button:disabled { + cursor: not-allowed; +} + /* Scrollbar styling */ ::-webkit-scrollbar { width: 12px; diff --git a/src/app.d.ts b/src/app.d.ts index 0d1d16f..2e20520 100644 --- a/src/app.d.ts +++ b/src/app.d.ts @@ -13,6 +13,13 @@ interface ReadResult { error?: string; } +interface FileReadResult { + success: boolean; + buffer?: ArrayBuffer; + name?: string; + error?: string; +} + interface DirEntry { name: string; isDirectory: boolean; @@ -31,6 +38,7 @@ interface ElectronAPI { readFile: (filePath: string) => Promise; readDir: (dirPath: string) => Promise; fileExists: (filePath: string) => Promise; + readFileFromPath: (filePath: string) => Promise; openExternal: (url: string) => Promise; platform: string; isElectron: boolean; diff --git a/src/lib/bookmarks.svelte.ts b/src/lib/bookmarks.svelte.ts index 93672fe..995be65 100644 --- a/src/lib/bookmarks.svelte.ts +++ b/src/lib/bookmarks.svelte.ts @@ -205,6 +205,11 @@ function createBookmarksState() { return this.importBookmarks(data); }, + // Get bookmarks for a specific chat (for persistence) + getBookmarksForChatAsExport(chatId: string): Bookmark[] { + return bookmarks.filter((b) => b.chatId === chatId); + }, + // Clear all bookmarks clearAll(): void { bookmarks = []; diff --git a/src/lib/components/ChatList.svelte b/src/lib/components/ChatList.svelte index d5da677..312bf29 100644 --- a/src/lib/components/ChatList.svelte +++ b/src/lib/components/ChatList.svelte @@ -25,6 +25,8 @@ interface Props { autoLoadMediaByChat?: Map; onAutoLoadMediaChange?: (chatTitle: string, enabled: boolean) => void; loadingChats?: LoadingChat[]; + rememberedChats?: Set; + onToggleRemember?: (chatTitle: string, enabled: boolean) => void; } let { @@ -37,6 +39,8 @@ let { autoLoadMediaByChat = new Map(), onAutoLoadMediaChange, loadingChats = [], + rememberedChats = new Set(), + onToggleRemember, }: Props = $props(); const stageLabels = { @@ -123,6 +127,19 @@ function handleAutoLoadToggle() { closeContextMenu(); } +function isRemembered(chatTitle: string): boolean { + return rememberedChats.has(chatTitle); +} + +function handleToggleRemember() { + if (contextMenuIndex !== null && onToggleRemember) { + const chat = chats[contextMenuIndex]; + const currentRemembered = isRemembered(chat.title); + onToggleRemember(chat.title, !currentRemembered); + } + closeContextMenu(); +} + function formatDate(date: Date | null): string { if (!date) return ''; const locale = getLocale(); @@ -356,6 +373,20 @@ function getLastMessage(chat: ChatData): string {
+ + + + + {m.persistence_remember_conversation()} + + {#if isRemembered(chats[contextMenuIndex]?.title || '')} + + {/if} + + + +
+ { {#if open} - + - + diff --git a/src/lib/components/RestoreSessionModal.svelte b/src/lib/components/RestoreSessionModal.svelte index e3c3ea4..a5066e9 100644 --- a/src/lib/components/RestoreSessionModal.svelte +++ b/src/lib/components/RestoreSessionModal.svelte @@ -110,7 +110,7 @@ function getInitials(title: string): string { onclick={selectAll} > - Select All + {m.persistence_select_all()} From 33d1254c1221a728ddbb122d658c6863d006239e Mon Sep 17 00:00:00 2001 From: Rodrigo Gomes da Silva Date: Tue, 31 Mar 2026 18:59:47 -0300 Subject: [PATCH 05/33] fix(persistence): clean up IndexedDB entries when removing a remembered chat When a user removed a chat via handleRemoveChat(), persisted data in IndexedDB was not cleaned up, leaving orphaned entries that caused the restore modal to show stale chats. Now handleRemoveChat checks if the chat is in rememberedChats and, if so, finds and removes the persisted entry from IndexedDB before removing it from UI state. --- src/routes/+page.svelte | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/src/routes/+page.svelte b/src/routes/+page.svelte index 98d3fc6..dc900ca 100644 --- a/src/routes/+page.svelte +++ b/src/routes/+page.svelte @@ -374,11 +374,26 @@ function handleSelectChat(index: number) { } } -function handleRemoveChat(index: number) { +async function handleRemoveChat(index: number) { const chat = appState.chats[index]; if (chat) { + const chatTitle = chat.title; // Clean up file reference - chatFileReferences.delete(chat.title); + chatFileReferences.delete(chatTitle); + + // Clean up persisted data in IndexedDB if this chat was remembered + if (rememberedChats.has(chatTitle)) { + try { + const persisted = await findPersistedChatByTitle(chatTitle); + if (persisted) { + await removePersistedChat(persisted.id); + } + } catch (e) { + console.error('Failed to clean up persisted chat:', e); + } + rememberedChats.delete(chatTitle); + rememberedChats = new Set(rememberedChats); + } } appState.removeChat(index); } From 579c1e5c683975f074fe539dca30b2a662662765 Mon Sep 17 00:00:00 2001 From: Rodrigo Gomes da Silva Date: Tue, 31 Mar 2026 19:01:41 -0300 Subject: [PATCH 06/33] fix(persistence): add error logging to silent catch blocks Add console.error/warn logging to five catch blocks in persistence.svelte.ts that were silently swallowing errors, making IndexedDB issues impossible to debug. --- src/lib/persistence.svelte.ts | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/src/lib/persistence.svelte.ts b/src/lib/persistence.svelte.ts index b6744ea..a33dee9 100644 --- a/src/lib/persistence.svelte.ts +++ b/src/lib/persistence.svelte.ts @@ -91,7 +91,8 @@ async function getStoredFileHandle( `${HANDLE_PREFIX}${handleId}`, ); return handle || null; - } catch (_e) { + } catch (e) { + console.error('Failed to get stored file handle from IndexedDB:', e); return null; } } @@ -125,7 +126,8 @@ async function verifyHandlePermission( } return permission; - } catch (_e) { + } catch (e) { + console.error('Failed to verify file handle permission:', e); return 'prompt'; } } @@ -154,8 +156,9 @@ export async function promptForFileHandle( const [handle] = await window.showOpenFilePicker(options); return handle || null; - } catch (_e) { - // User cancelled + } catch (e) { + // User cancelled or file picker failed + console.warn('File picker cancelled or failed:', e); return null; } } @@ -522,7 +525,8 @@ export async function restoreChat( metadata: persistedChat, }, }; - } catch (_e) { + } catch (e) { + console.error('Failed to read file from handle:', e); return { success: false, error: 'Failed to read file from handle', @@ -566,7 +570,8 @@ export async function getDontShowRestoreModal(): Promise { if (!browser) return false; try { return (await get(DONT_SHOW_KEY)) || false; - } catch (_e) { + } catch (e) { + console.error('Failed to get dont-show-restore-modal preference:', e); return false; } } From 81c0fa6148b03cfa48affc48deafdd2a4e374612 Mon Sep 17 00:00:00 2001 From: Rodrigo Gomes da Silva Date: Tue, 31 Mar 2026 19:03:23 -0300 Subject: [PATCH 07/33] fix(ReselectFileModal): eliminate drag-drop flicker with counter pattern Replace boolean isDragging state with dragCounter pattern to fix visual flicker that occurred when dragging files over nested elements. The counter increments on dragenter and decrements on dragleave, preventing the rapid toggling that caused the flicker. --- src/lib/components/ReselectFileModal.svelte | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/src/lib/components/ReselectFileModal.svelte b/src/lib/components/ReselectFileModal.svelte index b014980..97775b4 100644 --- a/src/lib/components/ReselectFileModal.svelte +++ b/src/lib/components/ReselectFileModal.svelte @@ -15,12 +15,13 @@ interface Props { let { chatMetadata, onFileSelected, onSkip, onClose }: Props = $props(); -let isDragging = $state(false); +let dragCounter = $state(0); +let isDragging = $derived(dragCounter > 0); function handleDrop(e: DragEvent) { e.preventDefault(); e.stopPropagation(); - isDragging = false; + dragCounter = 0; const files = e.dataTransfer?.files; if (files && files.length > 0) { @@ -34,13 +35,18 @@ function handleDrop(e: DragEvent) { function handleDragOver(e: DragEvent) { e.preventDefault(); e.stopPropagation(); - isDragging = true; +} + +function handleDragEnter(e: DragEvent) { + e.preventDefault(); + e.stopPropagation(); + dragCounter++; } function handleDragLeave(e: DragEvent) { e.preventDefault(); e.stopPropagation(); - isDragging = false; + dragCounter--; } function handleFileInput(e: Event) { @@ -107,6 +113,7 @@ function getInitials(title: string): string { : 'border-neutral-300 dark:border-neutral-600 hover:border-[var(--color-whatsapp-teal)]/50 hover:bg-neutral-50 dark:hover:bg-neutral-800/30'}" ondrop={handleDrop} ondragover={handleDragOver} + ondragenter={handleDragEnter} ondragleave={handleDragLeave} >
From 2b54c7d21265781a68759510b88f309d25c330c4 Mon Sep 17 00:00:00 2001 From: Rodrigo Gomes da Silva Date: Tue, 31 Mar 2026 19:04:42 -0300 Subject: [PATCH 08/33] chore: remove AI handoff document --- AI_HANDOFF.md | 417 -------------------------------------------------- 1 file changed, 417 deletions(-) delete mode 100644 AI_HANDOFF.md diff --git a/AI_HANDOFF.md b/AI_HANDOFF.md deleted file mode 100644 index c898f45..0000000 --- a/AI_HANDOFF.md +++ /dev/null @@ -1,417 +0,0 @@ -# AI Handoff: Persistent Conversation Feature Implementation - -## Problem Statement -We're implementing a "Remember Conversation" feature that allows users to persist chat sessions across app restarts. **Current Issue**: The feature still shows "Please Re-select File" modal every time, even after supposedly storing file handles or paths. - -## Repository Context -- **Repo**: rodrigogs/whats-reader -- **Branch**: copilot/add-persistent-conversation-feature -- **Tech Stack**: SvelteKit (Svelte 5 with runes), TypeScript, Electron, IndexedDB (via idb-keyval) -- **Build**: Hybrid app - runs as both web app (GitHub Pages) and Electron desktop app - -## What Has Been Implemented - -### 1. Core Files Created - -#### `src/lib/persistence.svelte.ts` (460+ lines) -Core persistence module with: -- `PersistedChatMetadata` interface for storing chat metadata -- `savePersistedChat()` - Save a chat for persistence -- `getPersistedChats()` - Get all persisted chats -- `removePersistedChat()` - Remove a persisted chat -- `updatePersistedChat()` - Update existing persisted chat metadata -- `restoreChat()` - Attempt to restore a chat (handles all platform logic) -- `validateRestoredFile()` - Validate file matches saved metadata -- File handle storage/retrieval functions -- Permission verification functions - -#### `src/lib/components/RestoreSessionModal.svelte` -Modal shown on app load when persisted chats exist: -- Lists all persisted chats sorted by updatedAt -- Checkboxes to select which chats to restore -- "Restore Selected" and "Start Fresh" buttons -- "Don't show this again" checkbox - -#### `src/lib/components/ReselectFileModal.svelte` -Modal prompting user to re-select a file when needed: -- Shows expected filename -- File drop zone / file picker -- Validates selected file against saved metadata - -#### `src/lib/components/Toast.svelte` -Toast notification component for user feedback. - -#### `src/lib/components/Modal.svelte` & `ModalContent.svelte` -Base modal components with backdrop, animations, and responsive design. - -### 2. Files Modified - -#### `src/routes/+page.svelte` -- Added restoration flow on app load -- Integrated RestoreSessionModal and ReselectFileModal -- Tracks persisted chats in `rememberedChatIds` Set -- `handleToggleRemember()` - Toggle remember state, request file handles -- `handleRestoreChats()` - Restore selected conversations -- `handleReselectFile()` - Handle file reselection - -#### `src/lib/components/ChatList.svelte` -- Added "Remember Conversation" toggle to context menu -- Shows checkmark when chat is remembered - -#### `src/lib/bookmarks.svelte.ts` -- Added `getBookmarksForChatAsExport()` method - -#### `src/lib/transcription.svelte.ts` -- Added `getTranscriptionsForChat()` method -- Added `setTranscriptionsForChat()` method - -#### `electron/main.cjs` -- Added IPC handlers: `fs:fileExists`, `fs:readFileFromPath` - -#### `electron/preload.cjs` -- Exposed file APIs to renderer - -#### `src/app.d.ts` -- Added TypeScript types for Electron APIs - -#### `src/app.css` -- Added cursor:pointer for all buttons - -### 3. Dependencies Added -- `idb-keyval` (v6.2.1) - Simple IndexedDB key-value storage - -### 4. i18n Strings Added -All persistence-related strings in all 10 languages (en, de, es, fr, it, ja, nl, pt, ru, zh) - -## Current Problem: File Restoration Not Working - -### Symptoms -User reports: "It doesn't matter which browser or electron I try. I always ask me 'Please Re-select File'" - -### Intended Flow - -#### **For Electron:** -1. User drops/selects ZIP file -2. User toggles "Remember Conversation" -3. File path is stored in metadata: `{ type: 'electron-path', filePath: '/absolute/path/to/file.zip' }` -4. On restore: Read file directly from disk using `window.electronAPI.readFileFromPath(filePath)` - -#### **For Web (Chromium with File System Access API):** -1. User drops/selects ZIP file -2. User toggles "Remember Conversation" -3. File picker appears (to get FileSystemFileHandle) -4. Handle stored in IndexedDB -5. Metadata updated: `{ type: 'file-handle', handleId: 'unique-id' }` -6. On restore: Retrieve handle, check permission, read file automatically - -#### **For Web (Firefox/Safari - no File System Access API):** -1. User drops/selects ZIP file -2. User toggles "Remember Conversation" -3. Metadata saved: `{ type: 'reselect-required' }` -4. On restore: Show ReselectFileModal (expected behavior) - -### Likely Issues to Debug - -#### Issue 1: File Reference Not Being Stored Correctly -**Check in `+page.svelte` line ~789:** -```typescript -async function handleToggleRemember(chatId: string) { - // ... - if (!isRemembered) { - // Saving... - const persistedId = await savePersistedChat(/* ... */); - - // For web with File System Access API - if (!isElectron && isFileSystemAccessSupported()) { - const fileHandle = await promptForFileHandle(file.name); - if (fileHandle) { - const handleId = await storeFileHandle(fileHandle); - await updatePersistedChat(persistedId, { - fileReference: { type: 'file-handle', handleId } - }); - } - } - } -} -``` - -**Potential Problems:** -- `file` might not be available in this scope -- `fileHandle` might be null/undefined -- `storeFileHandle()` might be failing -- `updatePersistedChat()` might not be updating correctly -- For Electron, file path might not be captured correctly - -#### Issue 2: Restoration Logic Not Finding File Reference -**Check in `src/lib/persistence.svelte.ts` line ~450:** -```typescript -export async function restoreChat(persistedChat: PersistedChatMetadata): Promise { - const { fileReference } = persistedChat; - - // Check what fileReference type is being received - console.log('Restoring with fileReference:', fileReference); - - if (fileReference.type === 'electron-path') { - // Electron path logic - } else if (fileReference.type === 'file-handle') { - // File handle logic - } else { - // Falls back to reselect-required - return { success: false, needsReselect: true }; - } -} -``` - -**Potential Problems:** -- `fileReference.type` might always be 'reselect-required' -- Electron file path not being passed to `savePersistedChat()` -- File handle not being stored correctly - -#### Issue 3: Electron File Path Not Being Captured -**Check in `+page.svelte` where `handleFilesSelected` is called:** -```typescript -async function handleFilesSelected(files: File[]) { - for (const file of files) { - // For Electron, we need to get the file path - // But File object from file input doesn't have path property - // Need to use window.electronAPI to get the actual file path - } -} -``` - -**Potential Problems:** -- When user drops file in Electron, we get a File object but not the actual file path -- Need to use Electron's dialog.showOpenFilePicker to get the real path -- Current implementation might not be capturing Electron file paths at all - -## Debug Steps to Take - -### Step 1: Add Console Logging -Add debug logging throughout the flow: - -**In `+page.svelte` - handleToggleRemember:** -```typescript -console.log('Toggle remember - isElectron:', isElectron); -console.log('Toggle remember - file:', file); -console.log('Toggle remember - fileRef from Map:', fileRef); -console.log('Persisted ID:', persistedId); -``` - -**In `persistence.svelte.ts` - savePersistedChat:** -```typescript -console.log('Saving with fileReference:', metadata.fileReference); -``` - -**In `persistence.svelte.ts` - restoreChat:** -```typescript -console.log('Restoring with fileReference:', persistedChat.fileReference); -``` - -**In `persistence.svelte.ts` - getPersistedChats:** -```typescript -const chats = await get('persisted-chats') || []; -console.log('Retrieved persisted chats:', chats.map(c => ({ - id: c.id, - title: c.chatTitle, - fileRef: c.fileReference -}))); -``` - -### Step 2: Check IndexedDB Directly -Open browser DevTools → Application → IndexedDB → Look for stored data: -- Check if `persisted-chats` key exists -- Check if file handles are stored -- Verify fileReference type in stored metadata - -### Step 3: Fix Electron File Path Capture - -The main issue is likely that we're not capturing the file path in Electron. When a user drops a file, we get a File object but not the actual path. - -**Solution for Electron:** -```typescript -// In +page.svelte -async function handleToggleRemember(chatId: string) { - // ... - if (isElectron) { - // Need to prompt user to select file again to get the path - // Or store the path when they originally selected it - const filePath = await window.electronAPI?.getFilePath(); - if (filePath) { - const persistedId = await savePersistedChat( - chat, - file, - // ... other params - { type: 'electron-path', filePath } - ); - } - } -} -``` - -Need to add `getFilePath()` to Electron IPC: -```javascript -// In electron/main.cjs -ipcMain.handle('fs:getFilePath', async () => { - const result = await dialog.showOpenDialog({ - properties: ['openFile'], - filters: [{ name: 'ZIP Files', extensions: ['zip'] }] - }); - return result.filePaths[0]; -}); -``` - -### Step 4: Verify File Handle Storage and Retrieval - -**Test in Chrome DevTools Console:** -```javascript -// Check if File System Access API is available -console.log('showOpenFilePicker' in window); - -// Test storing a handle -const [handle] = await window.showOpenFilePicker(); -await idb.set('test-handle', handle); -const retrieved = await idb.get('test-handle'); -console.log('Retrieved handle:', retrieved); - -// Test permission -const permission = await retrieved.queryPermission({ mode: 'read' }); -console.log('Permission:', permission); -``` - -## Key Code Locations - -### File Reference Flow -1. **Capture**: `+page.svelte` line ~789 in `handleToggleRemember()` -2. **Storage**: `persistence.svelte.ts` line ~100 in `savePersistedChat()` -3. **Retrieval**: `persistence.svelte.ts` line ~190 in `getPersistedChats()` -4. **Restoration**: `persistence.svelte.ts` line ~450 in `restoreChat()` - -### Electron IPC -1. **Main Process**: `electron/main.cjs` lines 220-250 -2. **Preload**: `electron/preload.cjs` lines 50-80 -3. **Usage**: `+page.svelte` and `persistence.svelte.ts` - -## Technical Constraints - -### Svelte 5 Runes (CRITICAL) -- **Use `$state`, `$derived`, `$effect`** - NOT Svelte 4 stores -- **Use `$props()`** for component props -- **Use callback props** for events (not createEventDispatcher) - -### File System Access API -- Only available in Chromium browsers (Chrome 86+, Edge 86+) -- `requestPermission()` REQUIRES user gesture -- Can't call during automated restoration -- Permissions may expire - -### Electron -- File paths are absolute paths on disk -- Use `fs.existsSync()` and `fs.readFileSync()` -- IPC communication between main and renderer process - -## Next Steps for AI Agent - -1. **Add comprehensive debug logging** to trace the exact flow -2. **Test in actual browser/Electron** to see console output -3. **Verify IndexedDB contents** to see what's actually stored -4. **Fix the root cause** - likely that file references aren't being captured/stored correctly -5. **Specific focus areas:** - - Electron: Ensure file path is captured when toggling remember - - Web: Ensure file handle is stored AND metadata is updated - - Verify `updatePersistedChat()` actually updates IndexedDB - -## Commands to Run - -```bash -# Build -npm run build - -# Lint -npm run lint - -# Run dev server (web) -npm run dev - -# Run Electron -npm run electron:dev - -# Type check -npm run check -``` - -## Files to Focus On - -1. **`src/routes/+page.svelte`** - lines 750-850 (handleToggleRemember, file reference capture) -2. **`src/lib/persistence.svelte.ts`** - lines 100-150 (savePersistedChat), lines 450-550 (restoreChat) -3. **`electron/main.cjs`** - lines 220-250 (file operations) - -## Expected Outcome - -After fixing: -- **Electron**: Toggle remember → close app → reopen → conversations restore automatically (no reselect modal) -- **Chrome/Edge**: Toggle remember → grant permission → close → reopen → conversations restore automatically -- **Firefox/Safari**: Toggle remember → close → reopen → shows reselect modal (expected, no API support) - -## Contact for Questions -Repository: https://github.com/rodrigogs/whats-reader -Branch: copilot/add-persistent-conversation-feature - ---- - -## Prompt for Another AI Tool - -Copy everything below to start working with another AI: - ---- - -I'm working on the rodrigogs/whats-reader repository on branch `copilot/add-persistent-conversation-feature`. - -**Problem**: I've implemented a "Remember Conversation" feature that should persist chat sessions across app restarts, but the file restoration isn't working. Users always see the "Please Re-select File" modal even after supposedly storing file handles or paths. - -**Repository Structure**: -- Hybrid SvelteKit + Electron app -- Uses Svelte 5 runes ($state, $derived, $effect) - NOT Svelte 4 stores -- TypeScript throughout -- IndexedDB storage via idb-keyval -- File System Access API for web, file paths for Electron - -**What I've implemented**: -- `src/lib/persistence.svelte.ts` - Core persistence module with save/restore/validate functions -- `src/lib/components/RestoreSessionModal.svelte` - Modal for selecting conversations to restore -- `src/lib/components/ReselectFileModal.svelte` - Modal for re-selecting files -- Modified `src/routes/+page.svelte` to add restoration flow -- Modified `src/lib/components/ChatList.svelte` to add "Remember Conversation" toggle -- Added Electron IPC handlers for file operations in `electron/main.cjs` and `electron/preload.cjs` - -**The Bug**: -The file reference (either Electron path or web file handle) is not being stored or retrieved correctly. Every restoration shows the reselect modal. - -**Likely Root Causes**: -1. For Electron: File path not being captured when user toggles "Remember Conversation" -2. For Web: File handle not being stored in IndexedDB or metadata not being updated -3. The `fileReference` in persisted metadata always shows `{ type: 'reselect-required' }` - -**Debug This**: -1. Add console.log statements in `+page.svelte` handleToggleRemember() to see what file reference is being captured -2. Add console.log in `persistence.svelte.ts` savePersistedChat() and restoreChat() to trace file reference flow -3. Check browser DevTools → Application → IndexedDB to see what's actually stored -4. For Electron: Verify file path is being obtained (might need to add getFilePath() IPC handler) -5. For Web: Verify file handle is stored AND metadata is updated with handleId - -**Key files to check**: -- `src/routes/+page.svelte` lines 750-850 (handleToggleRemember) -- `src/lib/persistence.svelte.ts` lines 100-150 (savePersistedChat), 450-550 (restoreChat) -- `electron/main.cjs` lines 220-250 (IPC handlers) - -**Commands**: -- `npm run build` - Build the app -- `npm run lint` - Lint code -- `npm run dev` - Dev server -- `npm run electron:dev` - Run in Electron - -Please debug and fix the file reference storage/retrieval so that: -- Electron: Automatically restores from file path -- Chrome/Edge: Automatically restores from file handle (after permission granted) -- Firefox/Safari: Shows reselect modal (expected - no File System Access API) - -Start by adding debug logging to trace where the file reference is lost, then fix the root cause. From 6a65b7e2d937177e5461acfd21c845cca91ac5e6 Mon Sep 17 00:00:00 2001 From: Rodrigo Gomes da Silva Date: Tue, 31 Mar 2026 20:26:39 -0300 Subject: [PATCH 09/33] fix: clean up dead code, timer leaks, and unused imports --- src/lib/components/ReselectFileModal.svelte | 9 +-- src/lib/components/RestoreSessionModal.svelte | 10 +--- src/lib/components/Toast.svelte | 27 ++++----- src/lib/helpers/format.ts | 16 ++++++ src/lib/persistence.svelte.ts | 4 +- src/lib/transcription.svelte.ts | 13 ++--- src/routes/+page.svelte | 56 +++++++++---------- 7 files changed, 62 insertions(+), 73 deletions(-) create mode 100644 src/lib/helpers/format.ts diff --git a/src/lib/components/ReselectFileModal.svelte b/src/lib/components/ReselectFileModal.svelte index 97775b4..136bcac 100644 --- a/src/lib/components/ReselectFileModal.svelte +++ b/src/lib/components/ReselectFileModal.svelte @@ -1,4 +1,5 @@ diff --git a/src/lib/components/RestoreSessionModal.svelte b/src/lib/components/RestoreSessionModal.svelte index a5066e9..ad8cabf 100644 --- a/src/lib/components/RestoreSessionModal.svelte +++ b/src/lib/components/RestoreSessionModal.svelte @@ -1,5 +1,5 @@ diff --git a/src/lib/components/Toast.svelte b/src/lib/components/Toast.svelte index 65832f2..a87f353 100644 --- a/src/lib/components/Toast.svelte +++ b/src/lib/components/Toast.svelte @@ -3,6 +3,7 @@ * Simple Toast Notification * Displays temporary notification messages */ +import { fly } from 'svelte/transition'; interface Props { message: string; @@ -15,17 +16,19 @@ let { message, type = 'success', duration = 3000, onClose }: Props = $props(); let visible = $state(true); -// Auto-hide after duration -if (duration > 0) { - setTimeout(() => { +// Auto-hide after duration, with cleanup on destroy +$effect(() => { + if (!visible || duration <= 0) return; + + const timer = setTimeout(() => { visible = false; - setTimeout(() => onClose?.(), 300); // Wait for fade out animation }, duration); -} + + return () => clearTimeout(timer); +}); function handleClose() { visible = false; - setTimeout(() => onClose?.(), 300); } const bgColors = { @@ -33,20 +36,14 @@ const bgColors = { error: 'bg-red-500 dark:bg-red-600', info: 'bg-blue-500 dark:bg-blue-600', }; - -const icons = { - success: 'check', - error: 'alert-circle', - info: 'info', -}; {#if visible} {/if} From 5ce83a3cf5064c62b3db7ad4debd88e5759e5e3f Mon Sep 17 00:00:00 2001 From: Rodrigo Gomes da Silva Date: Tue, 31 Mar 2026 21:19:59 -0300 Subject: [PATCH 16/33] fix(a11y): add aria-label to drop zone and i18n Modal close label - Add aria-label to drop zone in ReselectFileModal for screen reader accessibility - Replace hardcoded 'Close modal' string with i18n key close_modal in Modal component - Add close_modal translations to all 10 locale files (en, pt, es, fr, de, it, nl, ja, zh, ru) --- messages/de.json | 1 + messages/en.json | 1 + messages/es.json | 1 + messages/fr.json | 1 + messages/it.json | 1 + messages/ja.json | 1 + messages/nl.json | 1 + messages/pt.json | 1 + messages/ru.json | 1 + messages/zh.json | 1 + src/lib/components/Modal.svelte | 4 ++-- src/lib/components/ReselectFileModal.svelte | 1 + 12 files changed, 13 insertions(+), 2 deletions(-) diff --git a/messages/de.json b/messages/de.json index cac46b8..92fc879 100644 --- a/messages/de.json +++ b/messages/de.json @@ -181,6 +181,7 @@ "update_never_tooltip": "Nie Update-Benachrichtigungen anzeigen", "version_view_releases": "Versionen auf GitHub anzeigen", "close": "Schließen", + "close_modal": "Modal schließen", "update_ready": "Update bereit", "update_downloading": "Update wird heruntergeladen", "update_close": "Aktualisierungsbenachrichtigung schließen", diff --git a/messages/en.json b/messages/en.json index 3308ba7..6d19031 100644 --- a/messages/en.json +++ b/messages/en.json @@ -231,6 +231,7 @@ "calendar_weekday_fri": "Fr", "calendar_weekday_sat": "Sa", "close": "Close", + "close_modal": "Close modal", "media_gallery_options": "Options", "media_gallery_filter_by_participant": "Filter by participant", "media_gallery_filter_by_type": "Filter by type", diff --git a/messages/es.json b/messages/es.json index 8a87423..d7dc7b1 100644 --- a/messages/es.json +++ b/messages/es.json @@ -181,6 +181,7 @@ "update_never_tooltip": "Nunca mostrar notificaciones de actualización", "version_view_releases": "Ver versiones en GitHub", "close": "Cerrar", + "close_modal": "Cerrar modal", "update_ready": "Actualización lista", "update_downloading": "Descargando actualización", "update_close": "Cerrar notificación de actualización", diff --git a/messages/fr.json b/messages/fr.json index d9b9575..91f96a0 100644 --- a/messages/fr.json +++ b/messages/fr.json @@ -181,6 +181,7 @@ "update_never_tooltip": "Ne jamais afficher les notifications de mise à jour", "version_view_releases": "Voir les versions sur GitHub", "close": "Fermer", + "close_modal": "Fermer la boîte de dialogue", "update_ready": "Prêt pour la mise à jour", "update_downloading": "Téléchargement de la mise à jour", "update_close": "Fermer la notification de mise à jour", diff --git a/messages/it.json b/messages/it.json index 4ce4a0b..62e7906 100644 --- a/messages/it.json +++ b/messages/it.json @@ -181,6 +181,7 @@ "update_never_tooltip": "Non mostrare mai notifiche di aggiornamento", "version_view_releases": "Visualizza le versioni su GitHub", "close": "Chiudi", + "close_modal": "Chiudi finestra modale", "update_ready": "Aggiornamento pronto", "update_downloading": "Download dell'aggiornamento", "update_close": "Chiudi notifica di aggiornamento", diff --git a/messages/ja.json b/messages/ja.json index 4885dde..82d94a6 100644 --- a/messages/ja.json +++ b/messages/ja.json @@ -181,6 +181,7 @@ "update_never_tooltip": "アップデート通知を表示しない", "version_view_releases": "GitHubでリリースを見る", "close": "閉じる", + "close_modal": "モーダルを閉じる", "update_ready": "アップデート準備完了", "update_downloading": "アップデートをダウンロード中", "update_close": "更新通知を閉じる", diff --git a/messages/nl.json b/messages/nl.json index 8db7417..c9c2c58 100644 --- a/messages/nl.json +++ b/messages/nl.json @@ -181,6 +181,7 @@ "update_never_tooltip": "Nooit updatemeldingen tonen", "version_view_releases": "Bekijk releases op GitHub", "close": "Sluiten", + "close_modal": "Venster sluiten", "update_ready": "Update gereed", "update_downloading": "Update downloaden", "update_close": "Sluit de updatemelding", diff --git a/messages/pt.json b/messages/pt.json index 1e2769f..16315fc 100644 --- a/messages/pt.json +++ b/messages/pt.json @@ -181,6 +181,7 @@ "update_never_tooltip": "Nunca mostrar notificações de atualização", "version_view_releases": "Ver versões no GitHub", "close": "Fechar", + "close_modal": "Fechar modal", "update_ready": "Atualização pronta", "update_downloading": "Baixando atualização", "update_close": "Fechar notificação de atualização", diff --git a/messages/ru.json b/messages/ru.json index 74c7d79..5c908e4 100644 --- a/messages/ru.json +++ b/messages/ru.json @@ -181,6 +181,7 @@ "update_never_tooltip": "Никогда не показывать уведомления об обновлениях", "version_view_releases": "Посмотреть релизы на GitHub", "close": "Закрыть", + "close_modal": "Закрыть модальное окно", "update_ready": "Обновление готово", "update_downloading": "Загрузка обновления", "update_close": "Закрыть уведомление об обновлении", diff --git a/messages/zh.json b/messages/zh.json index d1f2f09..1ac7fd4 100644 --- a/messages/zh.json +++ b/messages/zh.json @@ -181,6 +181,7 @@ "update_never_tooltip": "不再显示更新通知", "version_view_releases": "在 GitHub 上查看版本", "close": "关闭", + "close_modal": "关闭对话框", "update_ready": "更新准备就绪", "update_downloading": "正在下载更新", "update_close": "关闭更新通知", diff --git a/src/lib/components/Modal.svelte b/src/lib/components/Modal.svelte index f7322d7..04bbda9 100644 --- a/src/lib/components/Modal.svelte +++ b/src/lib/components/Modal.svelte @@ -1,6 +1,7 @@ From 4a58b4c184cff0261dd0567c050ba1b572997372 Mon Sep 17 00:00:00 2001 From: Rodrigo Gomes da Silva Date: Wed, 1 Apr 2026 00:39:44 -0300 Subject: [PATCH 18/33] fix: address all 9 Copilot review comments 1. Capture Electron file.path from drag-drop for persistence 2. Block metadata restoration when file validation fails 3. Deduplicate savePersistedChat (removes existing entry first) 4. Filter transcriptions by chat message IDs (prevents cross-chat leak) 5. Case-insensitive .zip check in ReselectFileModal 6. Clamp dragCounter to 0 minimum 7. Use isAbsolute + reject .. segments for Electron path validation 8. Guard error.message with instanceof Error check 9. Add keyboard/click handlers to drop zone for accessibility --- electron/main.cjs | 14 +++- src/lib/components/ReselectFileModal.svelte | 22 ++++- src/lib/persistence.svelte.ts | 6 ++ src/lib/transcription.svelte.ts | 32 ++++--- src/routes/+page.svelte | 93 +++++++++++---------- 5 files changed, 99 insertions(+), 68 deletions(-) diff --git a/electron/main.cjs b/electron/main.cjs index c695279..5b3fbf7 100644 --- a/electron/main.cjs +++ b/electron/main.cjs @@ -230,8 +230,15 @@ ipcMain.handle('fs:fileExists', async (_event, filePath) => { // Read file from absolute path (for persistence) ipcMain.handle('file:readFromPath', async (_event, filePath) => { try { + if (typeof filePath !== 'string') { + return { success: false, error: 'Invalid file path' }; + } const normalized = path.resolve(filePath); - if (normalized !== filePath) { + // Require absolute path and reject path traversal segments + if (!path.isAbsolute(filePath)) { + return { success: false, error: 'Invalid file path' }; + } + if (filePath.split(/[/\\]+/).includes('..')) { return { success: false, error: 'Invalid file path' }; } if (path.extname(normalized).toLowerCase() !== '.zip') { @@ -261,7 +268,10 @@ ipcMain.handle('file:readFromPath', async (_event, filePath) => { await fd.close(); } } catch (error) { - return { success: false, error: error.message }; + return { + success: false, + error: error instanceof Error ? error.message : String(error), + }; } }); diff --git a/src/lib/components/ReselectFileModal.svelte b/src/lib/components/ReselectFileModal.svelte index ff9ca33..6f280ac 100644 --- a/src/lib/components/ReselectFileModal.svelte +++ b/src/lib/components/ReselectFileModal.svelte @@ -27,7 +27,7 @@ function handleDrop(e: DragEvent) { const files = e.dataTransfer?.files; if (files && files.length > 0) { const file = files[0]; - if (file.name.endsWith('.zip')) { + if (file.name.toLowerCase().endsWith('.zip')) { onFileSelected(file); } } @@ -47,19 +47,32 @@ function handleDragEnter(e: DragEvent) { function handleDragLeave(e: DragEvent) { e.preventDefault(); e.stopPropagation(); - dragCounter--; + dragCounter = Math.max(0, dragCounter - 1); } +let fileInputRef: HTMLInputElement | undefined = $state(); + function handleFileInput(e: Event) { const input = e.target as HTMLInputElement; const files = input.files; if (files && files.length > 0) { const file = files[0]; - if (file.name.endsWith('.zip')) { + if (file.name.toLowerCase().endsWith('.zip')) { onFileSelected(file); } } } + +function handleDropZoneKeydown(e: KeyboardEvent) { + if (e.key === 'Enter' || e.key === ' ') { + e.preventDefault(); + fileInputRef?.click(); + } +} + +function handleDropZoneClick() { + fileInputRef?.click(); +} @@ -109,6 +122,8 @@ function handleFileInput(e: Event) { ondragover={handleDragOver} ondragenter={handleDragEnter} ondragleave={handleDragLeave} + onkeydown={handleDropZoneKeydown} + onclick={handleDropZoneClick} >
@@ -130,6 +145,7 @@ function handleFileInput(e: Event) {