diff --git a/apps/desktop/README.md b/apps/desktop/README.md
index 8602e0eb422..feb163d43ca 100644
--- a/apps/desktop/README.md
+++ b/apps/desktop/README.md
@@ -111,15 +111,28 @@ npm run test:desktop:all
Boot logs land in `HERMES_HOME/logs/desktop.log` (includes backend output and recent Python tracebacks) — check it first if the app reports a boot failure.
+**macOS / Linux:**
+
```bash
# Force a clean first-launch setup
-rm "$HOME/.hermes/hermes-agent/.hermes-bootstrap-complete" # macOS/Linux
+rm "$HOME/.hermes/hermes-agent/.hermes-bootstrap-complete"
# Rebuild a broken Python venv
-rm -rf "$HOME/.hermes/hermes-agent/venv" # macOS/Linux
-# Reset a stuck macOS microphone prompt
+rm -rf "$HOME/.hermes/hermes-agent/venv"
+# Reset a stuck macOS microphone prompt (macOS only)
tccutil reset Microphone com.nousresearch.hermes
```
+**Windows (PowerShell):**
+
+```powershell
+# Force a clean first-launch setup
+Remove-Item "$env:LOCALAPPDATA\hermes\hermes-agent\.hermes-bootstrap-complete"
+# Rebuild a broken Python venv
+Remove-Item -Recurse -Force "$env:LOCALAPPDATA\hermes\hermes-agent\venv"
+```
+
+> The default Hermes home on Windows is `%LOCALAPPDATA%\hermes`. Set the `HERMES_HOME` env var if you've relocated it.
+
---
## Community
diff --git a/apps/desktop/electron/main.cjs b/apps/desktop/electron/main.cjs
index db6a2b7b9d4..f75fd83ce6a 100644
--- a/apps/desktop/electron/main.cjs
+++ b/apps/desktop/electron/main.cjs
@@ -535,6 +535,39 @@ function openExternalUrl(rawUrl) {
return false
}
+ // `file://` URLs come from the artifacts panel (the renderer can't open
+ // them itself because Chromium blocks file:// navigation from the app
+ // origin). Hand them to `shell.openPath`, which dispatches to the OS
+ // file association. If the OS can't open it (`error` is a non-empty
+ // string), fall back to revealing the file in the system file manager.
+ if (parsed.protocol === 'file:') {
+ let localPath
+ try {
+ localPath = fileURLToPath(parsed.toString())
+ } catch {
+ return false
+ }
+
+ void shell
+ .openPath(localPath)
+ .then(error => {
+ if (!error) {
+ return
+ }
+
+ rememberLog(`[file] openPath failed: ${error}; revealing in folder instead`)
+
+ try {
+ shell.showItemInFolder(localPath)
+ } catch (revealError) {
+ rememberLog(`[file] showItemInFolder failed: ${revealError.message}`)
+ }
+ })
+ .catch(error => rememberLog(`[file] openPath rejected: ${error.message}`))
+
+ return true
+ }
+
if (!['http:', 'https:', 'mailto:'].includes(parsed.protocol)) {
return false
}
@@ -1526,10 +1559,18 @@ function resolveRendererIndex() {
}
function resolveHermesCwd() {
+ // In a packaged build, `process.cwd()` resolves to the install root (e.g.
+ // `…/win-unpacked` on Windows or `/Applications/Hermes.app/Contents/...`
+ // on macOS). Sessions spawned there leave files inside the app bundle
+ // and bewilder users when "where did my files go?" is the install dir.
+ // The user-configurable default project directory wins over everything,
+ // followed by env hints (only honored when packaged if they point at a
+ // real directory), then the home dir.
const candidates = [
+ readDefaultProjectDir(),
process.env.HERMES_DESKTOP_CWD,
process.env.INIT_CWD,
- process.cwd(),
+ IS_PACKAGED ? null : process.cwd(),
!IS_PACKAGED ? SOURCE_REPO_ROOT : null,
app.getPath('home')
]
@@ -1543,6 +1584,48 @@ function resolveHermesCwd() {
return app.getPath('home')
}
+// Persisted "Default project directory" — surfaced as a setting in the
+// renderer (see app/settings/sessions-settings.tsx). Stored as JSON in
+// userData so it survives self-updates without bleeding into the new
+// install. `null` means "no preference, fall back to the usual chain".
+const DEFAULT_PROJECT_DIR_CONFIG_FILENAME = 'project-dir.json'
+
+function defaultProjectDirConfigPath() {
+ return path.join(app.getPath('userData'), DEFAULT_PROJECT_DIR_CONFIG_FILENAME)
+}
+
+function readDefaultProjectDir() {
+ try {
+ const raw = fs.readFileSync(defaultProjectDirConfigPath(), 'utf8')
+ const parsed = JSON.parse(raw)
+
+ if (parsed && typeof parsed.dir === 'string' && parsed.dir.trim()) {
+ const resolved = path.resolve(parsed.dir)
+
+ if (directoryExists(resolved)) {
+ return resolved
+ }
+ }
+ } catch {
+ // Missing / unreadable / malformed → fall through to the rest of the
+ // candidate chain.
+ }
+
+ return null
+}
+
+function writeDefaultProjectDir(dir) {
+ const target = defaultProjectDirConfigPath()
+ const payload = dir ? JSON.stringify({ dir: path.resolve(dir) }, null, 2) : JSON.stringify({}, null, 2)
+
+ try {
+ fs.mkdirSync(path.dirname(target), { recursive: true })
+ fs.writeFileSync(target, payload, 'utf8')
+ } catch (error) {
+ rememberLog(`[settings] write default project dir failed: ${error.message}`)
+ }
+}
+
function createPythonBackend(root, label, dashboardArgs, options = {}) {
const python = findPythonForRoot(root)
if (!python) return null
@@ -2702,6 +2785,28 @@ function installContextMenu(window) {
)
}
+ // Spell-check suggestions for the misspelled word under the caret.
+ // Chromium surfaces them on `params.dictionarySuggestions`; we offer the
+ // top 5 plus a "Add to dictionary" affordance.
+ const suggestions = Array.isArray(params.dictionarySuggestions) ? params.dictionarySuggestions : []
+
+ if (isEditable && params.misspelledWord && suggestions.length > 0) {
+ if (template.length) template.push({ type: 'separator' })
+
+ for (const suggestion of suggestions.slice(0, 5)) {
+ template.push({
+ label: suggestion,
+ click: () => window.webContents.replaceMisspelling(suggestion)
+ })
+ }
+
+ template.push({ type: 'separator' })
+ template.push({
+ label: 'Add to dictionary',
+ click: () => window.webContents.session.addWordToSpellCheckerDictionary(params.misspelledWord)
+ })
+ }
+
if (hasSelection || isEditable) {
if (template.length) template.push({ type: 'separator' })
if (isEditable) {
@@ -3497,6 +3602,45 @@ ipcMain.handle('hermes:openExternal', (_event, url) => {
}
})
+// User-configurable default project directory. The renderer reads this on
+// settings mount and seeds the value into the picker; writing back persists
+// it via writeDefaultProjectDir so resolveHermesCwd picks it up on the next
+// session spawn (no app restart needed).
+ipcMain.handle('hermes:setting:defaultProjectDir:get', async () => ({
+ dir: readDefaultProjectDir(),
+ defaultLabel: path.join(app.getPath('home'), 'hermes-projects')
+}))
+
+ipcMain.handle('hermes:setting:defaultProjectDir:set', async (_event, dir) => {
+ const next = typeof dir === 'string' && dir.trim() ? dir.trim() : null
+
+ if (next) {
+ try {
+ fs.mkdirSync(next, { recursive: true })
+ } catch (error) {
+ throw new Error(`Could not create directory: ${error.message}`)
+ }
+ }
+
+ writeDefaultProjectDir(next)
+
+ return { dir: next }
+})
+
+ipcMain.handle('hermes:setting:defaultProjectDir:pick', async () => {
+ const result = await dialog.showOpenDialog({
+ title: 'Choose default project directory',
+ properties: ['openDirectory', 'createDirectory'],
+ defaultPath: readDefaultProjectDir() || app.getPath('home')
+ })
+
+ if (result.canceled || result.filePaths.length === 0) {
+ return { canceled: true, dir: null }
+ }
+
+ return { canceled: false, dir: result.filePaths[0] }
+})
+
ipcMain.handle('hermes:fetchLinkTitle', (_event, url) => fetchLinkTitle(url))
ipcMain.handle('hermes:logs:reveal', async () => {
@@ -3806,6 +3950,7 @@ app.whenReady().then(() => {
installMediaPermissions()
registerMediaProtocol()
ensureWslWindowsFonts()
+ configureSpellChecker()
createWindow()
app.on('activate', () => {
@@ -3813,6 +3958,29 @@ app.whenReady().then(() => {
})
})
+// Seed Chromium's spellchecker with the system locale (falling back to en-US).
+// On macOS Electron uses the native spellchecker which ignores this list, but
+// on Windows/Linux Chromium downloads Hunspell dictionaries on demand and
+// won't enable any without an explicit language.
+function configureSpellChecker() {
+ try {
+ const defaultSession = session.defaultSession
+
+ if (!defaultSession || typeof defaultSession.setSpellCheckerLanguages !== 'function') {
+ return
+ }
+
+ const available = defaultSession.availableSpellCheckerLanguages || []
+ const locale = (app.getLocale && app.getLocale()) || 'en-US'
+ const candidates = [locale, locale.split('-')[0], 'en-US', 'en']
+ const chosen = candidates.find(lang => available.includes(lang)) || 'en-US'
+
+ defaultSession.setSpellCheckerLanguages([chosen])
+ } catch (error) {
+ rememberLog(`Spellchecker setup failed: ${error.message}`)
+ }
+}
+
app.on('before-quit', () => {
// Quitting mid-install should stop the installer, not orphan it.
if (bootstrapAbortController) {
diff --git a/apps/desktop/electron/preload.cjs b/apps/desktop/electron/preload.cjs
index fcdf789ae3e..384972fe792 100644
--- a/apps/desktop/electron/preload.cjs
+++ b/apps/desktop/electron/preload.cjs
@@ -31,6 +31,11 @@ contextBridge.exposeInMainWorld('hermesDesktop', {
setPreviewShortcutActive: active => ipcRenderer.send('hermes:previewShortcutActive', Boolean(active)),
openExternal: url => ipcRenderer.invoke('hermes:openExternal', url),
fetchLinkTitle: url => ipcRenderer.invoke('hermes:fetchLinkTitle', url),
+ settings: {
+ getDefaultProjectDir: () => ipcRenderer.invoke('hermes:setting:defaultProjectDir:get'),
+ setDefaultProjectDir: dir => ipcRenderer.invoke('hermes:setting:defaultProjectDir:set', dir),
+ pickDefaultProjectDir: () => ipcRenderer.invoke('hermes:setting:defaultProjectDir:pick')
+ },
revealLogs: () => ipcRenderer.invoke('hermes:logs:reveal'),
getRecentLogs: () => ipcRenderer.invoke('hermes:logs:recent'),
readDir: dirPath => ipcRenderer.invoke('hermes:fs:readDir', dirPath),
diff --git a/apps/desktop/index.html b/apps/desktop/index.html
index 4478787d753..0ef2dcb59ab 100644
--- a/apps/desktop/index.html
+++ b/apps/desktop/index.html
@@ -3,8 +3,11 @@
-
-
+
+
+
+
+
Hermes
diff --git a/apps/desktop/package.json b/apps/desktop/package.json
index a9a0db7e21b..15bb812b459 100644
--- a/apps/desktop/package.json
+++ b/apps/desktop/package.json
@@ -50,6 +50,7 @@
"@dnd-kit/sortable": "^10.0.0",
"@dnd-kit/utilities": "^3.2.2",
"@hermes/shared": "file:../shared",
+ "@icons-pack/react-simple-icons": "^13.13.0",
"@nanostores/react": "^1.1.0",
"@nous-research/ui": "^0.13.0",
"@radix-ui/react-slot": "^1.2.4",
diff --git a/apps/desktop/src/app/chat/composer/context-menu.tsx b/apps/desktop/src/app/chat/composer/context-menu.tsx
index 74de7b3b70a..300ddf92597 100644
--- a/apps/desktop/src/app/chat/composer/context-menu.tsx
+++ b/apps/desktop/src/app/chat/composer/context-menu.tsx
@@ -1,14 +1,20 @@
+import { useState } from 'react'
+
import { Button } from '@/components/ui/button'
import { Codicon } from '@/components/ui/codicon'
+import {
+ Dialog,
+ DialogContent,
+ DialogDescription,
+ DialogHeader,
+ DialogTitle
+} from '@/components/ui/dialog'
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuLabel,
DropdownMenuSeparator,
- DropdownMenuSub,
- DropdownMenuSubContent,
- DropdownMenuSubTrigger,
DropdownMenuTrigger
} from '@/components/ui/dropdown-menu'
import { Clipboard, FileText, FolderOpen, type IconComponent, ImageIcon, Link, MessageSquareText } from '@/lib/icons'
@@ -17,6 +23,24 @@ import { cn } from '@/lib/utils'
import { GHOST_ICON_BTN } from './controls'
import type { ChatBarState } from './types'
+const PROMPT_SNIPPETS: readonly PromptSnippet[] = [
+ {
+ description: 'Audit the current change for regressions, dropped edge cases, and missing tests.',
+ label: 'Code review',
+ text: 'Please review this for bugs, regressions, and missing tests.'
+ },
+ {
+ description: 'Outline an approach before touching code so the diff stays focused.',
+ label: 'Implementation plan',
+ text: 'Please make a concise implementation plan before changing code.'
+ },
+ {
+ description: 'Walk through how the selected code works and link to the key files.',
+ label: 'Explain this',
+ text: 'Please explain how this works and point me to the key files.'
+ }
+]
+
export function ContextMenu({
state,
onInsertText,
@@ -25,81 +49,114 @@ export function ContextMenu({
onPickFiles,
onPickFolders,
onPickImages
-}: {
- state: ChatBarState
- onInsertText: (text: string) => void
- onOpenUrlDialog: () => void
- onPasteClipboardImage?: () => void
- onPickFiles?: () => void
- onPickFolders?: () => void
- onPickImages?: () => void
-}) {
+}: ContextMenuProps) {
+ // Prompt snippets used to be a Radix submenu. That submenu didn't open
+ // reliably when the parent menu was positioned at the bottom of the
+ // window (composer "+" anchor), so we promoted it to a real Dialog —
+ // easier to grow with search / descriptions, and no positioning math.
+ const [snippetsOpen, setSnippetsOpen] = useState(false)
+
return (
-
-
-
-
-
-
-
-
- Attach
-
-
- Files…
-
-
- Folder…
-
-
- Images…
-
-
- Paste image
-
-
- URL…
-
+ <>
+
+
+
+
+
+
+
+
+ Attach
+
+
+ Files…
+
+
+ Folder…
+
+
+ Images…
+
+
+ Paste image
+
+
+ URL…
+
-
+
-
-
-
- Prompt snippets
-
-
- {[
- { label: 'Code review', text: 'Please review this for bugs, regressions, and missing tests.' },
- { label: 'Implementation plan', text: 'Please make a concise implementation plan before changing code.' },
- { label: 'Explain this', text: 'Please explain how this works and point me to the key files.' }
- ].map(snippet => (
- onInsertText(snippet.text)}>
- {snippet.label}
-
- ))}
-
-
+ setSnippetsOpen(true)}>
+ Prompt snippets…
+
-
+
-
- Tip: type @ to reference files
- inline.
-
-
-
+
+ Tip: type @ to reference files
+ inline.
+
+
+
+
+
+ >
+ )
+}
+
+function PromptSnippetsDialog({
+ onInsertText,
+ onOpenChange,
+ open,
+ snippets
+}: PromptSnippetsDialogProps) {
+ return (
+
+
+
+ Prompt snippets
+ Pick a starter prompt to drop into the composer.
+
+
+ {snippets.map(snippet => (
+
+ {
+ onInsertText(snippet.text)
+ onOpenChange(false)
+ }}
+ type="button"
+ >
+
+
+ {snippet.label}
+
+ {snippet.description}
+
+
+
+
+ ))}
+
+
+
)
}
@@ -108,12 +165,7 @@ export function ContextMenuItem({
disabled,
icon: Icon,
onSelect
-}: {
- children: string
- disabled?: boolean
- icon: IconComponent
- onSelect?: () => void
-}) {
+}: ContextMenuItemProps) {
return (
@@ -121,3 +173,33 @@ export function ContextMenuItem({
)
}
+
+interface ContextMenuItemProps {
+ children: string
+ disabled?: boolean
+ icon: IconComponent
+ onSelect?: () => void
+}
+
+interface ContextMenuProps {
+ onInsertText: (text: string) => void
+ onOpenUrlDialog: () => void
+ onPasteClipboardImage?: () => void
+ onPickFiles?: () => void
+ onPickFolders?: () => void
+ onPickImages?: () => void
+ state: ChatBarState
+}
+
+interface PromptSnippet {
+ description: string
+ label: string
+ text: string
+}
+
+interface PromptSnippetsDialogProps {
+ onInsertText: (text: string) => void
+ onOpenChange: (open: boolean) => void
+ open: boolean
+ snippets: readonly PromptSnippet[]
+}
diff --git a/apps/desktop/src/app/chat/composer/index.tsx b/apps/desktop/src/app/chat/composer/index.tsx
index a0b1a370baa..2a9580af3fd 100644
--- a/apps/desktop/src/app/chat/composer/index.tsx
+++ b/apps/desktop/src/app/chat/composer/index.tsx
@@ -1024,6 +1024,8 @@ export function ChatBar({
{/* assistant-ui requires ComposerPrimitive.Input somewhere in the tree
diff --git a/apps/desktop/src/app/chat/right-rail/preview.tsx b/apps/desktop/src/app/chat/right-rail/preview.tsx
index 268b9c41ce5..215991808e8 100644
--- a/apps/desktop/src/app/chat/right-rail/preview.tsx
+++ b/apps/desktop/src/app/chat/right-rail/preview.tsx
@@ -97,6 +97,17 @@ export function ChatPreviewRail({ onRestartServer, setTitlebarToolGroup }: ChatP
: 'border-r border-(--ui-stroke-quaternary) text-(--ui-text-tertiary) [--tab-bg:var(--ui-sidebar-surface-background)] hover:bg-(--chrome-action-hover) hover:text-foreground'
)}
key={tab.id}
+ // Middle-click closes the tab, matching browser/IDE muscle
+ // memory. `onMouseDown` swallows the middle-button press so
+ // Chromium doesn't switch into autoscroll mode.
+ onAuxClick={event => {
+ if (event.button !== 1) return
+ event.preventDefault()
+ closeRightRailTab(tab.id)
+ }}
+ onMouseDown={event => {
+ if (event.button === 1) event.preventDefault()
+ }}
>
{active && (
diff --git a/apps/desktop/src/app/chat/sidebar/index.tsx b/apps/desktop/src/app/chat/sidebar/index.tsx
index 351a57c0ded..d02c0e8e955 100644
--- a/apps/desktop/src/app/chat/sidebar/index.tsx
+++ b/apps/desktop/src/app/chat/sidebar/index.tsx
@@ -67,6 +67,12 @@ import { VirtualSessionList } from './virtual-session-list'
const VIRTUALIZE_THRESHOLD = 25
+// Render the modifier key the user actually presses on this platform. The
+// global accelerator is bound to both Cmd+N (macOS) and Ctrl+N (everywhere
+// else) in desktop-controller.tsx, but the hint should match muscle memory.
+const NEW_SESSION_KBD: readonly string[] =
+ typeof navigator !== 'undefined' && navigator.platform.toLowerCase().includes('mac') ? ['⌘', 'N'] : ['Ctrl', 'N']
+
const SIDEBAR_NAV: SidebarNavItem[] = [
{
id: 'new-session',
@@ -438,7 +444,7 @@ export function ChatSidebar({
<>
{item.label}
{item.id === 'new-session' && (
-
+
)}
>
)}
@@ -540,23 +546,28 @@ export function ChatSidebar({
forceEmptyState={showSessionSkeletons}
groups={agentsGrouped ? agentGroups : undefined}
headerAction={
-
{
- event.stopPropagation()
- setSidebarRecentsOpen(true)
- setSidebarAgentsGrouped(!agentsGrouped)
- }}
- size="icon-xs"
- title={agentsGrouped ? 'Ungroup sessions' : 'Group by workspace'}
- variant="ghost"
- >
-
-
+ // Grouping operates on unpinned recents; if everything is
+ // pinned the toggle does nothing visible, so hide it to avoid
+ // a phantom click target.
+ agentSessions.length > 0 ? (
+
{
+ event.stopPropagation()
+ setSidebarRecentsOpen(true)
+ setSidebarAgentsGrouped(!agentsGrouped)
+ }}
+ size="icon-xs"
+ title={agentsGrouped ? 'Ungroup sessions' : 'Group by workspace'}
+ variant="ghost"
+ >
+
+
+ ) : null
}
label="Sessions"
labelMeta={countLabel(agentSessions.length, knownSessionTotal)}
@@ -633,7 +644,7 @@ function SidebarPinnedEmptyState() {
-
Shift click to pin a chat
+
Shift-click a chat to pin · drag to reorder
)
}
diff --git a/apps/desktop/src/app/cron/index.tsx b/apps/desktop/src/app/cron/index.tsx
index b5c1deb083b..16a8c5c1c88 100644
--- a/apps/desktop/src/app/cron/index.tsx
+++ b/apps/desktop/src/app/cron/index.tsx
@@ -428,14 +428,6 @@ export function CronView({ setStatusbarItemGroup: _setStatusbarItemGroup, ...pro
return (
- setEditor({ mode: 'create' })} size="sm">
-
- New cron
-
-
- }
onSearchChange={setQuery}
searchPlaceholder="Search cron jobs..."
searchTrailingAction={
@@ -457,6 +449,10 @@ export function CronView({ setStatusbarItemGroup: _setStatusbarItemGroup, ...pro
{!jobs ? (
) : visibleJobs.length === 0 ? (
+ // Empty state owns the primary "create" CTA — we used to also have
+ // one in the filters bar but it was redundant. Only show the button
+ // when there are zero jobs total; the search-empty case ("No
+ // matches") just asks the user to broaden their query.
) : (
+ {/* Inline header replaces the old top-bar "New cron" button. We
+ still need a single, always-visible affordance to add a job
+ when the list is non-empty (rows themselves only expose
+ edit/pause/trigger/delete). */}
+
+
+ {enabledCount}/{totalCount} active
+
+ setEditor({ mode: 'create' })} size="sm">
+
+ New cron
+
+
{visibleJobs.map(job => (
)}
-
{totalCount === 0 ? 'No scheduled jobs' : `${enabledCount}/${totalCount} active`}
-
setEditor({ mode: 'closed' })} onSave={handleEditorSave} />
!open && !deleting && setPendingDelete(null)} open={pendingDelete !== null}>
diff --git a/apps/desktop/src/app/desktop-controller.tsx b/apps/desktop/src/app/desktop-controller.tsx
index 22bd7eedbe9..9e70acc3105 100644
--- a/apps/desktop/src/app/desktop-controller.tsx
+++ b/apps/desktop/src/app/desktop-controller.tsx
@@ -372,14 +372,22 @@ export function DesktopController() {
target instanceof HTMLTextAreaElement ||
target instanceof HTMLSelectElement
- if (editing || event.defaultPrevented || event.repeat || event.altKey || event.ctrlKey || event.metaKey) {
+ if (event.defaultPrevented || event.repeat || event.altKey || event.code !== 'KeyN') {
return
}
- if (event.shiftKey && event.code === 'KeyN') {
- event.preventDefault()
- startFreshSessionDraft()
+ // Two accelerators for "new session":
+ // - Cmd/Ctrl+N (browser-like, works while typing in any input)
+ // - Shift+N (single-key, only when no input is focused)
+ const accelerator = event.metaKey || event.ctrlKey
+ const singleKey = !accelerator && !editing && event.shiftKey
+
+ if (!accelerator && !singleKey) {
+ return
}
+
+ event.preventDefault()
+ startFreshSessionDraft()
}
window.addEventListener('keydown', onKeyDown)
diff --git a/apps/desktop/src/app/messaging/index.tsx b/apps/desktop/src/app/messaging/index.tsx
index 9d0904a70ba..a3fca713f2e 100644
--- a/apps/desktop/src/app/messaging/index.tsx
+++ b/apps/desktop/src/app/messaging/index.tsx
@@ -21,6 +21,8 @@ import { useRouteEnumParam } from '../hooks/use-route-enum-param'
import { PageSearchShell } from '../page-search-shell'
import type { SetStatusbarItemGroup } from '../shell/statusbar-controls'
+import { PlatformAvatar } from './platform-icon'
+
interface MessagingViewProps extends React.ComponentProps<'section'> {
setStatusbarItemGroup?: SetStatusbarItemGroup
}
@@ -39,29 +41,6 @@ const STATE_LABELS: Record = {
startup_failed: 'Startup failed'
}
-const PLATFORM_TINTS: Record = {
- telegram: 'bg-sky-500/15 text-sky-600 dark:text-sky-300',
- discord: 'bg-indigo-500/15 text-indigo-600 dark:text-indigo-300',
- slack: 'bg-violet-500/15 text-violet-600 dark:text-violet-300',
- mattermost: 'bg-blue-500/15 text-blue-600 dark:text-blue-300',
- matrix: 'bg-emerald-500/15 text-emerald-600 dark:text-emerald-300',
- signal: 'bg-cyan-500/15 text-cyan-600 dark:text-cyan-300',
- whatsapp: 'bg-green-500/15 text-green-600 dark:text-green-300',
- bluebubbles: 'bg-blue-500/15 text-blue-600 dark:text-blue-300',
- homeassistant: 'bg-teal-500/15 text-teal-600 dark:text-teal-300',
- email: 'bg-amber-500/15 text-amber-600 dark:text-amber-300',
- sms: 'bg-rose-500/15 text-rose-600 dark:text-rose-300',
- dingtalk: 'bg-blue-500/15 text-blue-600 dark:text-blue-300',
- feishu: 'bg-cyan-500/15 text-cyan-600 dark:text-cyan-300',
- wecom: 'bg-emerald-500/15 text-emerald-600 dark:text-emerald-300',
- wecom_callback: 'bg-emerald-500/15 text-emerald-600 dark:text-emerald-300',
- weixin: 'bg-green-500/15 text-green-600 dark:text-green-300',
- qqbot: 'bg-amber-500/15 text-amber-600 dark:text-amber-300',
- yuanbao: 'bg-orange-500/15 text-orange-600 dark:text-orange-300',
- api_server: 'bg-slate-500/15 text-slate-600 dark:text-slate-300',
- webhook: 'bg-zinc-500/15 text-zinc-600 dark:text-zinc-300'
-}
-
const PILL_TONE: Record = {
good: 'bg-primary/10 text-primary',
muted: 'bg-muted text-muted-foreground',
@@ -442,19 +421,6 @@ function PlatformRow({
)
}
-function PlatformAvatar({ platformId, platformName }: { platformId: string; platformName: string }) {
- return (
-
- {platformName.charAt(0).toUpperCase()}
-
- )
-}
-
function PlatformDetail({
edits,
onClear,
diff --git a/apps/desktop/src/app/messaging/platform-icon.tsx b/apps/desktop/src/app/messaging/platform-icon.tsx
new file mode 100644
index 00000000000..2212a58068d
--- /dev/null
+++ b/apps/desktop/src/app/messaging/platform-icon.tsx
@@ -0,0 +1,97 @@
+import type { ComponentType, SVGProps } from 'react'
+
+import {
+ SiApple,
+ SiBilibili,
+ SiDiscord,
+ SiGmail,
+ SiHomeassistant,
+ SiMatrix,
+ SiMattermost,
+ SiQq,
+ SiSignal,
+ SiTelegram,
+ SiWechat,
+ SiWhatsapp
+} from '@icons-pack/react-simple-icons'
+
+import { Globe, Link as LinkIcon, MessageSquareText } from '@/lib/icons'
+import { cn } from '@/lib/utils'
+
+// We render simpleicons.org brand glyphs for platforms whose owners publish a
+// usable mark (telegram, discord, matrix, ...). A few brands — Slack, Dingtalk,
+// Feishu, WeCom — have been removed from Simple Icons at the brand owner's
+// request, so we fall back to a colored letter monogram for those.
+//
+// `iconColor` is the brand's hex from simpleicons.org so we can paint each
+// glyph in its native color on top of a soft tint. The fallback monogram uses
+// the same hex to keep visual consistency.
+type IconKind = 'brand' | 'generic'
+
+interface PlatformIconSpec {
+ Icon: ComponentType>
+ color: string
+ kind: IconKind
+}
+
+const PLATFORM_ICONS: Record = {
+ telegram: { Icon: SiTelegram, color: '#26A5E4', kind: 'brand' },
+ discord: { Icon: SiDiscord, color: '#5865F2', kind: 'brand' },
+ // Slack removed from Simple Icons by Salesforce request — letter monogram.
+ mattermost: { Icon: SiMattermost, color: '#0058CC', kind: 'brand' },
+ matrix: { Icon: SiMatrix, color: '#000000', kind: 'brand' },
+ signal: { Icon: SiSignal, color: '#3A76F0', kind: 'brand' },
+ whatsapp: { Icon: SiWhatsapp, color: '#25D366', kind: 'brand' },
+ bluebubbles: { Icon: SiApple, color: '#0BD318', kind: 'brand' },
+ homeassistant: { Icon: SiHomeassistant, color: '#18BCF2', kind: 'brand' },
+ email: { Icon: SiGmail, color: '#EA4335', kind: 'brand' },
+ sms: { Icon: MessageSquareText, color: '#F43F5E', kind: 'generic' },
+ webhook: { Icon: LinkIcon, color: '#71717A', kind: 'generic' },
+ api_server: { Icon: Globe, color: '#64748B', kind: 'generic' },
+ weixin: { Icon: SiWechat, color: '#07C160', kind: 'brand' },
+ qqbot: { Icon: SiQq, color: '#EB1923', kind: 'brand' },
+ yuanbao: { Icon: SiBilibili, color: '#FB7299', kind: 'brand' }
+}
+
+interface PlatformAvatarProps {
+ platformId: string
+ platformName: string
+ className?: string
+}
+
+export function PlatformAvatar({ className, platformId, platformName }: PlatformAvatarProps) {
+ const spec = PLATFORM_ICONS[platformId]
+
+ const baseClass = cn(
+ 'inline-grid size-6 shrink-0 place-items-center rounded-md text-[length:var(--conversation-caption-font-size)] font-medium',
+ className
+ )
+
+ if (!spec) {
+ return (
+
+ {platformName.charAt(0).toUpperCase()}
+
+ )
+ }
+
+ const { Icon, color } = spec
+
+ return (
+
+
+
+ )
+}
diff --git a/apps/desktop/src/app/page-search-shell.tsx b/apps/desktop/src/app/page-search-shell.tsx
index 6e7d3432be1..fc29935dca0 100644
--- a/apps/desktop/src/app/page-search-shell.tsx
+++ b/apps/desktop/src/app/page-search-shell.tsx
@@ -28,10 +28,16 @@ export function PageSearchShell({
{...props}
className={cn('flex h-full min-w-0 flex-col overflow-hidden bg-(--ui-chat-surface-background)', className)}
>
-
+ {/*
+ This header sits in the titlebar row, so it overlaps the OS window-drag
+ region painted by the shell. Without `-webkit-app-region: no-drag` on
+ the search row, mousedown on the input gets intercepted as a window-
+ drag start and the input never receives focus (visible as "I can't
+ click the search box" on the messaging/cron/etc pages).
+ */}
+
{/* Reserve the top-right titlebar tools + native window-controls
- footprint so the full-width search input never slides under them
- (this header sits in the titlebar row at the window top). */}
+ footprint so the full-width search input never slides under them. */}
prev.filter(s => s.id !== storedSessionId))
+ // Keep $sessionsTotal in sync so the sidebar's "Load N more" footer
+ // doesn't keep claiming the removed row is still on the server.
+ setSessionsTotal(prev => Math.max(0, prev - 1))
$pinnedSessionIds.set(previousPinned.filter(id => id !== storedSessionId))
// Tear down before awaiting so the route effect can't resume the
@@ -711,6 +715,7 @@ export function useSessionActions({
} catch (err) {
if (removed) {
setSessions(prev => [removed, ...prev])
+ setSessionsTotal(prev => prev + 1)
}
$pinnedSessionIds.set(previousPinned)
@@ -763,6 +768,10 @@ export function useSessionActions({
// Soft-hide: drop from the sidebar immediately, keep the data.
setSessions(prev => prev.filter(s => s.id !== storedSessionId))
+ // Archived sessions are hidden by the listSessions(min_messages=1) query
+ // on the next refresh, so they count as "removed" for the load-more
+ // footer math.
+ setSessionsTotal(prev => Math.max(0, prev - 1))
$pinnedSessionIds.set(previousPinned.filter(id => id !== storedSessionId))
if (wasSelected) {
@@ -775,6 +784,7 @@ export function useSessionActions({
} catch (err) {
if (archived) {
setSessions(prev => [archived, ...prev.filter(s => s.id !== storedSessionId)])
+ setSessionsTotal(prev => prev + 1)
}
$pinnedSessionIds.set(previousPinned)
diff --git a/apps/desktop/src/app/session/hooks/use-session-state-cache.ts b/apps/desktop/src/app/session/hooks/use-session-state-cache.ts
index 398c3c9325d..683d342dd38 100644
--- a/apps/desktop/src/app/session/hooks/use-session-state-cache.ts
+++ b/apps/desktop/src/app/session/hooks/use-session-state-cache.ts
@@ -4,7 +4,7 @@ import { type MutableRefObject, useCallback, useEffect, useRef } from 'react'
import type { ChatMessage } from '@/lib/chat-messages'
import { preserveLocalAssistantErrors } from '@/lib/chat-messages'
import { createClientSessionState } from '@/lib/chat-runtime'
-import { $busy, $messages, setSessionWorking } from '@/store/session'
+import { $busy, $messages, noteSessionActivity, setSessionWorking } from '@/store/session'
import type { ClientSessionState } from '../../types'
@@ -140,6 +140,13 @@ export function useSessionStateCache({
}
setSessionWorking(next.storedSessionId, next.busy)
+ // Every state update is effectively a "still alive" heartbeat for
+ // streaming events. The session-store watchdog uses this to keep the
+ // working flag alive during long-running turns and to clear it once
+ // the stream goes silent.
+ if (next.busy) {
+ noteSessionActivity(next.storedSessionId)
+ }
syncSessionStateToView(sessionId, next)
return next
diff --git a/apps/desktop/src/app/settings/about-settings.tsx b/apps/desktop/src/app/settings/about-settings.tsx
index e178b998dc2..991b860624b 100644
--- a/apps/desktop/src/app/settings/about-settings.tsx
+++ b/apps/desktop/src/app/settings/about-settings.tsx
@@ -1,5 +1,5 @@
import { useStore } from '@nanostores/react'
-import { useState } from 'react'
+import { useEffect, useState } from 'react'
import { Button } from '@/components/ui/button'
import { CheckCircle2, ExternalLink, Loader2, RefreshCw, Sparkles } from '@/lib/icons'
@@ -10,7 +10,8 @@ import {
$updateChecking,
$updateStatus,
checkUpdates,
- openUpdatesWindow
+ openUpdatesWindow,
+ refreshDesktopVersion
} from '@/store/updates'
import { ListRow, SectionHeading, SettingsContent } from './primitives'
@@ -46,6 +47,14 @@ export function AboutSettings() {
const checking = useStore($updateChecking)
const [justChecked, setJustChecked] = useState(false)
+ // The version atom is loaded once at app boot, which makes About show a
+ // stale number after a self-update (the running binary is current, the
+ // displayed string is not). Re-read on mount so opening About always
+ // reflects the running build.
+ useEffect(() => {
+ void refreshDesktopVersion()
+ }, [])
+
const behind = status?.behind ?? 0
const supported = status?.supported !== false
const applying = apply.applying || apply.stage === 'restart'
diff --git a/apps/desktop/src/app/settings/keys-settings.tsx b/apps/desktop/src/app/settings/keys-settings.tsx
index 242485e5c8b..0b778b12e1d 100644
--- a/apps/desktop/src/app/settings/keys-settings.tsx
+++ b/apps/desktop/src/app/settings/keys-settings.tsx
@@ -22,8 +22,6 @@ import {
import { LoadingState, Pill, SectionHeading, SettingsContent } from './primitives'
import type { EnvPatch, EnvRowProps, ProviderGroup, SearchProps } from './types'
-const SHOW_ADVANCED_STORAGE_KEY = 'desktop.settings.keys.show_advanced'
-
interface EnvActionsProps {
varKey: string
info: EnvVarInfo
@@ -186,8 +184,11 @@ function EnvProviderGroup({
group: ProviderGroup
rowProps: Omit
}) {
- const [expanded, setExpanded] = useState(false)
const setCount = group.entries.filter(([, info]) => info.is_set).length
+ // Default-expand providers that already have at least one key set; the
+ // user is much more likely to be coming back to edit those than to start
+ // configuring a fresh provider from scratch.
+ const [expanded, setExpanded] = useState(setCount > 0)
return (
@@ -222,27 +223,17 @@ export function KeysSettings({ query }: SearchProps) {
const [revealed, setRevealed] = useState
>({})
const [saving, setSaving] = useState(null)
- const [showAdvanced, setShowAdvanced] = useState(() => {
- try {
- const stored = window.localStorage.getItem(SHOW_ADVANCED_STORAGE_KEY)
-
- if (stored === null) {
- return false
- }
-
- return stored === 'true'
- } catch {
- return false
- }
- })
-
+ // We used to hide ~80% of rows behind a global "Show advanced" toggle, but
+ // everything in this view is configuration-level — "advanced" was a poor
+ // distinction. The full list is rendered now and provider groups
+ // default-collapsed-unless-set keep the surface manageable.
useEffect(() => {
try {
- window.localStorage.setItem(SHOW_ADVANCED_STORAGE_KEY, showAdvanced ? 'true' : 'false')
+ window.localStorage.removeItem('desktop.settings.keys.show_advanced')
} catch {
- // Ignore persistence failures and keep in-memory preference.
+ // Ignore — old key cleanup is best-effort.
}
- }, [showAdvanced])
+ }, [])
useEffect(() => {
let cancelled = false
@@ -262,28 +253,21 @@ export function KeysSettings({ query }: SearchProps) {
return () => void (cancelled = true)
}, [])
- const filterEnv = useCallback(
- (info: EnvVarInfo, key: string, q: string, cat: string, extra?: string) => {
- if (asText(info.category) !== cat) {
- return false
- }
+ const filterEnv = useCallback((info: EnvVarInfo, key: string, q: string, cat: string, extra?: string) => {
+ if (asText(info.category) !== cat) {
+ return false
+ }
- if (!showAdvanced && Boolean(info.advanced)) {
- return false
- }
+ if (!q) {
+ return true
+ }
- if (!q) {
- return true
- }
-
- return (
- key.toLowerCase().includes(q) ||
- includesQuery(info.description, q) ||
- Boolean(extra && extra.toLowerCase().includes(q))
- )
- },
- [showAdvanced]
- )
+ return (
+ key.toLowerCase().includes(q) ||
+ includesQuery(info.description, q) ||
+ Boolean(extra && extra.toLowerCase().includes(q))
+ )
+ }, [])
const providerGroups = useMemo(() => {
if (!vars) {
@@ -415,12 +399,6 @@ export function KeysSettings({ query }: SearchProps) {
return (
-
- setShowAdvanced(s => !s)} size="sm" variant="outline">
- {showAdvanced ? 'Hide advanced' : 'Show advanced'}
-
-
-
+
+
)
}
+
+// Lets the user pin the default cwd for new sessions. Without this, packaged
+// builds on Windows used to spawn sessions in the install dir (`win-unpacked`
+// / Program Files), which buried any files Hermes wrote there.
+function DefaultProjectDirSetting() {
+ const [dir, setDir] = useState(null)
+ const [fallback, setFallback] = useState('')
+ const [busy, setBusy] = useState(false)
+
+ useEffect(() => {
+ // The bridge is only present when running inside Electron. In a Vitest
+ // / Storybook / non-Electron context `window.hermesDesktop` is
+ // undefined, so guard the WHOLE call chain rather than chaining
+ // `?.settings.getDefaultProjectDir().then(...)` (the latter would
+ // short-circuit to `undefined.then(...)` and throw at runtime).
+ const settings = window.hermesDesktop?.settings
+
+ if (!settings) {
+ return
+ }
+
+ let alive = true
+
+ void settings.getDefaultProjectDir().then(result => {
+ if (!alive) return
+ setDir(result.dir)
+ setFallback(result.defaultLabel)
+ })
+
+ return () => {
+ alive = false
+ }
+ }, [])
+
+ const choose = useCallback(async () => {
+ const settings = window.hermesDesktop?.settings
+
+ if (!settings) return
+
+ setBusy(true)
+
+ try {
+ const picked = await settings.pickDefaultProjectDir()
+
+ if (picked.canceled || !picked.dir) {
+ return
+ }
+
+ const result = await settings.setDefaultProjectDir(picked.dir)
+ setDir(result.dir)
+ notify({ durationMs: 2_000, kind: 'success', message: 'Default project directory updated' })
+ } catch (err) {
+ notifyError(err, 'Could not update default directory')
+ } finally {
+ setBusy(false)
+ }
+ }, [])
+
+ const clear = useCallback(async () => {
+ const settings = window.hermesDesktop?.settings
+
+ if (!settings) return
+
+ setBusy(true)
+
+ try {
+ await settings.setDefaultProjectDir(null)
+ setDir(null)
+ } catch (err) {
+ notifyError(err, 'Could not clear default directory')
+ } finally {
+ setBusy(false)
+ }
+ }, [])
+
+ return (
+
+
+
+ New sessions start in this folder unless you pick another. Leave it unset to use your home directory.
+
+
+ void choose()} size="sm" type="button" variant="outline">
+
+ {dir ? 'Change' : 'Choose'}
+
+ {dir && (
+ void clear()} size="sm" type="button" variant="ghost">
+ Clear
+
+ )}
+
+ }
+ description={dir || `Defaults to ${fallback || '~/hermes-projects'}.`}
+ title={dir ? dir : 'Not set'}
+ />
+
+ )
+}
diff --git a/apps/desktop/src/app/shell/statusbar-controls.tsx b/apps/desktop/src/app/shell/statusbar-controls.tsx
index 227d59dc8c5..084614960a3 100644
--- a/apps/desktop/src/app/shell/statusbar-controls.tsx
+++ b/apps/desktop/src/app/shell/statusbar-controls.tsx
@@ -54,14 +54,18 @@ export function StatusbarControls({ className, leftItems = [], items = [], ...pr
)}
{...props}
>
-
+ {/* `overflow-x-clip` (not `overflow-x-auto`) so a wide status item — for
+ example "Connecting…" on a fresh/untitled session — can't paint a
+ horizontal scrollbar across the bottom of the window. Items already
+ `truncate` their labels, so clipping is the right behavior. */}
+
{leftItems
.filter(item => !item.hidden)
.map(item => (
))}
-
+
{items
.filter(item => !item.hidden)
.map(item => (
diff --git a/apps/desktop/src/app/shell/titlebar.ts b/apps/desktop/src/app/shell/titlebar.ts
index b3ed2b630af..34f0da8e5ad 100644
--- a/apps/desktop/src/app/shell/titlebar.ts
+++ b/apps/desktop/src/app/shell/titlebar.ts
@@ -13,7 +13,7 @@ export const TITLEBAR_FALLBACK_WINDOW_BUTTON_X = 24
export const TITLEBAR_EDGE_INSET = 14
export const titlebarButtonClass =
- 'h-[var(--titlebar-control-height)] w-[var(--titlebar-control-size)] rounded-md text-muted-foreground/85 transition-colors hover:bg-(--ui-control-hover-background) hover:text-foreground'
+ 'h-[var(--titlebar-control-height)] w-[var(--titlebar-control-size)] cursor-pointer rounded-md text-muted-foreground/85 transition-colors hover:bg-(--ui-control-hover-background) hover:text-foreground'
export const titlebarHeaderBaseClass =
'pointer-events-none relative z-3 flex h-(--titlebar-height) shrink-0 items-center justify-start gap-3 border-b border-(--ui-stroke-tertiary) bg-(--ui-chat-surface-background) px-[max(0.75rem,var(--titlebar-content-inset,0rem))]'
diff --git a/apps/desktop/src/components/assistant-ui/ansi-text.tsx b/apps/desktop/src/components/assistant-ui/ansi-text.tsx
new file mode 100644
index 00000000000..99ced1f6c44
--- /dev/null
+++ b/apps/desktop/src/components/assistant-ui/ansi-text.tsx
@@ -0,0 +1,34 @@
+import type { FC } from 'react'
+import { useMemo } from 'react'
+
+import { ansiColorClass, hasAnsiCodes, parseAnsi } from '@/lib/ansi'
+import { cn } from '@/lib/utils'
+
+interface AnsiTextProps {
+ text: string
+ className?: string
+}
+
+/** Renders text with embedded ANSI SGR codes as colored / bold spans. Falls
+ * back to a plain string node when no codes are present so the parser cost
+ * is paid only when there's something to colorize. */
+export const AnsiText: FC
= ({ className, text }) => {
+ const segments = useMemo(() => (hasAnsiCodes(text) ? parseAnsi(text) : null), [text])
+
+ if (!segments) {
+ return {text}
+ }
+
+ return (
+
+ {segments.map((segment, index) => (
+
+ {segment.text}
+
+ ))}
+
+ )
+}
diff --git a/apps/desktop/src/components/assistant-ui/thread.tsx b/apps/desktop/src/components/assistant-ui/thread.tsx
index 0c90d29903d..7b03c9991e0 100644
--- a/apps/desktop/src/components/assistant-ui/thread.tsx
+++ b/apps/desktop/src/components/assistant-ui/thread.tsx
@@ -48,7 +48,8 @@ import { detectTrigger, textBeforeCaret, type TriggerState } from '@/app/chat/co
import { ComposerTriggerPopover } from '@/app/chat/composer/trigger-popover'
import { extractDroppedFiles, HERMES_PATHS_MIME } from '@/app/chat/hooks/use-composer-actions'
import { ClarifyTool } from '@/components/assistant-ui/clarify-tool'
-import { DirectiveContent, DirectiveText } from '@/components/assistant-ui/directive-text'
+import { DirectiveContent } from '@/components/assistant-ui/directive-text'
+import { UserMessageText } from '@/components/assistant-ui/user-message-text'
import { hermesDirectiveFormatter } from '@/components/assistant-ui/directive-text'
import { MarkdownText } from '@/components/assistant-ui/markdown-text'
import { VirtualizedThread } from '@/components/assistant-ui/thread-virtualizer'
@@ -703,9 +704,10 @@ const UserMessage: FC<{
)}
{hasBody && (
-
-
-
+ // Render the user's text through a minimal markdown pipeline:
+ // backtick `code` and ``` fenced ``` blocks, with directive chips
+ // (`@file:` etc.) still resolved inside the plain-text spans.
+
)}
>
)
diff --git a/apps/desktop/src/components/assistant-ui/tool-fallback-model.ts b/apps/desktop/src/components/assistant-ui/tool-fallback-model.ts
index b31b1e8c8af..c5b4d7a789f 100644
--- a/apps/desktop/src/components/assistant-ui/tool-fallback-model.ts
+++ b/apps/desktop/src/components/assistant-ui/tool-fallback-model.ts
@@ -35,7 +35,18 @@ export interface ToolView {
previewTarget?: string
rawArgs: string
rawResult: string
+ /** Set for tools whose output naturally contains ANSI escape codes
+ * (terminal/execute_code) so the renderer knows to run them through
+ * the ANSI parser instead of printing them as literals. */
+ rendersAnsi?: boolean
searchHits?: SearchResultRow[]
+ /** When the backend reports stderr as a separate stream (terminal /
+ * execute_code), the renderer shows it as its own labeled, neutrally
+ * tinted block under stdout — distinct from an error tone. */
+ stderr?: string
+ /** When set, the renderer uses stdout+stderr as separate sections and
+ * ignores the merged `detail`. */
+ stdout?: string
status: ToolStatus
subtitle: string
title: string
@@ -1002,6 +1013,10 @@ function toolDetailText(
}
if (part.toolName === 'terminal' || part.toolName === 'execute_code') {
+ // Streams are split out into ToolView.stdout / ToolView.stderr by
+ // buildToolView so the renderer can label them separately. The merged
+ // fallback here is only used when the backend doesn't expose either
+ // stream individually.
const output = firstStringField(resultRecord, ['output', 'stdout', 'stderr'])
const lines = Array.isArray(resultRecord.lines)
@@ -1209,6 +1224,18 @@ export function buildToolView(part: ToolPart, inlineDiff: string): ToolView {
const resultCount = status === 'error' ? null : toolResultCount(part, argsRecord, resultRecord)
+ // For shell/code tools we surface stdout and stderr as separate labeled
+ // streams in the renderer. Many CLIs use stderr for informational
+ // messages (npm progress, git hints), so we deliberately don't paint
+ // stderr destructively even though it's tagged.
+ const rendersAnsi = part.toolName === 'terminal' || part.toolName === 'execute_code'
+ const stdout = rendersAnsi ? firstStringField(resultRecord, ['stdout']) : ''
+ const stderrRaw = rendersAnsi ? firstStringField(resultRecord, ['stderr']) : ''
+ // Only attach stderr when the backend actually returned it as its own
+ // field — otherwise the merged `detail` already covers it and double-
+ // rendering would duplicate output.
+ const hasSplitStreams = rendersAnsi && (Boolean(stdout) || Boolean(stderrRaw))
+
return {
countLabel: resultCount ? formatCountLabel(resultCount) : undefined,
detail,
@@ -1220,7 +1247,10 @@ export function buildToolView(part: ToolPart, inlineDiff: string): ToolView {
previewTarget: toolPreviewTarget(part.toolName, argsRecord, resultRecord),
rawArgs: prettyJson(part.args),
rawResult: prettyJson(part.result),
+ rendersAnsi: rendersAnsi || undefined,
searchHits: searchHits?.length ? searchHits : undefined,
+ stderr: hasSplitStreams ? stderrRaw || undefined : undefined,
+ stdout: hasSplitStreams ? stdout || undefined : undefined,
status,
subtitle,
title,
diff --git a/apps/desktop/src/components/assistant-ui/tool-fallback.tsx b/apps/desktop/src/components/assistant-ui/tool-fallback.tsx
index 5e2f75ae167..cb8cd2194ce 100644
--- a/apps/desktop/src/components/assistant-ui/tool-fallback.tsx
+++ b/apps/desktop/src/components/assistant-ui/tool-fallback.tsx
@@ -5,6 +5,7 @@ import { useStore } from '@nanostores/react'
import { createContext, type FC, type PropsWithChildren, type ReactNode, useContext, useMemo } from 'react'
import { useShallow } from 'zustand/shallow'
+import { AnsiText } from '@/components/assistant-ui/ansi-text'
import { useElapsedSeconds } from '@/components/chat/activity-timer'
import { ActivityTimerText } from '@/components/chat/activity-timer-text'
import { CompactMarkdown } from '@/components/chat/compact-markdown'
@@ -344,11 +345,41 @@ function ToolEntry({ part }: ToolEntryProps) {
)}
) : null
+ ) : view.stdout || view.stderr ? (
+ // Stdout + stderr split: render both as labeled blocks. stderr
+ // is intentionally NOT painted destructive — many CLIs log
+ // informational output there.
+
+ {view.detailLabel &&
{view.detailLabel}
}
+ {view.stdout && (
+
+ {view.stderr &&
stdout
}
+
+ {view.rendersAnsi ? : view.stdout}
+
+
+ )}
+ {view.stderr && (
+
+
stderr
+
+ {view.rendersAnsi ? : view.stderr}
+
+
+ )}
+
) : (
{view.detailLabel &&
{view.detailLabel}
}
{renderDetailAsCode ? (
-
{view.detail}
+
+ {view.rendersAnsi ? : view.detail}
+
) : (
)}
diff --git a/apps/desktop/src/components/assistant-ui/user-message-text.tsx b/apps/desktop/src/components/assistant-ui/user-message-text.tsx
new file mode 100644
index 00000000000..9e0da646f29
--- /dev/null
+++ b/apps/desktop/src/components/assistant-ui/user-message-text.tsx
@@ -0,0 +1,150 @@
+import type { FC } from 'react'
+import { Fragment, useMemo } from 'react'
+
+import { DirectiveContent } from '@/components/assistant-ui/directive-text'
+import { cn } from '@/lib/utils'
+
+// User messages should render the bare-minimum of markdown: backtick `code`
+// spans and ``` fenced blocks. We deliberately don't pull in the full
+// assistant Markdown pipeline (Streamdown + KaTeX + syntax highlighter)
+// because user input rarely contains structured docs and the heavy pipeline
+// adds a lot of runtime cost per bubble.
+//
+// Directive chips (`@file:`, `@image:`, ...) still resolve via DirectiveContent
+// inside the plain-text segments.
+
+interface FenceSegment {
+ kind: 'fence'
+ code: string
+ lang: string | null
+}
+
+interface InlineSegment {
+ kind: 'inline'
+ text: string
+}
+
+interface InlineCodeSegment {
+ kind: 'inline-code'
+ code: string
+}
+
+interface InlineTextSegment {
+ kind: 'inline-text'
+ text: string
+}
+
+type TopSegment = FenceSegment | InlineSegment
+type InlineNode = InlineCodeSegment | InlineTextSegment
+
+const FENCE_RE = /```([^\n`]*)\n([\s\S]*?)```/g
+
+// Greedy backtick run length so ``code with `backticks` inside`` works.
+const INLINE_CODE_RE = /(`+)([^`\n][\s\S]*?)\1/g
+
+function splitFences(text: string): TopSegment[] {
+ const segments: TopSegment[] = []
+ let cursor = 0
+
+ for (const match of text.matchAll(FENCE_RE)) {
+ const start = match.index ?? 0
+
+ if (start > cursor) {
+ segments.push({ kind: 'inline', text: text.slice(cursor, start) })
+ }
+
+ segments.push({
+ kind: 'fence',
+ lang: (match[1] || '').trim() || null,
+ code: match[2] ?? ''
+ })
+ cursor = start + match[0].length
+ }
+
+ if (cursor < text.length) {
+ segments.push({ kind: 'inline', text: text.slice(cursor) })
+ }
+
+ return segments
+}
+
+function splitInlineCode(text: string): InlineNode[] {
+ const nodes: InlineNode[] = []
+ let cursor = 0
+
+ for (const match of text.matchAll(INLINE_CODE_RE)) {
+ const start = match.index ?? 0
+
+ if (start > cursor) {
+ nodes.push({ kind: 'inline-text', text: text.slice(cursor, start) })
+ }
+
+ nodes.push({ kind: 'inline-code', code: match[2] })
+ cursor = start + match[0].length
+ }
+
+ if (cursor < text.length) {
+ nodes.push({ kind: 'inline-text', text: text.slice(cursor) })
+ }
+
+ return nodes
+}
+
+interface UserMessageTextProps {
+ text: string
+ className?: string
+}
+
+export const UserMessageText: FC
= ({ className, text }) => {
+ const top = useMemo(() => splitFences(text), [text])
+
+ return (
+
+ {top.map((segment, segmentIndex) => {
+ if (segment.kind === 'fence') {
+ return (
+
+ {segment.code}
+
+ )
+ }
+
+ return (
+
+
+
+ )
+ })}
+
+ )
+}
+
+const InlineSegmentView: FC<{ text: string }> = ({ text }) => {
+ const nodes = useMemo(() => splitInlineCode(text), [text])
+
+ return (
+
+ {nodes.map((node, nodeIndex) =>
+ node.kind === 'inline-code' ? (
+
+ {node.code}
+
+ ) : (
+ // Pass plain-text bits through DirectiveContent so @file:/@url: chips
+ // still render. DirectiveContent already preserves whitespace.
+
+
+
+ )
+ )}
+
+ )
+}
diff --git a/apps/desktop/src/components/ui/button.tsx b/apps/desktop/src/components/ui/button.tsx
index 467f4c0a5df..be38242bfa4 100644
--- a/apps/desktop/src/components/ui/button.tsx
+++ b/apps/desktop/src/components/ui/button.tsx
@@ -5,7 +5,7 @@ import * as React from 'react'
import { cn } from '@/lib/utils'
const buttonVariants = cva(
- "inline-flex shrink-0 items-center justify-center gap-2 rounded-md text-sm font-medium whitespace-nowrap transition-all outline-none focus-visible:border-ring focus-visible:ring-[0.1875rem] focus-visible:ring-ring/50 disabled:pointer-events-none disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
+ "inline-flex shrink-0 cursor-pointer items-center justify-center gap-2 rounded-md text-sm font-medium whitespace-nowrap transition-all outline-none focus-visible:border-ring focus-visible:ring-[0.1875rem] focus-visible:ring-ring/50 disabled:pointer-events-none disabled:cursor-default disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
{
variants: {
variant: {
diff --git a/apps/desktop/src/components/ui/dialog.tsx b/apps/desktop/src/components/ui/dialog.tsx
index 4f732954a2e..66e93103bf7 100644
--- a/apps/desktop/src/components/ui/dialog.tsx
+++ b/apps/desktop/src/components/ui/dialog.tsx
@@ -46,7 +46,10 @@ function DialogContent({
) {
return (
void
openExternal: (url: string) => Promise
fetchLinkTitle: (url: string) => Promise
+ settings: {
+ getDefaultProjectDir: () => Promise<{ defaultLabel: string; dir: null | string }>
+ pickDefaultProjectDir: () => Promise<{ canceled: boolean; dir: null | string }>
+ setDefaultProjectDir: (dir: null | string) => Promise<{ dir: null | string }>
+ }
revealLogs: () => Promise<{ ok: boolean; path: string; error?: string }>
getRecentLogs: () => Promise<{ path: string; lines: string[] }>
readDir: (path: string) => Promise
diff --git a/apps/desktop/src/lib/ansi.test.ts b/apps/desktop/src/lib/ansi.test.ts
new file mode 100644
index 00000000000..30b9d410c2f
--- /dev/null
+++ b/apps/desktop/src/lib/ansi.test.ts
@@ -0,0 +1,123 @@
+import { describe, expect, it } from 'vitest'
+
+import { ansiColorClass, hasAnsiCodes, parseAnsi } from './ansi'
+
+const ESC = '\x1b'
+
+describe('parseAnsi', () => {
+ it('returns a single default segment for plain text', () => {
+ expect(parseAnsi('hello world')).toEqual([{ bold: false, fg: null, text: 'hello world' }])
+ })
+
+ it('returns nothing for an empty string', () => {
+ expect(parseAnsi('')).toEqual([])
+ })
+
+ it('parses a basic foreground color sequence and resets', () => {
+ const input = `${ESC}[31merror${ESC}[0m ok`
+
+ expect(parseAnsi(input)).toEqual([
+ { bold: false, fg: 'red', text: 'error' },
+ { bold: false, fg: null, text: ' ok' }
+ ])
+ })
+
+ it('treats bold (1) and bold-off (22) as toggles without affecting fg', () => {
+ const input = `${ESC}[1mloud${ESC}[22m quiet`
+
+ expect(parseAnsi(input)).toEqual([
+ { bold: true, fg: null, text: 'loud' },
+ { bold: false, fg: null, text: ' quiet' }
+ ])
+ })
+
+ it('treats default-fg (39) as a foreground-only reset (keeps bold)', () => {
+ const input = `${ESC}[1;31mboth${ESC}[39mbold-only`
+
+ expect(parseAnsi(input)).toEqual([
+ { bold: true, fg: 'red', text: 'both' },
+ { bold: true, fg: null, text: 'bold-only' }
+ ])
+ })
+
+ it('handles bright colors via the 90-97 range', () => {
+ expect(parseAnsi(`${ESC}[92mgreen`)).toEqual([{ bold: false, fg: 'bright-green', text: 'green' }])
+ })
+
+ it('coalesces adjacent runs with the same style', () => {
+ const input = `${ESC}[31ma${ESC}[31mb${ESC}[31mc`
+
+ expect(parseAnsi(input)).toEqual([{ bold: false, fg: 'red', text: 'abc' }])
+ })
+
+ it('skips 256-color (38;5) trailing args without painting fg or leaking the params as text', () => {
+ // 256-color and truecolor aren't rendered (FG_BY_CODE doesn't cover them),
+ // but the parser must consume the trailing `;5;` / `;2;r;g;b` args so
+ // they never bleed into the visible segment text.
+ const segments = parseAnsi(`${ESC}[38;5;208morange${ESC}[0m`)
+
+ expect(segments).toHaveLength(1)
+ expect(segments[0].fg).toBe(null)
+ expect(segments[0].text).toBe('orange')
+ })
+
+ it('skips truecolor (38;2;r;g;b) trailing args', () => {
+ const segments = parseAnsi(`${ESC}[38;2;10;20;30mrgb${ESC}[0m`)
+
+ expect(segments).toHaveLength(1)
+ expect(segments[0].fg).toBe(null)
+ expect(segments[0].text).toBe('rgb')
+ })
+
+ it('drops non-SGR CSI sequences (cursor motion, erase) without consuming surrounding text', () => {
+ const input = `before${ESC}[2Jmiddle${ESC}[10;5Hafter`
+
+ expect(parseAnsi(input)).toEqual([{ bold: false, fg: null, text: 'beforemiddleafter' }])
+ })
+
+ it('treats an empty SGR parameter (ESC[m) as a full reset', () => {
+ const input = `${ESC}[1;31mfoo${ESC}[mbar`
+
+ expect(parseAnsi(input)).toEqual([
+ { bold: true, fg: 'red', text: 'foo' },
+ { bold: false, fg: null, text: 'bar' }
+ ])
+ })
+})
+
+describe('hasAnsiCodes', () => {
+ it('returns false for plain text', () => {
+ expect(hasAnsiCodes('hello world')).toBe(false)
+ })
+
+ it('returns true when any CSI introducer is present', () => {
+ expect(hasAnsiCodes(`${ESC}[31mred`)).toBe(true)
+ })
+})
+
+describe('ansiColorClass', () => {
+ it('returns a non-empty Tailwind class string for every supported color', () => {
+ const colors = [
+ 'black',
+ 'red',
+ 'green',
+ 'yellow',
+ 'blue',
+ 'magenta',
+ 'cyan',
+ 'white',
+ 'bright-black',
+ 'bright-red',
+ 'bright-green',
+ 'bright-yellow',
+ 'bright-blue',
+ 'bright-magenta',
+ 'bright-cyan',
+ 'bright-white'
+ ] as const
+
+ for (const color of colors) {
+ expect(ansiColorClass(color)).toMatch(/\S/)
+ }
+ })
+})
diff --git a/apps/desktop/src/lib/ansi.ts b/apps/desktop/src/lib/ansi.ts
new file mode 100644
index 00000000000..9503ac9ad08
--- /dev/null
+++ b/apps/desktop/src/lib/ansi.ts
@@ -0,0 +1,175 @@
+// Minimal ANSI SGR parser for rendering terminal output inside chat tool
+// cards. Only handles the SGR codes that show up in practice (color, bold,
+// reset); cursor motions and other CSI sequences are dropped silently.
+//
+// Returns a flat array of styled segments so callers can render them as
+// React spans without each consumer having to re-implement the parser.
+
+export interface AnsiSegment {
+ bold: boolean
+ /** Tailwind text-color class or null for the default foreground. */
+ fg: AnsiColor | null
+ text: string
+}
+
+export type AnsiColor =
+ | 'black'
+ | 'red'
+ | 'green'
+ | 'yellow'
+ | 'blue'
+ | 'magenta'
+ | 'cyan'
+ | 'white'
+ | 'bright-black'
+ | 'bright-red'
+ | 'bright-green'
+ | 'bright-yellow'
+ | 'bright-blue'
+ | 'bright-magenta'
+ | 'bright-cyan'
+ | 'bright-white'
+
+const FG_BY_CODE: Record = {
+ 30: 'black',
+ 31: 'red',
+ 32: 'green',
+ 33: 'yellow',
+ 34: 'blue',
+ 35: 'magenta',
+ 36: 'cyan',
+ 37: 'white',
+ 90: 'bright-black',
+ 91: 'bright-red',
+ 92: 'bright-green',
+ 93: 'bright-yellow',
+ 94: 'bright-blue',
+ 95: 'bright-magenta',
+ 96: 'bright-cyan',
+ 97: 'bright-white'
+}
+
+// CSI = ESC '[' params 'final'. We only care about SGR (final == 'm'); other
+// final bytes are matched and consumed so they don't leak into the rendered
+// text. Range covers the common CSI command set (A-Z / a-z / @).
+// eslint-disable-next-line no-control-regex
+const CSI_RE = /\x1b\[([\d;]*)([\x40-\x7e])/g
+// Other escape sequences (single-char OSC/SS3/etc.) — strip silently.
+// eslint-disable-next-line no-control-regex
+const OTHER_ESCAPE_RE = /\x1b[@-Z\\-_]|\x1b\][^\x07\x1b]*(?:\x07|\x1b\\)/g
+
+export function parseAnsi(input: string): AnsiSegment[] {
+ if (!input) {
+ return []
+ }
+
+ // Strip non-CSI escapes upfront — none of them carry text we want to keep
+ // and CSI_RE wouldn't match them.
+ const cleaned = input.replace(OTHER_ESCAPE_RE, '')
+
+ const segments: AnsiSegment[] = []
+ let cursor = 0
+ let bold = false
+ let fg: AnsiColor | null = null
+
+ const pushText = (text: string) => {
+ if (!text) {
+ return
+ }
+
+ const last = segments.at(-1)
+
+ if (last && last.bold === bold && last.fg === fg) {
+ last.text += text
+
+ return
+ }
+
+ segments.push({ bold, fg, text })
+ }
+
+ CSI_RE.lastIndex = 0
+ let match: RegExpExecArray | null
+
+ while ((match = CSI_RE.exec(cleaned)) !== null) {
+ const start = match.index
+
+ if (start > cursor) {
+ pushText(cleaned.slice(cursor, start))
+ }
+
+ if (match[2] === 'm') {
+ const codes = match[1]
+ .split(';')
+ .map(part => (part === '' ? 0 : Number(part)))
+ .filter(value => Number.isFinite(value))
+
+ for (let i = 0; i < codes.length; i += 1) {
+ const code = codes[i]
+
+ if (code === 0) {
+ bold = false
+ fg = null
+ } else if (code === 1) {
+ bold = true
+ } else if (code === 22) {
+ bold = false
+ } else if (code === 39) {
+ fg = null
+ } else if (code in FG_BY_CODE) {
+ fg = FG_BY_CODE[code]
+ } else if (code === 38) {
+ // 256-color / truecolor — skip the trailing args we don't render.
+ if (codes[i + 1] === 5) {
+ i += 2
+ } else if (codes[i + 1] === 2) {
+ i += 4
+ }
+ }
+ // Background colors (40-47, 100-107) and effects we don't render are
+ // intentionally ignored — the segment keeps the prior bold/fg state.
+ }
+ }
+
+ cursor = CSI_RE.lastIndex
+ }
+
+ if (cursor < cleaned.length) {
+ pushText(cleaned.slice(cursor))
+ }
+
+ return segments
+}
+
+const TAILWIND_BY_COLOR: Record = {
+ // Tuned for legibility against the muted bg-(--ui-bg-tertiary) surface used
+ // in tool cards. We don't paint pure ANSI colors (#000, #fff) because they
+ // disappear into the surface.
+ 'black': 'text-zinc-700 dark:text-zinc-300',
+ 'red': 'text-red-700 dark:text-red-300',
+ 'green': 'text-emerald-700 dark:text-emerald-300',
+ 'yellow': 'text-amber-700 dark:text-amber-300',
+ 'blue': 'text-blue-700 dark:text-blue-300',
+ 'magenta': 'text-fuchsia-700 dark:text-fuchsia-300',
+ 'cyan': 'text-cyan-700 dark:text-cyan-300',
+ 'white': 'text-zinc-600 dark:text-zinc-200',
+ 'bright-black': 'text-zinc-500 dark:text-zinc-400',
+ 'bright-red': 'text-rose-600 dark:text-rose-300',
+ 'bright-green': 'text-emerald-600 dark:text-emerald-200',
+ 'bright-yellow': 'text-amber-600 dark:text-amber-200',
+ 'bright-blue': 'text-sky-600 dark:text-sky-300',
+ 'bright-magenta': 'text-pink-600 dark:text-pink-300',
+ 'bright-cyan': 'text-teal-600 dark:text-teal-200',
+ 'bright-white': 'text-zinc-500 dark:text-zinc-100'
+}
+
+export function ansiColorClass(color: AnsiColor): string {
+ return TAILWIND_BY_COLOR[color]
+}
+
+/** Returns true if the input contains at least one CSI sequence. Cheap check
+ * so callers can skip the parser for plain-ASCII output. */
+export function hasAnsiCodes(input: string): boolean {
+ // eslint-disable-next-line no-control-regex
+ return /\x1b\[/.test(input)
+}
diff --git a/apps/desktop/src/lib/tool-result-summary.ts b/apps/desktop/src/lib/tool-result-summary.ts
index 22af5644452..b51f1c35b18 100644
--- a/apps/desktop/src/lib/tool-result-summary.ts
+++ b/apps/desktop/src/lib/tool-result-summary.ts
@@ -20,7 +20,11 @@ const PRIORITY_KEYS = [
] as const
const ERROR_KEYS = ['error', 'errors', 'failure', 'exception'] as const
-const ERROR_MSG_KEYS = ['message', 'reason', 'detail', 'stderr'] as const
+// 'stderr' deliberately excluded: many CLIs emit informational lines on
+// stderr (npm progress, git's hint:, gcc's `In file included from`) that
+// aren't errors. Treating those as error signal flipped tool cards into
+// destructive styling for healthy commands.
+const ERROR_MSG_KEYS = ['message', 'reason', 'detail'] as const
const NON_ERROR_TEXT = new Set(['', '0', 'false', 'none', 'null', 'nil', 'ok', 'success', 'n/a', 'na'])
type Json = Record
diff --git a/apps/desktop/src/store/session.ts b/apps/desktop/src/store/session.ts
index 06bbb1ff063..187dca7c36b 100644
--- a/apps/desktop/src/store/session.ts
+++ b/apps/desktop/src/store/session.ts
@@ -97,6 +97,53 @@ export const setIntroSeed = (next: Updater) => updateAtom($introSeed, ne
export const setContextSuggestions = (next: Updater) => updateAtom($contextSuggestions, next)
export const setModelPickerOpen = (next: Updater) => updateAtom($modelPickerOpen, next)
+// Watchdog tracking — when does a "working" session count as stuck?
+// Long-running tool calls (LLM inference, long shell commands, web fetches)
+// can take a few minutes legitimately. We allow 8 minutes of complete
+// silence on the stream before clearing the working flag; in practice this
+// catches gateway hangs and dropped streams without false-positive-clearing
+// real long turns.
+const SESSION_WATCHDOG_TIMEOUT_MS = 8 * 60 * 1000
+const sessionWatchdogTimers = new Map>()
+
+function armSessionWatchdog(sessionId: string) {
+ const existing = sessionWatchdogTimers.get(sessionId)
+
+ if (existing) {
+ clearTimeout(existing)
+ }
+
+ const timer = setTimeout(() => {
+ sessionWatchdogTimers.delete(sessionId)
+ // Re-check the latest state at fire-time. If the user already navigated
+ // away or the session genuinely finished, the timer is a no-op.
+ if ($workingSessionIds.get().includes(sessionId)) {
+ setWorkingSessionIds(current => current.filter(id => id !== sessionId))
+ }
+ }, SESSION_WATCHDOG_TIMEOUT_MS)
+
+ sessionWatchdogTimers.set(sessionId, timer)
+}
+
+function clearSessionWatchdog(sessionId: string) {
+ const existing = sessionWatchdogTimers.get(sessionId)
+
+ if (existing) {
+ clearTimeout(existing)
+ sessionWatchdogTimers.delete(sessionId)
+ }
+}
+
+/** Call when a streaming event for a session lands. Refreshes the watchdog
+ * so the session keeps its "working" status as long as data keeps coming. */
+export function noteSessionActivity(sessionId: string | null | undefined) {
+ if (!sessionId || !$workingSessionIds.get().includes(sessionId)) {
+ return
+ }
+
+ armSessionWatchdog(sessionId)
+}
+
export function setSessionWorking(sessionId: string | null | undefined, working: boolean) {
if (!sessionId) {
return
@@ -111,4 +158,13 @@ export function setSessionWorking(sessionId: string | null | undefined, working:
return alreadyWorking ? current.filter(id => id !== sessionId) : current
})
+
+ // Bookend the watchdog: arm it whenever a session enters "working",
+ // disarm it whenever it leaves. A subsequent noteSessionActivity() from
+ // a streaming event will refresh the timer.
+ if (working) {
+ armSessionWatchdog(sessionId)
+ } else {
+ clearSessionWatchdog(sessionId)
+ }
}
diff --git a/apps/desktop/src/store/updates.ts b/apps/desktop/src/store/updates.ts
index e28f1e74faf..3a8fbc77968 100644
--- a/apps/desktop/src/store/updates.ts
+++ b/apps/desktop/src/store/updates.ts
@@ -145,6 +145,34 @@ export function openUpdatesWindow(): void {
void checkUpdates()
}
+/** Re-read the running app's version from the Electron main process and
+ * publish it on `$desktopVersion`. Called when the About panel mounts, the
+ * update flow finishes, and the window regains focus, so the About text
+ * stays in sync with the just-installed binary instead of frozen at the
+ * value captured at first-load. */
+export async function refreshDesktopVersion(): Promise {
+ if (typeof window === 'undefined') {
+ return null
+ }
+
+ // Best-effort UI sync: callers (checkUpdates, startUpdatePoller, window
+ // focus handler) all kick this off with `void refreshDesktopVersion()`,
+ // so any rejection from the IPC bridge (e.g. main process shutting down
+ // mid-reload, or the bridge not yet ready on first paint) would surface
+ // as an unhandled promise rejection in the renderer. Swallow it.
+ try {
+ const next = await window.hermesDesktop?.getVersion?.()
+
+ if (next) {
+ $desktopVersion.set(next)
+ }
+
+ return next ?? null
+ } catch {
+ return null
+ }
+}
+
export async function checkUpdates(): Promise {
const bridge = window.hermesDesktop?.updates
@@ -158,6 +186,10 @@ export async function checkUpdates(): Promise {
const status = await bridge.check()
$updateStatus.set(status)
maybeNotifyUpdateAvailable(status)
+ // The update check pulls the latest hermes_cli + bundled package metadata
+ // into place. Re-read the running version so About reflects the now-fresh
+ // checkout rather than the one captured at process start.
+ void refreshDesktopVersion()
return status
} catch (error) {
@@ -249,7 +281,7 @@ export function startUpdatePoller(): void {
pollerStarted = true
void checkUpdates()
- void window.hermesDesktop?.getVersion?.().then(info => $desktopVersion.set(info))
+ void refreshDesktopVersion()
bridge.onProgress(ingestProgress)
window.addEventListener('focus', onFocus)
@@ -275,4 +307,8 @@ function onFocus() {
lastFocusAt = now
void checkUpdates()
+ // Cheap and safe to re-read on every (throttled) focus: the user may have
+ // updated Hermes from another window/CLI between focuses, and About should
+ // catch up without forcing a restart.
+ void refreshDesktopVersion()
}
diff --git a/apps/desktop/src/styles.css b/apps/desktop/src/styles.css
index 1a2d333bfc8..581036cdeb2 100644
--- a/apps/desktop/src/styles.css
+++ b/apps/desktop/src/styles.css
@@ -641,6 +641,41 @@ canvas {
.scrollbar-dt *::-webkit-scrollbar-button {
display: none;
}
+
+ /* Variant for portaled overlays (Radix DropdownMenu, Popover, etc.) that
+ render under document.body, outside the `.scrollbar-dt` scope on
+ #root. Same visual treatment, applied directly to the overlay
+ container so its (and only its) internal scrollbar is themed. */
+ .dt-portal-scrollbar {
+ scrollbar-width: thin;
+ scrollbar-color: color-mix(in srgb, var(--dt-midground) 28%, transparent) transparent;
+ }
+
+ .dt-portal-scrollbar::-webkit-scrollbar {
+ width: 0.375rem;
+ height: 0.375rem;
+ }
+
+ .dt-portal-scrollbar::-webkit-scrollbar-track,
+ .dt-portal-scrollbar::-webkit-scrollbar-corner {
+ background: transparent;
+ }
+
+ .dt-portal-scrollbar::-webkit-scrollbar-thumb {
+ background: color-mix(in srgb, var(--dt-midground) 28%, transparent);
+ border-radius: 9999rem;
+ border: 0.0625rem solid transparent;
+ background-clip: padding-box;
+ }
+
+ .dt-portal-scrollbar::-webkit-scrollbar-thumb:hover {
+ background: color-mix(in srgb, var(--dt-midground) 50%, transparent);
+ background-clip: padding-box;
+ }
+
+ .dt-portal-scrollbar::-webkit-scrollbar-button {
+ display: none;
+ }
}
/* Bottom clearance lives on [data-slot='aui_composer-clearance'] —
diff --git a/package-lock.json b/package-lock.json
index 093d6353a23..bed6dddc061 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -56,7 +56,7 @@
},
"apps/desktop": {
"name": "hermes",
- "version": "0.0.2",
+ "version": "0.15.1",
"dependencies": {
"@assistant-ui/react": "^0.12.28",
"@assistant-ui/react-streamdown": "^0.1.11",
@@ -66,6 +66,7 @@
"@dnd-kit/sortable": "^10.0.0",
"@dnd-kit/utilities": "^3.2.2",
"@hermes/shared": "file:../shared",
+ "@icons-pack/react-simple-icons": "^13.13.0",
"@nanostores/react": "^1.1.0",
"@nous-research/ui": "^0.13.0",
"@radix-ui/react-slot": "^1.2.4",
@@ -256,6 +257,7 @@
"integrity": "sha512-rZuUu9j6J5uotLDs+cAA4O5H4K1SfPliUlQwqa6YEwSrWDZzP4rhm00oJR5snMewjxF5V/K3D4kctsUTsIU9Mw==",
"dev": true,
"license": "MIT",
+ "peer": true,
"dependencies": {
"lightningcss": "^1.32.0",
"picomatch": "^4.0.4",
@@ -450,6 +452,7 @@
"resolved": "https://registry.npmjs.org/@assistant-ui/react/-/react-0.12.28.tgz",
"integrity": "sha512-czjpexLK1lKnNDNM1YMJi8SufeKUWBICqiVUtiHMV+86PYGCwJykOZKkchI8MVbSQ62xZ8A1LfPO5W2IDjed3A==",
"license": "MIT",
+ "peer": true,
"dependencies": {
"@assistant-ui/core": "^0.1.17",
"@assistant-ui/store": "^0.2.9",
@@ -526,6 +529,7 @@
"resolved": "https://registry.npmjs.org/@assistant-ui/store/-/store-0.2.9.tgz",
"integrity": "sha512-EDd6yCfirb2OsAKoTo7HeMtqPG+1cqVlNXOzUsho35ZF3O1XQ2CyEY4iUbdhj3HfmWeZo7rmfhvbaYQVEqAfeA==",
"license": "MIT",
+ "peer": true,
"dependencies": {
"use-effect-event": "^2.0.3"
},
@@ -545,6 +549,7 @@
"resolved": "https://registry.npmjs.org/@assistant-ui/tap/-/tap-0.5.10.tgz",
"integrity": "sha512-sBHTf+q1geRyu5l4gJJp2hk6ZxwhHZHj39ixjC9ARADuIYedYv1B8bCNS82eTC/COpD1xe86mzvT/+HwIsO9WA==",
"license": "MIT",
+ "peer": true,
"peerDependencies": {
"@types/react": "*",
"react": "^18 || ^19"
@@ -608,6 +613,7 @@
"integrity": "sha512-CGOfOJqWjg2qW/Mb6zNsDm+u5vFQ8DxXfbM09z69p5Z6+mE1ikP2jUXw+j42Pf1XTYED2Rni5f95npYeuwMDQA==",
"dev": true,
"license": "MIT",
+ "peer": true,
"dependencies": {
"@babel/code-frame": "^7.29.0",
"@babel/generator": "^7.29.0",
@@ -1210,6 +1216,7 @@
}
],
"license": "MIT",
+ "peer": true,
"engines": {
"node": ">=20.19.0"
},
@@ -1258,6 +1265,7 @@
}
],
"license": "MIT",
+ "peer": true,
"engines": {
"node": ">=20.19.0"
}
@@ -1295,6 +1303,7 @@
"version": "6.3.1",
"resolved": "https://registry.npmjs.org/@dnd-kit/core/-/core-6.3.1.tgz",
"integrity": "sha512-xkGBRQQab4RLwgXxoqETICr6S5JlogafbhNsidmrkVv2YRs5MLwpjoF2qpiGjQt8S9AoxtIV603s0GIUpY5eYQ==",
+ "peer": true,
"dependencies": {
"@dnd-kit/accessibility": "^3.1.1",
"@dnd-kit/utilities": "^3.2.2",
@@ -2703,6 +2712,19 @@
"mlly": "^1.8.2"
}
},
+ "node_modules/@icons-pack/react-simple-icons": {
+ "version": "13.13.0",
+ "resolved": "https://registry.npmjs.org/@icons-pack/react-simple-icons/-/react-simple-icons-13.13.0.tgz",
+ "integrity": "sha512-B5HhQMIpcSH4z8IZ8HFhD59CboHceKYMpPC9kAwGyKntvPdyJJv26DLu4Z1wAjcCLyrJhf11tMhiQGom9Rxb9g==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=24",
+ "pnpm": ">=10"
+ },
+ "peerDependencies": {
+ "react": "^16.13 || ^17 || ^18 || ^19"
+ }
+ },
"node_modules/@isaacs/fs-minipass": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/@isaacs/fs-minipass/-/fs-minipass-4.0.1.tgz",
@@ -2932,29 +2954,6 @@
}
}
},
- "node_modules/@observablehq/plot": {
- "version": "0.6.17",
- "resolved": "https://registry.npmjs.org/@observablehq/plot/-/plot-0.6.17.tgz",
- "integrity": "sha512-/qaXP/7mc4MUS0s4cPPFASDRjtsWp85/TbfsciqDgU1HwYixbSbbytNuInD8AcTYC3xaxACgVX06agdfQy9W+g==",
- "license": "ISC",
- "dependencies": {
- "d3": "^7.9.0",
- "interval-tree-1d": "^1.0.0",
- "isoformat": "^0.2.0"
- },
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@opentelemetry/api": {
- "version": "1.9.1",
- "resolved": "https://registry.npmjs.org/@opentelemetry/api/-/api-1.9.1.tgz",
- "integrity": "sha512-gLyJlPHPZYdAk1JENA9LeHejZe1Ti77/pTeFm/nMXmQH/HFZlcS/O2XJB+L8fkbrNSqhdtlvjBVjxwUYanNH5Q==",
- "license": "Apache-2.0",
- "engines": {
- "node": ">=8.0.0"
- }
- },
"node_modules/@oxc-project/types": {
"version": "0.127.0",
"resolved": "https://registry.npmjs.org/@oxc-project/types/-/types-0.127.0.tgz",
@@ -6527,78 +6526,6 @@
"resolved": "https://registry.npmjs.org/@react-dnd/shallowequal/-/shallowequal-2.0.0.tgz",
"integrity": "sha512-Pc/AFTdwZwEKJxFJvlxrSmGe/di+aAOBn60sremrpLo6VI/6cmiUYNNwlI5KNYttg7uypzA3ILPMPgxB2GYZEg=="
},
- "node_modules/@react-three/fiber": {
- "version": "9.6.1",
- "resolved": "https://registry.npmjs.org/@react-three/fiber/-/fiber-9.6.1.tgz",
- "integrity": "sha512-zF0rsKcVYpcJwbFEnv2HkHX9cvOEgsfQo/X8lwmR2dn13S4qEQJXir9fxf5js2LQFoXqxOY7MDkOkYx2uZ4gSg==",
- "license": "MIT",
- "dependencies": {
- "@babel/runtime": "^7.17.8",
- "@types/webxr": "*",
- "base64-js": "^1.5.1",
- "buffer": "^6.0.3",
- "its-fine": "^2.0.0",
- "react-use-measure": "^2.1.7",
- "scheduler": "^0.27.0",
- "suspend-react": "^0.1.3",
- "use-sync-external-store": "^1.4.0",
- "zustand": "^5.0.3"
- },
- "peerDependencies": {
- "expo": ">=43.0",
- "expo-asset": ">=8.4",
- "expo-file-system": ">=11.0",
- "expo-gl": ">=11.0",
- "react": ">=19 <19.3",
- "react-dom": ">=19 <19.3",
- "react-native": ">=0.78",
- "three": ">=0.156"
- },
- "peerDependenciesMeta": {
- "expo": {
- "optional": true
- },
- "expo-asset": {
- "optional": true
- },
- "expo-file-system": {
- "optional": true
- },
- "expo-gl": {
- "optional": true
- },
- "react-dom": {
- "optional": true
- },
- "react-native": {
- "optional": true
- }
- }
- },
- "node_modules/@react-three/fiber/node_modules/buffer": {
- "version": "6.0.3",
- "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz",
- "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==",
- "funding": [
- {
- "type": "github",
- "url": "https://github.com/sponsors/feross"
- },
- {
- "type": "patreon",
- "url": "https://www.patreon.com/feross"
- },
- {
- "type": "consulting",
- "url": "https://feross.org/support"
- }
- ],
- "license": "MIT",
- "dependencies": {
- "base64-js": "^1.3.1",
- "ieee754": "^1.2.1"
- }
- },
"node_modules/@rolldown/binding-android-arm64": {
"version": "1.0.0-rc.17",
"resolved": "https://registry.npmjs.org/@rolldown/binding-android-arm64/-/binding-android-arm64-1.0.0-rc.17.tgz",
@@ -7292,6 +7219,7 @@
"version": "4.6.0",
"resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.6.0.tgz",
"integrity": "sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw==",
+ "dev": true,
"license": "MIT",
"engines": {
"node": ">=10"
@@ -7320,6 +7248,7 @@
"resolved": "https://registry.npmjs.org/@streamdown/code/-/code-1.1.1.tgz",
"integrity": "sha512-i7HTNuDgZWb+VdrNVOam9gQhIc5MSSDXKWXgbUrn/4vSRaSMM+Rtl10MQj4wLWPNpF7p80waJsAqFP8HZfb0Jg==",
"license": "Apache-2.0",
+ "peer": true,
"dependencies": {
"shiki": "^3.19.0"
},
@@ -7409,6 +7338,7 @@
"resolved": "https://registry.npmjs.org/@streamdown/math/-/math-1.0.2.tgz",
"integrity": "sha512-r8Ur9/lBuFnzZAFdEWrLUF2s/gRwRRRwruqltdZibyjbCBnuW7SJbFm26nXqvpJPW/gzpBUMrBVBzd88z05D5g==",
"license": "Apache-2.0",
+ "peer": true,
"dependencies": {
"katex": "^0.16.27",
"rehype-katex": "^7.0.1",
@@ -7933,9 +7863,6 @@
"arm64"
],
"dev": true,
- "libc": [
- "glibc"
- ],
"license": "Apache-2.0 OR MIT",
"optional": true,
"os": [
@@ -7953,9 +7880,6 @@
"arm64"
],
"dev": true,
- "libc": [
- "musl"
- ],
"license": "Apache-2.0 OR MIT",
"optional": true,
"os": [
@@ -7973,9 +7897,6 @@
"riscv64"
],
"dev": true,
- "libc": [
- "glibc"
- ],
"license": "Apache-2.0 OR MIT",
"optional": true,
"os": [
@@ -7993,9 +7914,6 @@
"x64"
],
"dev": true,
- "libc": [
- "glibc"
- ],
"license": "Apache-2.0 OR MIT",
"optional": true,
"os": [
@@ -8013,9 +7931,6 @@
"x64"
],
"dev": true,
- "libc": [
- "musl"
- ],
"license": "Apache-2.0 OR MIT",
"optional": true,
"os": [
@@ -8177,8 +8092,7 @@
"resolved": "https://registry.npmjs.org/@types/aria-query/-/aria-query-5.0.4.tgz",
"integrity": "sha512-rfT93uj5s0PRL7EzccGMs3brplhcrghnDoV26NqKhCAS1hVo+WdNsPvE/yb6ilfr5hi2MEk6d5EWJTKdxg8jVw==",
"dev": true,
- "license": "MIT",
- "peer": true
+ "license": "MIT"
},
"node_modules/@types/babel__core": {
"version": "7.20.5",
@@ -8609,6 +8523,7 @@
"integrity": "sha512-A1sre26ke7HDIuY/M23nd9gfB+nrmhtYyMINbjI1zHJxYteKR6qSMX56FsmjMcDb3SMcjJg5BiRRgOCC/yBD0g==",
"devOptional": true,
"license": "MIT",
+ "peer": true,
"dependencies": {
"undici-types": "~7.16.0"
}
@@ -8629,6 +8544,7 @@
"version": "19.2.14",
"resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.14.tgz",
"integrity": "sha512-ilcTH/UniCkMdtexkoCN0bI7pMcJDvmQFPvuPvmEaYA/NSfFTAgdUSLAoVjaRJm7+6PvcM+q1zYOwS4wTYMF9w==",
+ "devOptional": true,
"license": "MIT",
"dependencies": {
"csstype": "^3.2.2"
@@ -8649,6 +8565,7 @@
"resolved": "https://registry.npmjs.org/@types/react-reconciler/-/react-reconciler-0.28.9.tgz",
"integrity": "sha512-HHM3nxyUZ3zAylX8ZEyrDNd2XZOnQ0D5XfunJF5FLQnZbHHYq4UWvW1QfelQNXv1ICNkwYhfxjwfnqivYB6bFg==",
"license": "MIT",
+ "optional": true,
"peerDependencies": {
"@types/react": "*"
}
@@ -8688,7 +8605,8 @@
"version": "0.5.24",
"resolved": "https://registry.npmjs.org/@types/webxr/-/webxr-0.5.24.tgz",
"integrity": "sha512-h8fgEd/DpoS9CBrjEQXR+dIDraopAEfu4wYVNY2tEPwk60stPWhvZMf4Foo5FakuQ7HFZoa8WceaWFervK2Ovg==",
- "license": "MIT"
+ "license": "MIT",
+ "optional": true
},
"node_modules/@types/yauzl": {
"version": "2.10.3",
@@ -8707,6 +8625,7 @@
"integrity": "sha512-BOziFIfE+6osHO9FoJG4zjoHUcvI7fTNBSpdAwrNH0/TLvzjsk2oo8XSSOT2HhqUyhZPfHv4UOffoJ9oEEQ7Ag==",
"dev": true,
"license": "MIT",
+ "peer": true,
"dependencies": {
"@eslint-community/regexpp": "^4.12.2",
"@typescript-eslint/scope-manager": "8.59.1",
@@ -9269,24 +9188,12 @@
"node": "^20.17.0 || >=22.9.0"
}
},
- "node_modules/accepts": {
- "version": "1.3.8",
- "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz",
- "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==",
- "license": "MIT",
- "dependencies": {
- "mime-types": "~2.1.34",
- "negotiator": "0.6.3"
- },
- "engines": {
- "node": ">= 0.6"
- }
- },
"node_modules/acorn": {
"version": "8.16.0",
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.16.0.tgz",
"integrity": "sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==",
"license": "MIT",
+ "peer": true,
"bin": {
"acorn": "bin/acorn"
},
@@ -9304,15 +9211,6 @@
"acorn": "^6.0.0 || ^7.0.0 || ^8.0.0"
}
},
- "node_modules/adm-zip": {
- "version": "0.5.17",
- "resolved": "https://registry.npmjs.org/adm-zip/-/adm-zip-0.5.17.tgz",
- "integrity": "sha512-+Ut8d9LLqwEvHHJl1+PIHqoyDxFgVN847JTVM3Izi3xHDWPE4UtzzXysMZQs64DMcrJfBeS/uoEP4AD3HQHnQQ==",
- "license": "MIT",
- "engines": {
- "node": ">=12.0"
- }
- },
"node_modules/agent-base": {
"version": "7.1.4",
"resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.4.tgz",
@@ -9339,6 +9237,7 @@
"integrity": "sha512-fgFx7Hfoq60ytK2c7DhnF8jIvzYgOMxfugjLOSMHjLIPgenqa7S7oaagATUq99mV6IYvN2tRmC0wnTYX6iPbMw==",
"dev": true,
"license": "MIT",
+ "peer": true,
"dependencies": {
"fast-deep-equal": "^3.1.1",
"fast-json-stable-stringify": "^2.0.0",
@@ -9604,20 +9503,10 @@
"integrity": "sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==",
"dev": true,
"license": "Apache-2.0",
- "peer": true,
"dependencies": {
"dequal": "^2.0.3"
}
},
- "node_modules/arr-union": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz",
- "integrity": "sha512-sKpyeERZ02v1FeCZT8lrfJq5u6goHCtpTAzPwJYe7c8SPFOboNjNg1vz2L4VTn9T4PQxEx13TbXLmYUcS6Ug7Q==",
- "license": "MIT",
- "engines": {
- "node": ">=0.10.0"
- }
- },
"node_modules/array-buffer-byte-length": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.2.tgz",
@@ -9635,12 +9524,6 @@
"url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/array-flatten": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz",
- "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==",
- "license": "MIT"
- },
"node_modules/array-includes": {
"version": "3.1.9",
"resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.9.tgz",
@@ -9797,6 +9680,7 @@
"resolved": "https://registry.npmjs.org/assistant-cloud/-/assistant-cloud-0.1.27.tgz",
"integrity": "sha512-BGfVnx7YFN5xtB/kbrgGxRI0TfSWq4yxB3MwYn6RDPlv4JvdtPupvDC1Y6An0EhAe42Z0AYtSmDSsR6p6eeBng==",
"license": "MIT",
+ "peer": true,
"dependencies": {
"assistant-stream": "^0.3.12"
}
@@ -9918,6 +9802,7 @@
"version": "4.0.4",
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz",
"integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==",
+ "dev": true,
"license": "MIT",
"engines": {
"node": "18 || 20 || >=22"
@@ -9927,6 +9812,7 @@
"version": "1.5.1",
"resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz",
"integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==",
+ "devOptional": true,
"funding": [
{
"type": "github",
@@ -9947,6 +9833,7 @@
"version": "2.10.18",
"resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.10.18.tgz",
"integrity": "sha512-VSnGQAOLtP5mib/DPyg2/t+Tlv65NTBz83BJBJvmLVHHuKJVaDOBvJJykiT5TR++em5nfAySPccDZDa4oSrn8A==",
+ "dev": true,
"license": "Apache-2.0",
"bin": {
"baseline-browser-mapping": "dist/cli.cjs"
@@ -9955,20 +9842,6 @@
"node": ">=6.0.0"
}
},
- "node_modules/better-sqlite3": {
- "version": "12.9.0",
- "resolved": "https://registry.npmjs.org/better-sqlite3/-/better-sqlite3-12.9.0.tgz",
- "integrity": "sha512-wqUv4Gm3toFpHDQmaKD4QhZm3g1DjUBI0yzS4UBl6lElUmXFYdTQmmEDpAFa5o8FiFiymURypEnfVHzILKaxqQ==",
- "hasInstallScript": true,
- "license": "MIT",
- "dependencies": {
- "bindings": "^1.5.0",
- "prebuild-install": "^7.1.1"
- },
- "engines": {
- "node": "20.x || 22.x || 23.x || 24.x || 25.x"
- }
- },
"node_modules/bidi-js": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/bidi-js/-/bidi-js-1.0.3.tgz",
@@ -9983,57 +9856,8 @@
"version": "2.0.5",
"resolved": "https://registry.npmjs.org/binary-search-bounds/-/binary-search-bounds-2.0.5.tgz",
"integrity": "sha512-H0ea4Fd3lS1+sTEB2TgcLoK21lLhwEJzlQv3IN47pJS976Gx4zoWe0ak3q+uYh60ppQxg9F16Ri4tS1sfD4+jA==",
- "license": "MIT"
- },
- "node_modules/bindings": {
- "version": "1.5.0",
- "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz",
- "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==",
"license": "MIT",
- "dependencies": {
- "file-uri-to-path": "1.0.0"
- }
- },
- "node_modules/bintrees": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/bintrees/-/bintrees-1.0.2.tgz",
- "integrity": "sha512-VOMgTMwjAaUG580SXn3LacVgjurrbMme7ZZNYGSSV7mmtY6QQRh0Eg3pwIcntQ77DErK1L0NxkbetjcoXzVwKw==",
- "license": "MIT"
- },
- "node_modules/bl": {
- "version": "4.1.0",
- "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz",
- "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==",
- "license": "MIT",
- "dependencies": {
- "buffer": "^5.5.0",
- "inherits": "^2.0.4",
- "readable-stream": "^3.4.0"
- }
- },
- "node_modules/body-parser": {
- "version": "1.20.4",
- "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.4.tgz",
- "integrity": "sha512-ZTgYYLMOXY9qKU/57FAo8F+HA2dGX7bqGc71txDRC1rS4frdFI5R7NhluHxH6M0YItAP0sHB4uqAOcYKxO6uGA==",
- "license": "MIT",
- "dependencies": {
- "bytes": "~3.1.2",
- "content-type": "~1.0.5",
- "debug": "2.6.9",
- "depd": "2.0.0",
- "destroy": "~1.2.0",
- "http-errors": "~2.0.1",
- "iconv-lite": "~0.4.24",
- "on-finished": "~2.4.1",
- "qs": "~6.14.0",
- "raw-body": "~2.5.3",
- "type-is": "~1.6.18",
- "unpipe": "~1.0.0"
- },
- "engines": {
- "node": ">= 0.8",
- "npm": "1.2.8000 || >= 1.4.16"
- }
+ "optional": true
},
"node_modules/boolean": {
"version": "3.2.0",
@@ -10048,6 +9872,7 @@
"version": "5.0.5",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.5.tgz",
"integrity": "sha512-VZznLgtwhn+Mact9tfiwx64fA9erHH/MCXEUfB/0bX/6Fz6ny5EGTXYltMocqg4xFAQZtnO3DHWWXi8RiuN7cQ==",
+ "dev": true,
"license": "MIT",
"dependencies": {
"balanced-match": "^4.0.2"
@@ -10060,6 +9885,7 @@
"version": "4.28.2",
"resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.2.tgz",
"integrity": "sha512-48xSriZYYg+8qXna9kwqjIVzuQxi+KYWp2+5nCYnYKPTr0LvD89Jqk2Or5ogxz0NUMfIjhh2lIUX/LyX9B4oIg==",
+ "dev": true,
"funding": [
{
"type": "opencollective",
@@ -10075,6 +9901,7 @@
}
],
"license": "MIT",
+ "peer": true,
"dependencies": {
"baseline-browser-mapping": "^2.10.12",
"caniuse-lite": "^1.0.30001782",
@@ -10093,6 +9920,7 @@
"version": "5.7.1",
"resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz",
"integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==",
+ "dev": true,
"funding": [
{
"type": "github",
@@ -10108,6 +9936,7 @@
}
],
"license": "MIT",
+ "optional": true,
"dependencies": {
"base64-js": "^1.3.1",
"ieee754": "^1.1.13"
@@ -10219,15 +10048,6 @@
"dev": true,
"license": "MIT"
},
- "node_modules/bytes": {
- "version": "3.1.2",
- "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz",
- "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==",
- "license": "MIT",
- "engines": {
- "node": ">= 0.8"
- }
- },
"node_modules/cacheable-lookup": {
"version": "5.0.4",
"resolved": "https://registry.npmjs.org/cacheable-lookup/-/cacheable-lookup-5.0.4.tgz",
@@ -10280,6 +10100,7 @@
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz",
"integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==",
+ "dev": true,
"license": "MIT",
"dependencies": {
"es-errors": "^1.3.0",
@@ -10293,6 +10114,7 @@
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz",
"integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==",
+ "dev": true,
"license": "MIT",
"dependencies": {
"call-bind-apply-helpers": "^1.0.2",
@@ -10309,6 +10131,7 @@
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz",
"integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==",
+ "dev": true,
"license": "MIT",
"engines": {
"node": ">=6"
@@ -10318,6 +10141,7 @@
"version": "1.0.30001787",
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001787.tgz",
"integrity": "sha512-mNcrMN9KeI68u7muanUpEejSLghOKlVhRqS/Za2IeyGllJ9I9otGpR9g3nsw7n4W378TE/LyIteA0+/FOZm4Kg==",
+ "dev": true,
"funding": [
{
"type": "opencollective",
@@ -10429,6 +10253,7 @@
"resolved": "https://registry.npmjs.org/chevrotain/-/chevrotain-12.0.0.tgz",
"integrity": "sha512-csJvb+6kEiQaqo1woTdSAuOWdN0WTLIydkKrBnS+V5gZz0oqBrp4kQ35519QgK6TpBThiG3V1vNSHlIkv4AglQ==",
"license": "Apache-2.0",
+ "peer": true,
"dependencies": {
"@chevrotain/cst-dts-gen": "12.0.0",
"@chevrotain/gast": "12.0.0",
@@ -10452,12 +10277,6 @@
"chevrotain": "^12.0.0"
}
},
- "node_modules/chownr": {
- "version": "1.1.4",
- "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz",
- "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==",
- "license": "ISC"
- },
"node_modules/chromium-pickle-js": {
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/chromium-pickle-js/-/chromium-pickle-js-0.2.0.tgz",
@@ -10526,22 +10345,6 @@
"node": ">=12"
}
},
- "node_modules/clone-deep": {
- "version": "0.2.4",
- "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-0.2.4.tgz",
- "integrity": "sha512-we+NuQo2DHhSl+DP6jlUiAhyAjBQrYnpOk15rN6c6JSPScjiCLh8IbSU+VTcph6YS3o7mASE8a0+gbZ7ChLpgg==",
- "license": "MIT",
- "dependencies": {
- "for-own": "^0.1.3",
- "is-plain-object": "^2.0.1",
- "kind-of": "^3.0.2",
- "lazy-cache": "^1.0.3",
- "shallow-clone": "^0.1.2"
- },
- "engines": {
- "node": ">=0.10.0"
- }
- },
"node_modules/clone-response": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.3.tgz",
@@ -10639,15 +10442,6 @@
"url": "https://github.com/sponsors/wooorm"
}
},
- "node_modules/commander": {
- "version": "14.0.3",
- "resolved": "https://registry.npmjs.org/commander/-/commander-14.0.3.tgz",
- "integrity": "sha512-H+y0Jo/T1RZ9qPP4Eh1pkcQcLRglraJaSLoyOtHxu6AapkjWVCy2Sit1QQ4x3Dng8qDlSsZEet7g5Pq06MvTgw==",
- "license": "MIT",
- "engines": {
- "node": ">=20"
- }
- },
"node_modules/compare-version": {
"version": "0.1.2",
"resolved": "https://registry.npmjs.org/compare-version/-/compare-version-0.1.2.tgz",
@@ -10662,6 +10456,7 @@
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
"integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==",
+ "dev": true,
"license": "MIT"
},
"node_modules/concurrently": {
@@ -10695,27 +10490,6 @@
"integrity": "sha512-RMtmw0iFkeR4YV+fUOSucriAQNb9g8zFR52MWCtl+cCZOFRNL6zeB395vPzFhEjjn4fMxXudmELnl/KF/WrK6w==",
"license": "MIT"
},
- "node_modules/content-disposition": {
- "version": "0.5.4",
- "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz",
- "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==",
- "license": "MIT",
- "dependencies": {
- "safe-buffer": "5.2.1"
- },
- "engines": {
- "node": ">= 0.6"
- }
- },
- "node_modules/content-type": {
- "version": "1.0.5",
- "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz",
- "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==",
- "license": "MIT",
- "engines": {
- "node": ">= 0.6"
- }
- },
"node_modules/convert-source-map": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz",
@@ -10723,21 +10497,6 @@
"dev": true,
"license": "MIT"
},
- "node_modules/cookie": {
- "version": "0.7.2",
- "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz",
- "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==",
- "license": "MIT",
- "engines": {
- "node": ">= 0.6"
- }
- },
- "node_modules/cookie-signature": {
- "version": "1.0.7",
- "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.7.tgz",
- "integrity": "sha512-NXdYc3dLr47pBkpUCHtKSwIOQXLVn8dZEuywboCOJY/osA0wFSLlSawr3KN8qXJEyX66FcONTH8EIlVuK0yyFA==",
- "license": "MIT"
- },
"node_modules/core-util-is": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
@@ -10876,6 +10635,7 @@
"version": "3.2.3",
"resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz",
"integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==",
+ "devOptional": true,
"license": "MIT"
},
"node_modules/cytoscape": {
@@ -10883,6 +10643,7 @@
"resolved": "https://registry.npmjs.org/cytoscape/-/cytoscape-3.33.3.tgz",
"integrity": "sha512-Gej7U+OKR+LZ8kvX7rb2HhCYJ0IhvEFsnkud4SB1PR+BUY/TsSO0dmOW59WEVLu51b1Rm+gQRKoz4bLYxGSZ2g==",
"license": "MIT",
+ "peer": true,
"engines": {
"node": ">=0.10"
}
@@ -11304,6 +11065,7 @@
"resolved": "https://registry.npmjs.org/d3-selection/-/d3-selection-3.0.0.tgz",
"integrity": "sha512-fmTRWbNMmsmWq6xJV8D19U/gw/bwrHfNXxrIN+HfZgnzqTHp9jOmKMhsTUjXOJnZOdZY9Q28y4yebKzqDKlxlQ==",
"license": "ISC",
+ "peer": true,
"engines": {
"node": ">=12"
}
@@ -11472,15 +11234,6 @@
"integrity": "sha512-YbwwqR/uYpeoP4pu043q+LTDLFBLApUP6VxRihdfNTqu4ubqMlGDLd6ErXhEgsyvY0K6nCs7nggYumAN+9uEuQ==",
"license": "MIT"
},
- "node_modules/debug": {
- "version": "2.6.9",
- "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
- "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
- "license": "MIT",
- "dependencies": {
- "ms": "2.0.0"
- }
- },
"node_modules/decimal.js": {
"version": "10.6.0",
"resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.6.0.tgz",
@@ -11505,6 +11258,7 @@
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz",
"integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==",
+ "dev": true,
"license": "MIT",
"dependencies": {
"mimic-response": "^3.1.0"
@@ -11516,15 +11270,6 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
- "node_modules/deep-extend": {
- "version": "0.6.0",
- "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz",
- "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==",
- "license": "MIT",
- "engines": {
- "node": ">=4.0.0"
- }
- },
"node_modules/deep-is": {
"version": "0.1.4",
"resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz",
@@ -11606,15 +11351,6 @@
"node": ">=0.4.0"
}
},
- "node_modules/depd": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz",
- "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==",
- "license": "MIT",
- "engines": {
- "node": ">= 0.8"
- }
- },
"node_modules/dequal": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz",
@@ -11624,36 +11360,6 @@
"node": ">=6"
}
},
- "node_modules/destroy": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz",
- "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==",
- "license": "MIT",
- "engines": {
- "node": ">= 0.8",
- "npm": "1.2.8000 || >= 1.4.16"
- }
- },
- "node_modules/detect-europe-js": {
- "version": "0.1.2",
- "resolved": "https://registry.npmjs.org/detect-europe-js/-/detect-europe-js-0.1.2.tgz",
- "integrity": "sha512-lgdERlL3u0aUdHocoouzT10d9I89VVhk0qNRmll7mXdGfJT1/wqZ2ZLA4oJAjeACPY5fT1wsbq2AT+GkuInsow==",
- "funding": [
- {
- "type": "github",
- "url": "https://github.com/sponsors/faisalman"
- },
- {
- "type": "opencollective",
- "url": "https://opencollective.com/ua-parser-js"
- },
- {
- "type": "paypal",
- "url": "https://paypal.me/faisalman"
- }
- ],
- "license": "MIT"
- },
"node_modules/detect-libc": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz",
@@ -11738,6 +11444,7 @@
"integrity": "sha512-glMJgnTreo8CFINujtAhCgN96QAqApDMZ8Vl1r8f0QT8QprvC1UCltV4CcWj20YoIyLZx6IUskaJZ0NV8fokcg==",
"dev": true,
"license": "MIT",
+ "peer": true,
"dependencies": {
"app-builder-lib": "26.8.1",
"builder-util": "26.8.1",
@@ -11825,8 +11532,7 @@
"resolved": "https://registry.npmjs.org/dom-accessibility-api/-/dom-accessibility-api-0.5.16.tgz",
"integrity": "sha512-X7BJ2yElsnOJ30pZF4uIIDfBEVgF4XEBxL9Bxhy6dnrm5hkzqmsWHGTiHqRiITNhMyFLyAiWndIJP7Z1NTteDg==",
"dev": true,
- "license": "MIT",
- "peer": true
+ "license": "MIT"
},
"node_modules/dom-serializer": {
"version": "2.0.0",
@@ -11904,21 +11610,6 @@
"url": "https://github.com/fb55/domutils?sponsor=1"
}
},
- "node_modules/dot-prop": {
- "version": "6.0.1",
- "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-6.0.1.tgz",
- "integrity": "sha512-tE7ztYzXHIeyvc7N+hR3oi7FIbf/NIjVP9hmAt3yMXzrQ072/fpjGLx2GxNxGxUl5V73MEqYzioOMoVhGMJ5cA==",
- "license": "MIT",
- "dependencies": {
- "is-obj": "^2.0.0"
- },
- "engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
"node_modules/dotenv": {
"version": "16.6.1",
"resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.6.1.tgz",
@@ -11952,6 +11643,7 @@
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz",
"integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==",
+ "dev": true,
"license": "MIT",
"dependencies": {
"call-bind-apply-helpers": "^1.0.1",
@@ -11962,12 +11654,6 @@
"node": ">= 0.4"
}
},
- "node_modules/ee-first": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
- "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==",
- "license": "MIT"
- },
"node_modules/ejs": {
"version": "3.1.10",
"resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.10.tgz",
@@ -12076,6 +11762,7 @@
"version": "1.5.335",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.335.tgz",
"integrity": "sha512-q9n5T4BR4Xwa2cwbrwcsDJtHD/enpQ5S1xF1IAtdqf5AAgqDFmR/aakqH3ChFdqd/QXJhS3rnnXFtexU7rax6Q==",
+ "dev": true,
"license": "ISC"
},
"node_modules/electron-winstaller": {
@@ -12085,7 +11772,6 @@
"dev": true,
"hasInstallScript": true,
"license": "MIT",
- "peer": true,
"dependencies": {
"@electron/asar": "^3.2.1",
"debug": "^4.1.1",
@@ -12106,7 +11792,6 @@
"integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==",
"dev": true,
"license": "MIT",
- "peer": true,
"dependencies": {
"ms": "^2.1.3"
},
@@ -12125,7 +11810,6 @@
"integrity": "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==",
"dev": true,
"license": "MIT",
- "peer": true,
"dependencies": {
"graceful-fs": "^4.1.2",
"jsonfile": "^4.0.0",
@@ -12141,7 +11825,6 @@
"integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==",
"dev": true,
"license": "MIT",
- "peer": true,
"optionalDependencies": {
"graceful-fs": "^4.1.6"
}
@@ -12151,8 +11834,7 @@
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
"dev": true,
- "license": "MIT",
- "peer": true
+ "license": "MIT"
},
"node_modules/electron-winstaller/node_modules/universalify": {
"version": "0.1.2",
@@ -12160,7 +11842,6 @@
"integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==",
"dev": true,
"license": "MIT",
- "peer": true,
"engines": {
"node": ">= 4.0.0"
}
@@ -12172,19 +11853,11 @@
"dev": true,
"license": "MIT"
},
- "node_modules/encodeurl": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz",
- "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==",
- "license": "MIT",
- "engines": {
- "node": ">= 0.8"
- }
- },
"node_modules/end-of-stream": {
"version": "1.4.5",
"resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.5.tgz",
"integrity": "sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg==",
+ "dev": true,
"license": "MIT",
"dependencies": {
"once": "^1.4.0"
@@ -12306,6 +11979,7 @@
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz",
"integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==",
+ "dev": true,
"license": "MIT",
"engines": {
"node": ">= 0.4"
@@ -12315,6 +11989,7 @@
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz",
"integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==",
+ "dev": true,
"license": "MIT",
"engines": {
"node": ">= 0.4"
@@ -12359,6 +12034,7 @@
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz",
"integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==",
+ "dev": true,
"license": "MIT",
"dependencies": {
"es-errors": "^1.3.0"
@@ -12428,6 +12104,7 @@
"integrity": "sha512-IxpibTjyVnmrIQo5aqNpCgoACA/dTKLTlhMHihVHhdkxKyPO1uBBthumT0rdHmcsk9uMonIWS0m4FljWzILh3w==",
"hasInstallScript": true,
"license": "MIT",
+ "peer": true,
"bin": {
"esbuild": "bin/esbuild"
},
@@ -12467,17 +12144,12 @@
"version": "3.2.0",
"resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz",
"integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==",
+ "dev": true,
"license": "MIT",
"engines": {
"node": ">=6"
}
},
- "node_modules/escape-html": {
- "version": "1.0.3",
- "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
- "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==",
- "license": "MIT"
- },
"node_modules/escape-string-regexp": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
@@ -12496,6 +12168,7 @@
"integrity": "sha512-XoMjdBOwe/esVgEvLmNsD3IRHkm7fbKIUGvrleloJXUZgDHig2IPWNniv+GwjyJXzuNqVjlr5+4yVUZjycJwfQ==",
"dev": true,
"license": "MIT",
+ "peer": true,
"dependencies": {
"@eslint-community/eslint-utils": "^4.8.0",
"@eslint-community/regexpp": "^4.12.1",
@@ -12627,6 +12300,7 @@
"integrity": "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==",
"dev": true,
"license": "MIT",
+ "peer": true,
"funding": {
"url": "https://github.com/sponsors/colinhacks"
}
@@ -12664,16 +12338,6 @@
"eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 || ^9.0.0 || ^10.0.0"
}
},
- "node_modules/eslint-plugin-react-refresh": {
- "version": "0.5.2",
- "resolved": "https://registry.npmjs.org/eslint-plugin-react-refresh/-/eslint-plugin-react-refresh-0.5.2.tgz",
- "integrity": "sha512-hmgTH57GfzoTFjVN0yBwTggnsVUF2tcqi7RJZHqi9lIezSs4eFyAMktA68YD4r5kNw1mxyY4dmkyoFDb3FIqrA==",
- "dev": true,
- "license": "MIT",
- "peerDependencies": {
- "eslint": "^9 || ^10"
- }
- },
"node_modules/eslint-plugin-react/node_modules/balanced-match": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
@@ -12937,24 +12601,6 @@
"node": ">=0.10.0"
}
},
- "node_modules/etag": {
- "version": "1.8.1",
- "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz",
- "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==",
- "license": "MIT",
- "engines": {
- "node": ">= 0.6"
- }
- },
- "node_modules/expand-template": {
- "version": "2.0.3",
- "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz",
- "integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==",
- "license": "(MIT OR WTFPL)",
- "engines": {
- "node": ">=6"
- }
- },
"node_modules/expect-type": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/expect-type/-/expect-type-1.3.0.tgz",
@@ -12972,52 +12618,6 @@
"dev": true,
"license": "Apache-2.0"
},
- "node_modules/express": {
- "version": "4.22.1",
- "resolved": "https://registry.npmjs.org/express/-/express-4.22.1.tgz",
- "integrity": "sha512-F2X8g9P1X7uCPZMA3MVf9wcTqlyNp7IhH5qPCI0izhaOIYXaW9L535tGA3qmjRzpH+bZczqq7hVKxTR4NWnu+g==",
- "license": "MIT",
- "dependencies": {
- "accepts": "~1.3.8",
- "array-flatten": "1.1.1",
- "body-parser": "~1.20.3",
- "content-disposition": "~0.5.4",
- "content-type": "~1.0.4",
- "cookie": "~0.7.1",
- "cookie-signature": "~1.0.6",
- "debug": "2.6.9",
- "depd": "2.0.0",
- "encodeurl": "~2.0.0",
- "escape-html": "~1.0.3",
- "etag": "~1.8.1",
- "finalhandler": "~1.3.1",
- "fresh": "~0.5.2",
- "http-errors": "~2.0.0",
- "merge-descriptors": "1.0.3",
- "methods": "~1.1.2",
- "on-finished": "~2.4.1",
- "parseurl": "~1.3.3",
- "path-to-regexp": "~0.1.12",
- "proxy-addr": "~2.0.7",
- "qs": "~6.14.0",
- "range-parser": "~1.2.1",
- "safe-buffer": "5.2.1",
- "send": "~0.19.0",
- "serve-static": "~1.16.2",
- "setprototypeof": "1.2.0",
- "statuses": "~2.0.1",
- "type-is": "~1.6.18",
- "utils-merge": "1.0.1",
- "vary": "~1.1.2"
- },
- "engines": {
- "node": ">= 0.10.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/express"
- }
- },
"node_modules/extend": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz",
@@ -13165,12 +12765,6 @@
"node": ">= 10"
}
},
- "node_modules/file-uri-to-path": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz",
- "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==",
- "license": "MIT"
- },
"node_modules/filelist": {
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.6.tgz",
@@ -13211,24 +12805,6 @@
"node": ">=10"
}
},
- "node_modules/finalhandler": {
- "version": "1.3.2",
- "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.2.tgz",
- "integrity": "sha512-aA4RyPcd3badbdABGDuTXCMTtOneUCAYH/gxoYRTZlIJdF0YPWuGqiAsIrhNnnqdXGswYk6dGujem4w80UJFhg==",
- "license": "MIT",
- "dependencies": {
- "debug": "2.6.9",
- "encodeurl": "~2.0.0",
- "escape-html": "~1.0.3",
- "on-finished": "~2.4.1",
- "parseurl": "~1.3.3",
- "statuses": "~2.0.2",
- "unpipe": "~1.0.0"
- },
- "engines": {
- "node": ">= 0.8"
- }
- },
"node_modules/find-up": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz",
@@ -13246,20 +12822,6 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
- "node_modules/fingerprint-generator": {
- "version": "2.1.82",
- "resolved": "https://registry.npmjs.org/fingerprint-generator/-/fingerprint-generator-2.1.82.tgz",
- "integrity": "sha512-5Z/yCKW324pMyMarpIKe/QPdkrFWKNJv3ktdU+fXHri80+HAwNE6QhMvEvsMkK9Q8DeCXZlpPHV77UBa1nFb4A==",
- "license": "Apache-2.0",
- "dependencies": {
- "generative-bayesian-network": "^2.1.82",
- "header-generator": "^2.1.82",
- "tslib": "^2.4.0"
- },
- "engines": {
- "node": ">=16.0.0"
- }
- },
"node_modules/flat-cache": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz",
@@ -13327,18 +12889,6 @@
"node": ">=0.10.0"
}
},
- "node_modules/for-own": {
- "version": "0.1.5",
- "resolved": "https://registry.npmjs.org/for-own/-/for-own-0.1.5.tgz",
- "integrity": "sha512-SKmowqGTJoPzLO1T0BBJpkfp3EMacCMOuH40hOUbrbzElVktk4DioXVM99QkLCyKoiuOmyjgcWMpVz2xjE7LZw==",
- "license": "MIT",
- "dependencies": {
- "for-in": "^1.0.1"
- },
- "engines": {
- "node": ">=0.10.0"
- }
- },
"node_modules/form-data": {
"version": "4.0.5",
"resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.5.tgz",
@@ -13356,15 +12906,6 @@
"node": ">= 6"
}
},
- "node_modules/forwarded": {
- "version": "0.2.0",
- "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz",
- "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==",
- "license": "MIT",
- "engines": {
- "node": ">= 0.6"
- }
- },
"node_modules/framer-motion": {
"version": "12.38.0",
"resolved": "https://registry.npmjs.org/framer-motion/-/framer-motion-12.38.0.tgz",
@@ -13391,25 +12932,11 @@
}
}
},
- "node_modules/fresh": {
- "version": "0.5.2",
- "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz",
- "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==",
- "license": "MIT",
- "engines": {
- "node": ">= 0.6"
- }
- },
- "node_modules/fs-constants": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz",
- "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==",
- "license": "MIT"
- },
"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",
@@ -13424,6 +12951,7 @@
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
"integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==",
+ "dev": true,
"license": "ISC"
},
"node_modules/fsevents": {
@@ -13444,6 +12972,7 @@
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
"integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==",
+ "dev": true,
"license": "MIT",
"funding": {
"url": "https://github.com/sponsors/ljharb"
@@ -13480,16 +13009,6 @@
"url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/generative-bayesian-network": {
- "version": "2.1.82",
- "resolved": "https://registry.npmjs.org/generative-bayesian-network/-/generative-bayesian-network-2.1.82.tgz",
- "integrity": "sha512-DH4NrmQheoMaJErdVv2IzaqkbOYSDQZmiZTV6UPDJYRDK2EyPpIQ88XRcYdPeFrUjS1N0Jj25H3HUywoJ1dbow==",
- "license": "Apache-2.0",
- "dependencies": {
- "adm-zip": "^0.5.9",
- "tslib": "^2.4.0"
- }
- },
"node_modules/generator-function": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/generator-function/-/generator-function-2.0.1.tgz",
@@ -13524,6 +13043,7 @@
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz",
"integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==",
+ "dev": true,
"license": "MIT",
"dependencies": {
"call-bind-apply-helpers": "^1.0.2",
@@ -13557,6 +13077,7 @@
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz",
"integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==",
+ "dev": true,
"license": "MIT",
"dependencies": {
"dunder-proto": "^1.0.1",
@@ -13609,29 +13130,6 @@
"node": ">=0.10.0"
}
},
- "node_modules/github-from-package": {
- "version": "0.0.0",
- "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz",
- "integrity": "sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==",
- "license": "MIT"
- },
- "node_modules/glob": {
- "version": "13.0.6",
- "resolved": "https://registry.npmjs.org/glob/-/glob-13.0.6.tgz",
- "integrity": "sha512-Wjlyrolmm8uDpm/ogGyXZXb1Z+Ca2B8NbJwqBVg0axK9GbBeoS7yGV6vjXnYdGm6X53iehEuxxbyiKp8QmN4Vw==",
- "license": "BlueOak-1.0.0",
- "dependencies": {
- "minimatch": "^10.2.2",
- "minipass": "^7.1.3",
- "path-scurry": "^2.0.2"
- },
- "engines": {
- "node": "18 || 20 || >=22"
- },
- "funding": {
- "url": "https://github.com/sponsors/isaacs"
- }
- },
"node_modules/glob-parent": {
"version": "6.0.2",
"resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz",
@@ -13664,19 +13162,6 @@
"node": ">=10.0"
}
},
- "node_modules/globals": {
- "version": "17.6.0",
- "resolved": "https://registry.npmjs.org/globals/-/globals-17.6.0.tgz",
- "integrity": "sha512-sepffkT8stwnIYbsMBpoCHJuJM5l98FUF2AnE07hfvE0m/qp3R586hw4jF4uadbhvg1ooIdzuu7CsfD2jzCaNA==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=18"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
"node_modules/globalthis": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.4.tgz",
@@ -13698,6 +13183,7 @@
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz",
"integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==",
+ "dev": true,
"license": "MIT",
"engines": {
"node": ">= 0.4"
@@ -13738,12 +13224,6 @@
"integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==",
"license": "ISC"
},
- "node_modules/gsap": {
- "version": "3.15.0",
- "resolved": "https://registry.npmjs.org/gsap/-/gsap-3.15.0.tgz",
- "integrity": "sha512-dMW4CWBTUK1AEEDeZc1g4xpPGIrSf9fJF960qbTZmN/QwZIWY5wgliS6JWl9/25fpTGJrMRtSjGtOmPnfjZB+A==",
- "license": "Standard 'no charge' license: https://gsap.com/standard-license."
- },
"node_modules/hachure-fill": {
"version": "0.5.2",
"resolved": "https://registry.npmjs.org/hachure-fill/-/hachure-fill-0.5.2.tgz",
@@ -13806,6 +13286,7 @@
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz",
"integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==",
+ "dev": true,
"license": "MIT",
"engines": {
"node": ">= 0.4"
@@ -13834,6 +13315,7 @@
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz",
"integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==",
+ "dev": true,
"license": "MIT",
"dependencies": {
"function-bind": "^1.1.2"
@@ -14140,21 +13622,6 @@
"url": "https://opencollective.com/unified"
}
},
- "node_modules/header-generator": {
- "version": "2.1.82",
- "resolved": "https://registry.npmjs.org/header-generator/-/header-generator-2.1.82.tgz",
- "integrity": "sha512-4NjPB0+bAKjPoponSmTOkK58IEF2W22sOJA5O48k/MxbCZgOm+jrU4WVR53Z2I6xFgIPkVrQmKtt1LAbWtfqXw==",
- "license": "Apache-2.0",
- "dependencies": {
- "browserslist": "^4.21.1",
- "generative-bayesian-network": "^2.1.82",
- "ow": "^0.28.1",
- "tslib": "^2.4.0"
- },
- "engines": {
- "node": ">=16.0.0"
- }
- },
"node_modules/hermes": {
"resolved": "apps/desktop",
"link": true
@@ -14293,26 +13760,6 @@
"dev": true,
"license": "BSD-2-Clause"
},
- "node_modules/http-errors": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.1.tgz",
- "integrity": "sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==",
- "license": "MIT",
- "dependencies": {
- "depd": "~2.0.0",
- "inherits": "~2.0.4",
- "setprototypeof": "~1.2.0",
- "statuses": "~2.0.2",
- "toidentifier": "~1.0.1"
- },
- "engines": {
- "node": ">= 0.8"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/express"
- }
- },
"node_modules/http-proxy-agent": {
"version": "7.0.2",
"resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz",
@@ -14423,18 +13870,6 @@
"node": "^8.11.2 || >=10"
}
},
- "node_modules/iconv-lite": {
- "version": "0.4.24",
- "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
- "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==",
- "license": "MIT",
- "dependencies": {
- "safer-buffer": ">= 2.1.2 < 3"
- },
- "engines": {
- "node": ">=0.10.0"
- }
- },
"node_modules/ieee754": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz",
@@ -14453,7 +13888,8 @@
"url": "https://feross.org/support"
}
],
- "license": "BSD-3-Clause"
+ "license": "BSD-3-Clause",
+ "optional": true
},
"node_modules/ignore": {
"version": "7.0.5",
@@ -14463,153 +13899,6 @@
"node": ">= 4"
}
},
- "node_modules/impit": {
- "version": "0.7.6",
- "resolved": "https://registry.npmjs.org/impit/-/impit-0.7.6.tgz",
- "integrity": "sha512-AkS6Gv63+E6GMvBrcRhMmOREKpq5oJ0J5m3xwfkHiEs97UIsbpEqFmW3sFw/sdyOTDGRF5q4EjaLxtb922Ta8g==",
- "license": "Apache-2.0",
- "engines": {
- "node": ">= 20"
- },
- "optionalDependencies": {
- "impit-darwin-arm64": "0.7.6",
- "impit-darwin-x64": "0.7.6",
- "impit-linux-arm64-gnu": "0.7.6",
- "impit-linux-arm64-musl": "0.7.6",
- "impit-linux-x64-gnu": "0.7.6",
- "impit-linux-x64-musl": "0.7.6",
- "impit-win32-arm64-msvc": "0.7.6",
- "impit-win32-x64-msvc": "0.7.6"
- }
- },
- "node_modules/impit-darwin-arm64": {
- "version": "0.7.6",
- "resolved": "https://registry.npmjs.org/impit-darwin-arm64/-/impit-darwin-arm64-0.7.6.tgz",
- "integrity": "sha512-M7NQXkttyzqilWfzVkNCp7hApT69m0etyJkVpHze4bR5z1kJnHhdsb8BSdDv2dzvZL4u1JyqZNxq+qoMn84eUw==",
- "cpu": [
- "arm64"
- ],
- "license": "Apache-2.0",
- "optional": true,
- "os": [
- "darwin"
- ],
- "engines": {
- "node": ">= 10"
- }
- },
- "node_modules/impit-darwin-x64": {
- "version": "0.7.6",
- "resolved": "https://registry.npmjs.org/impit-darwin-x64/-/impit-darwin-x64-0.7.6.tgz",
- "integrity": "sha512-kikTesWirAwJp9JPxzGLoGVc+heBlEabWS5AhTkQedACU153vmuL90OBQikVr3ul2N0LPImvnuB+51wV0zDE6g==",
- "cpu": [
- "x64"
- ],
- "license": "Apache-2.0",
- "optional": true,
- "os": [
- "darwin"
- ],
- "engines": {
- "node": ">= 10"
- }
- },
- "node_modules/impit-linux-arm64-gnu": {
- "version": "0.7.6",
- "resolved": "https://registry.npmjs.org/impit-linux-arm64-gnu/-/impit-linux-arm64-gnu-0.7.6.tgz",
- "integrity": "sha512-H6GHjVr/0lG9VEJr6IHF8YLq+YkSIOF4k7Dfue2ygzUAj1+jZ5ZwnouhG/XrZHYW6EWsZmEAjjRfWE56Q0wDRQ==",
- "cpu": [
- "arm64"
- ],
- "license": "Apache-2.0",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">= 10"
- }
- },
- "node_modules/impit-linux-arm64-musl": {
- "version": "0.7.6",
- "resolved": "https://registry.npmjs.org/impit-linux-arm64-musl/-/impit-linux-arm64-musl-0.7.6.tgz",
- "integrity": "sha512-1sCB/UBVXLZTpGJsXRdNNSvhN9xmmQcYLMWAAB4Itb7w684RHX1pLoCb6ichv7bfAf6tgaupcFIFZNBp3ghmQA==",
- "cpu": [
- "arm64"
- ],
- "license": "Apache-2.0",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">= 10"
- }
- },
- "node_modules/impit-linux-x64-gnu": {
- "version": "0.7.6",
- "resolved": "https://registry.npmjs.org/impit-linux-x64-gnu/-/impit-linux-x64-gnu-0.7.6.tgz",
- "integrity": "sha512-yYhlRnZ4fhKt8kuGe0JK2WSHc8TkR6BEH0wn+guevmu8EOn9Xu43OuRvkeOyVAkRqvFnlZtMyySUo/GuSLz9Gw==",
- "cpu": [
- "x64"
- ],
- "license": "Apache-2.0",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">= 10"
- }
- },
- "node_modules/impit-linux-x64-musl": {
- "version": "0.7.6",
- "resolved": "https://registry.npmjs.org/impit-linux-x64-musl/-/impit-linux-x64-musl-0.7.6.tgz",
- "integrity": "sha512-sdGWyu+PCLmaOXy7Mzo4WP61ZLl5qpZ1L+VeXW+Ycazgu0e7ox0NZLdiLRunIrEzD+h0S+e4CyzNwaiP3yIolg==",
- "cpu": [
- "x64"
- ],
- "license": "Apache-2.0",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">= 10"
- }
- },
- "node_modules/impit-win32-arm64-msvc": {
- "version": "0.7.6",
- "resolved": "https://registry.npmjs.org/impit-win32-arm64-msvc/-/impit-win32-arm64-msvc-0.7.6.tgz",
- "integrity": "sha512-sM5deBqo0EuXg5GACBUMKEua9jIau/i34bwNlfrf/Amnw1n0GB4/RkuUh+sKiUcbNAntrRq+YhCq8qDP8IW19w==",
- "cpu": [
- "arm64"
- ],
- "license": "Apache-2.0",
- "optional": true,
- "os": [
- "win32"
- ],
- "engines": {
- "node": ">= 10"
- }
- },
- "node_modules/impit-win32-x64-msvc": {
- "version": "0.7.6",
- "resolved": "https://registry.npmjs.org/impit-win32-x64-msvc/-/impit-win32-x64-msvc-0.7.6.tgz",
- "integrity": "sha512-ry63ADGLCB/PU/vNB1VioRt2V+klDJ34frJUXUZBEv1kA96HEAg9AxUk+604o+UHS3ttGH2rkLmrbwHOdAct5Q==",
- "cpu": [
- "x64"
- ],
- "license": "Apache-2.0",
- "optional": true,
- "os": [
- "win32"
- ],
- "engines": {
- "node": ">= 10"
- }
- },
"node_modules/import-fresh": {
"version": "3.3.1",
"resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz",
@@ -14642,6 +13931,7 @@
"resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
"integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==",
"deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.",
+ "dev": true,
"license": "ISC",
"dependencies": {
"once": "^1.3.0",
@@ -14652,12 +13942,7 @@
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
- "license": "ISC"
- },
- "node_modules/ini": {
- "version": "1.3.8",
- "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz",
- "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==",
+ "dev": true,
"license": "ISC"
},
"node_modules/inline-style-parser": {
@@ -14695,19 +13980,11 @@
"resolved": "https://registry.npmjs.org/interval-tree-1d/-/interval-tree-1d-1.0.4.tgz",
"integrity": "sha512-wY8QJH+6wNI0uh4pDQzMvl+478Qh7Rl4qLmqiluxALlNvl+I+o5x38Pw3/z7mDPTPS1dQalZJXsmbvxx5gclhQ==",
"license": "MIT",
+ "optional": true,
"dependencies": {
"binary-search-bounds": "^2.0.0"
}
},
- "node_modules/ipaddr.js": {
- "version": "1.9.1",
- "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz",
- "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==",
- "license": "MIT",
- "engines": {
- "node": ">= 0.10"
- }
- },
"node_modules/is-alphabetical": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/is-alphabetical/-/is-alphabetical-2.0.1.tgz",
@@ -14803,12 +14080,6 @@
"url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/is-buffer": {
- "version": "1.1.6",
- "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz",
- "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==",
- "license": "MIT"
- },
"node_modules/is-callable": {
"version": "1.2.7",
"resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz",
@@ -15030,15 +14301,6 @@
"url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/is-obj": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz",
- "integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==",
- "license": "MIT",
- "engines": {
- "node": ">=8"
- }
- },
"node_modules/is-plain-obj": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-4.1.0.tgz",
@@ -15118,26 +14380,6 @@
"url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/is-standalone-pwa": {
- "version": "0.1.1",
- "resolved": "https://registry.npmjs.org/is-standalone-pwa/-/is-standalone-pwa-0.1.1.tgz",
- "integrity": "sha512-9Cbovsa52vNQCjdXOzeQq5CnCbAcRk05aU62K20WO372NrTv0NxibLFCK6lQ4/iZEFdEA3p3t2VNOn8AJ53F5g==",
- "funding": [
- {
- "type": "github",
- "url": "https://github.com/sponsors/faisalman"
- },
- {
- "type": "opencollective",
- "url": "https://opencollective.com/ua-parser-js"
- },
- {
- "type": "paypal",
- "url": "https://paypal.me/faisalman"
- }
- ],
- "license": "MIT"
- },
"node_modules/is-string": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/is-string/-/is-string-1.1.1.tgz",
@@ -15288,7 +14530,8 @@
"version": "0.2.1",
"resolved": "https://registry.npmjs.org/isoformat/-/isoformat-0.2.1.tgz",
"integrity": "sha512-tFLRAygk9NqrRPhJSnNGh7g7oaVWDwR0wKh/GM2LgmPa50Eg4UfyaCO4I8k6EqJHl1/uh2RAD6g06n5ygEnrjQ==",
- "license": "ISC"
+ "license": "ISC",
+ "optional": true
},
"node_modules/iterator.prototype": {
"version": "1.1.5",
@@ -15313,6 +14556,7 @@
"resolved": "https://registry.npmjs.org/its-fine/-/its-fine-2.0.0.tgz",
"integrity": "sha512-KLViCmWx94zOvpLwSlsx6yOCeMhZYaxrJV87Po5k/FoZzcPSahvK5qJ7fYhS61sZi5ikmh2S3Hz55A2l3U69ng==",
"license": "MIT",
+ "optional": true,
"dependencies": {
"@types/react-reconciler": "^0.28.9"
},
@@ -15495,6 +14739,7 @@
"version": "6.2.0",
"resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.0.tgz",
"integrity": "sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==",
+ "dev": true,
"license": "MIT",
"dependencies": {
"universalify": "^2.0.0"
@@ -15559,18 +14804,6 @@
"resolved": "https://registry.npmjs.org/khroma/-/khroma-2.1.0.tgz",
"integrity": "sha512-Ls993zuzfayK269Svk9hzpeGUKob/sIgZzyHYdjQoAdQetRKpOLj+k/QQQ/6Qi0Yz65mlROrfd+Ev+1+7dz9Kw=="
},
- "node_modules/kind-of": {
- "version": "3.2.2",
- "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
- "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==",
- "license": "MIT",
- "dependencies": {
- "is-buffer": "^1.1.5"
- },
- "engines": {
- "node": ">=0.10.0"
- }
- },
"node_modules/langium": {
"version": "4.2.3",
"resolved": "https://registry.npmjs.org/langium/-/langium-4.2.3.tgz",
@@ -15589,24 +14822,6 @@
"npm": ">=10.2.3"
}
},
- "node_modules/language-subtag-registry": {
- "version": "0.3.23",
- "resolved": "https://registry.npmjs.org/language-subtag-registry/-/language-subtag-registry-0.3.23.tgz",
- "integrity": "sha512-0K65Lea881pHotoGEa5gDlMxt3pctLi2RplBb7Ezh4rRdLEOtgi7n4EwK9lamnUCkKBqaeKRVebTq6BAxSkpXQ==",
- "license": "CC0-1.0"
- },
- "node_modules/language-tags": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/language-tags/-/language-tags-2.1.0.tgz",
- "integrity": "sha512-D4CgpyCt+61f6z2jHjJS1OmZPviAWM57iJ9OKdFFWSNgS7Udj9QVWqyGs/cveVNF57XpZmhSvMdVIV5mjLA7Vg==",
- "license": "MIT",
- "dependencies": {
- "language-subtag-registry": "^0.3.20"
- },
- "engines": {
- "node": ">=22"
- }
- },
"node_modules/launder": {
"version": "1.7.1",
"resolved": "https://registry.npmjs.org/launder/-/launder-1.7.1.tgz",
@@ -15622,15 +14837,6 @@
"integrity": "sha512-8h2oVEZNktL4BH2JCOI90iD1yXwL6iNW7KcCKT2QZgQJR2vbqDsldCTPRU9NifTCqHZci57XvQQ15YTu+sTYPg==",
"license": "MIT"
},
- "node_modules/lazy-cache": {
- "version": "1.0.4",
- "resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-1.0.4.tgz",
- "integrity": "sha512-RE2g0b5VGZsOCFOCgP7omTRYFqydmZkBwl5oNnQ1lDYC57uyO9KqNnNVxT7COSHTxrRCWVcAVOcbjk+tvh/rgQ==",
- "license": "MIT",
- "engines": {
- "node": ">=0.10.0"
- }
- },
"node_modules/lazy-val": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/lazy-val/-/lazy-val-1.0.5.tgz",
@@ -15642,6 +14848,7 @@
"version": "0.10.1",
"resolved": "https://registry.npmjs.org/leva/-/leva-0.10.1.tgz",
"integrity": "sha512-BcjnfUX8jpmwZUz2L7AfBtF9vn4ggTH33hmeufDULbP3YgNZ/C+ss/oO3stbrqRQyaOmRwy70y7BGTGO81S3rA==",
+ "peer": true,
"dependencies": {
"@radix-ui/react-portal": "^1.1.4",
"@radix-ui/react-tooltip": "^1.1.8",
@@ -15969,13 +15176,6 @@
"integrity": "sha512-J8xewKD/Gk22OZbhpOVSwcs60zhd95ESDwezOFuA3/099925PdHJ7OFHNTGtajL3AlZkykD32HykiMo+BIBI8A==",
"license": "MIT"
},
- "node_modules/lodash.isequal": {
- "version": "4.5.0",
- "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz",
- "integrity": "sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==",
- "deprecated": "This package is deprecated. Use require('node:util').isDeepStrictEqual instead.",
- "license": "MIT"
- },
"node_modules/lodash.merge": {
"version": "4.6.2",
"resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz",
@@ -16040,7 +15240,6 @@
"integrity": "sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ==",
"dev": true,
"license": "MIT",
- "peer": true,
"bin": {
"lz-string": "bin/bin.js"
}
@@ -16094,25 +15293,12 @@
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz",
"integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==",
+ "dev": true,
"license": "MIT",
"engines": {
"node": ">= 0.4"
}
},
- "node_modules/maxmind": {
- "version": "5.0.6",
- "resolved": "https://registry.npmjs.org/maxmind/-/maxmind-5.0.6.tgz",
- "integrity": "sha512-5bvd/u+kIaTqaGM+xkXjatzQw1dQfSmlLggr2W1EKMyMxSgx2woZyusLpNpZ4DdPmL+1bbJWeo4LXsi6bC0Iew==",
- "license": "MIT",
- "dependencies": {
- "mmdb-lib": "3.0.2",
- "tiny-lru": "13.0.0"
- },
- "engines": {
- "node": ">=12",
- "npm": ">=6"
- }
- },
"node_modules/mdast-util-find-and-replace": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/mdast-util-find-and-replace/-/mdast-util-find-and-replace-3.0.2.tgz",
@@ -16421,43 +15607,11 @@
"dev": true,
"license": "CC0-1.0"
},
- "node_modules/media-typer": {
- "version": "0.3.0",
- "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
- "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==",
- "license": "MIT",
- "engines": {
- "node": ">= 0.6"
- }
- },
"node_modules/memoize-one": {
"version": "5.2.1",
"resolved": "https://registry.npmjs.org/memoize-one/-/memoize-one-5.2.1.tgz",
"integrity": "sha512-zYiwtZUcYyXKo/np96AGZAckk+FWWsUdJ3cHGGmld7+AhvcWmQyGCYUh1hc4Q/pkOhb65dQR/pqCyK0cOaHz4Q=="
},
- "node_modules/merge-deep": {
- "version": "3.0.3",
- "resolved": "https://registry.npmjs.org/merge-deep/-/merge-deep-3.0.3.tgz",
- "integrity": "sha512-qtmzAS6t6grwEkNrunqTBdn0qKwFgNWvlxUbAV8es9M7Ot1EbyApytCnvE0jALPa46ZpKDUo527kKiaWplmlFA==",
- "license": "MIT",
- "dependencies": {
- "arr-union": "^3.1.0",
- "clone-deep": "^0.2.4",
- "kind-of": "^3.0.2"
- },
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/merge-descriptors": {
- "version": "1.0.3",
- "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.3.tgz",
- "integrity": "sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==",
- "license": "MIT",
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
"node_modules/merge-value": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/merge-value/-/merge-value-1.0.0.tgz",
@@ -16526,15 +15680,6 @@
"node": ">= 20"
}
},
- "node_modules/methods": {
- "version": "1.1.2",
- "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz",
- "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==",
- "license": "MIT",
- "engines": {
- "node": ">= 0.6"
- }
- },
"node_modules/micromark": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/micromark/-/micromark-4.0.2.tgz",
@@ -17140,22 +16285,11 @@
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
"license": "MIT"
},
- "node_modules/mime": {
- "version": "1.6.0",
- "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz",
- "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==",
- "license": "MIT",
- "bin": {
- "mime": "cli.js"
- },
- "engines": {
- "node": ">=4"
- }
- },
"node_modules/mime-db": {
"version": "1.52.0",
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
"integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
+ "dev": true,
"license": "MIT",
"engines": {
"node": ">= 0.6"
@@ -17165,6 +16299,7 @@
"version": "2.1.35",
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
"integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
+ "dev": true,
"license": "MIT",
"dependencies": {
"mime-db": "1.52.0"
@@ -17177,6 +16312,7 @@
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz",
"integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==",
+ "dev": true,
"license": "MIT",
"engines": {
"node": ">=10"
@@ -17189,6 +16325,7 @@
"version": "10.2.5",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.5.tgz",
"integrity": "sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg==",
+ "dev": true,
"license": "BlueOak-1.0.0",
"dependencies": {
"brace-expansion": "^5.0.5"
@@ -17204,6 +16341,7 @@
"version": "1.2.8",
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz",
"integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==",
+ "dev": true,
"license": "MIT",
"funding": {
"url": "https://github.com/sponsors/ljharb"
@@ -17213,6 +16351,7 @@
"version": "7.1.3",
"resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.3.tgz",
"integrity": "sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A==",
+ "dev": true,
"license": "BlueOak-1.0.0",
"engines": {
"node": ">=16 || 14 >=14.17"
@@ -17256,35 +16395,12 @@
"node": ">=0.10.0"
}
},
- "node_modules/mixin-object": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/mixin-object/-/mixin-object-2.0.1.tgz",
- "integrity": "sha512-ALGF1Jt9ouehcaXaHhn6t1yGWRqGaHkPFndtFVHfZXOvkIZ/yoGaSi0AHVTafb3ZBGg4dr/bDwnaEKqCXzchMA==",
- "license": "MIT",
- "dependencies": {
- "for-in": "^0.1.3",
- "is-extendable": "^0.1.1"
- },
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/mixin-object/node_modules/for-in": {
- "version": "0.1.8",
- "resolved": "https://registry.npmjs.org/for-in/-/for-in-0.1.8.tgz",
- "integrity": "sha512-F0to7vbBSHP8E3l6dCjxNOLuSFAACIxFy3UehTUlG7svlXi37HHsDkyVcHo0Pq8QwrE+pXvWSVX3ZT1T9wAZ9g==",
- "license": "MIT",
- "engines": {
- "node": ">=0.10.0"
- }
- },
"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"
},
@@ -17292,12 +16408,6 @@
"mkdirp": "bin/cmd.js"
}
},
- "node_modules/mkdirp-classic": {
- "version": "0.5.3",
- "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz",
- "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==",
- "license": "MIT"
- },
"node_modules/mlly": {
"version": "1.8.2",
"resolved": "https://registry.npmjs.org/mlly/-/mlly-1.8.2.tgz",
@@ -17310,20 +16420,11 @@
"ufo": "^1.6.3"
}
},
- "node_modules/mmdb-lib": {
- "version": "3.0.2",
- "resolved": "https://registry.npmjs.org/mmdb-lib/-/mmdb-lib-3.0.2.tgz",
- "integrity": "sha512-7e87vk0DdWT647wjcfEtWeMtjm+zVGqNohN/aeIymbUfjHQ2T4Sx5kM+1irVDBSloNC3CkGKxswdMoo8yhqTDg==",
- "license": "MIT",
- "engines": {
- "node": ">=10",
- "npm": ">=6"
- }
- },
"node_modules/motion": {
"version": "12.38.0",
"resolved": "https://registry.npmjs.org/motion/-/motion-12.38.0.tgz",
"integrity": "sha512-uYfXzeHlgThchzwz5Te47dlv5JOUC7OB4rjJ/7XTUgtBZD8CchMN8qEJ4ZVsUmTyYA44zjV0fBwsiktRuFnn+w==",
+ "peer": true,
"dependencies": {
"framer-motion": "^12.38.0",
"tslib": "^2.4.0"
@@ -17358,12 +16459,6 @@
"resolved": "https://registry.npmjs.org/motion-utils/-/motion-utils-12.36.0.tgz",
"integrity": "sha512-eHWisygbiwVvf6PZ1vhaHCLamvkSbPIeAYxWUuL3a2PD/TROgE7FvfHWTIH4vMl798QLfMw15nRqIaRDXTlYRg=="
},
- "node_modules/ms": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
- "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
- "license": "MIT"
- },
"node_modules/nanoid": {
"version": "5.1.11",
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-5.1.11.tgz",
@@ -17393,16 +16488,11 @@
}
],
"license": "MIT",
+ "peer": true,
"engines": {
"node": "^20.0.0 || >=22.0.0"
}
},
- "node_modules/napi-build-utils": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-2.0.0.tgz",
- "integrity": "sha512-GEbrYkbfF7MoNaoh2iGG84Mnf/WZfB0GdGEsM8wz7Expx/LlWf5U8t9nvJKXSp3qr5IsEbK04cBGhol/KwOsWA==",
- "license": "MIT"
- },
"node_modules/natural-compare": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz",
@@ -17420,27 +16510,6 @@
"node": ">=18"
}
},
- "node_modules/negotiator": {
- "version": "0.6.3",
- "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz",
- "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==",
- "license": "MIT",
- "engines": {
- "node": ">= 0.6"
- }
- },
- "node_modules/node-abi": {
- "version": "3.89.0",
- "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.89.0.tgz",
- "integrity": "sha512-6u9UwL0HlAl21+agMN3YAMXcKByMqwGx+pq+P76vii5f7hTPtKDp08/H9py6DY+cfDw7kQNTGEj/rly3IgbNQA==",
- "license": "MIT",
- "dependencies": {
- "semver": "^7.3.5"
- },
- "engines": {
- "node": ">=10"
- }
- },
"node_modules/node-addon-api": {
"version": "1.7.2",
"resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-1.7.2.tgz",
@@ -17569,6 +16638,7 @@
"version": "2.0.37",
"resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.37.tgz",
"integrity": "sha512-1h5gKZCF+pO/o3Iqt5Jp7wc9rH3eJJ0+nh/CIoiRwjRxde/hAHyLPXYN4V3CqKAbiZPSeJFSWHmJsbkicta0Eg==",
+ "dev": true,
"license": "MIT"
},
"node_modules/nopt": {
@@ -17613,6 +16683,7 @@
"version": "1.13.4",
"resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz",
"integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==",
+ "dev": true,
"license": "MIT",
"engines": {
"node": ">= 0.4"
@@ -17717,22 +16788,11 @@
],
"license": "MIT"
},
- "node_modules/on-finished": {
- "version": "2.4.1",
- "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz",
- "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==",
- "license": "MIT",
- "dependencies": {
- "ee-first": "1.1.1"
- },
- "engines": {
- "node": ">= 0.8"
- }
- },
"node_modules/once": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
"integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
+ "dev": true,
"license": "ISC",
"dependencies": {
"wrappy": "1"
@@ -17773,25 +16833,6 @@
"node": ">= 0.8.0"
}
},
- "node_modules/ow": {
- "version": "0.28.2",
- "resolved": "https://registry.npmjs.org/ow/-/ow-0.28.2.tgz",
- "integrity": "sha512-dD4UpyBh/9m4X2NVjA+73/ZPBRF+uF4zIMFvvQsabMiEK8x41L3rQ8EENOi35kyyoaJwNxEeJcP6Fj1H4U409Q==",
- "license": "MIT",
- "dependencies": {
- "@sindresorhus/is": "^4.2.0",
- "callsites": "^3.1.0",
- "dot-prop": "^6.0.1",
- "lodash.isequal": "^4.5.0",
- "vali-date": "^1.0.0"
- },
- "engines": {
- "node": ">=12"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
"node_modules/own-keys": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/own-keys/-/own-keys-1.0.1.tgz",
@@ -17915,15 +16956,6 @@
"url": "https://github.com/inikulin/parse5?sponsor=1"
}
},
- "node_modules/parseurl": {
- "version": "1.3.3",
- "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz",
- "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==",
- "license": "MIT",
- "engines": {
- "node": ">= 0.8"
- }
- },
"node_modules/path-data-parser": {
"version": "0.1.0",
"resolved": "https://registry.npmjs.org/path-data-parser/-/path-data-parser-0.1.0.tgz",
@@ -17944,6 +16976,7 @@
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
"integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==",
+ "dev": true,
"license": "MIT",
"engines": {
"node": ">=0.10.0"
@@ -17966,37 +16999,6 @@
"dev": true,
"license": "MIT"
},
- "node_modules/path-scurry": {
- "version": "2.0.2",
- "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-2.0.2.tgz",
- "integrity": "sha512-3O/iVVsJAPsOnpwWIeD+d6z/7PmqApyQePUtCndjatj/9I5LylHvt5qluFaBT3I5h3r1ejfR056c+FCv+NnNXg==",
- "license": "BlueOak-1.0.0",
- "dependencies": {
- "lru-cache": "^11.0.0",
- "minipass": "^7.1.2"
- },
- "engines": {
- "node": "18 || 20 || >=22"
- },
- "funding": {
- "url": "https://github.com/sponsors/isaacs"
- }
- },
- "node_modules/path-scurry/node_modules/lru-cache": {
- "version": "11.3.3",
- "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.3.3.tgz",
- "integrity": "sha512-JvNw9Y81y33E+BEYPr0U7omo+U9AySnsMsEiXgwT6yqd31VQWTLNQqmT4ou5eqPFUrTfIDFta2wKhB1hyohtAQ==",
- "license": "BlueOak-1.0.0",
- "engines": {
- "node": "20 || >=22"
- }
- },
- "node_modules/path-to-regexp": {
- "version": "0.1.13",
- "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.13.tgz",
- "integrity": "sha512-A/AGNMFN3c8bOlvV9RreMdrv7jsmF9XIfDeCd87+I8RNg6s78BhJxMu69NEMHBSJFxKidViTEdruRwEk/WIKqA==",
- "license": "MIT"
- },
"node_modules/pathe": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz",
@@ -18054,83 +17056,6 @@
"pathe": "^2.0.1"
}
},
- "node_modules/playwright": {
- "version": "1.59.1",
- "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.59.1.tgz",
- "integrity": "sha512-C8oWjPR3F81yljW9o5OxcWzfh6avkVwDD2VYdwIGqTkl+OGFISgypqzfu7dOe4QNLL2aqcWBmI3PMtLIK233lw==",
- "license": "Apache-2.0",
- "dependencies": {
- "playwright-core": "1.59.1"
- },
- "bin": {
- "playwright": "cli.js"
- },
- "engines": {
- "node": ">=18"
- },
- "optionalDependencies": {
- "fsevents": "2.3.2"
- }
- },
- "node_modules/playwright-core": {
- "version": "1.59.1",
- "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.59.1.tgz",
- "integrity": "sha512-HBV/RJg81z5BiiZ9yPzIiClYV/QMsDCKUyogwH9p3MCP6IYjUFu/MActgYAvK0oWyV9NlwM3GLBjADyWgydVyg==",
- "license": "Apache-2.0",
- "bin": {
- "playwright-core": "cli.js"
- },
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/playwright-extra": {
- "version": "4.3.6",
- "resolved": "https://registry.npmjs.org/playwright-extra/-/playwright-extra-4.3.6.tgz",
- "integrity": "sha512-q2rVtcE8V8K3vPVF1zny4pvwZveHLH8KBuVU2MoE3Jw4OKVoBWsHI9CH9zPydovHHOCDxjGN2Vg+2m644q3ijA==",
- "license": "MIT",
- "dependencies": {
- "debug": "^4.3.4"
- },
- "engines": {
- "node": ">=12"
- },
- "peerDependencies": {
- "playwright": "*",
- "playwright-core": "*"
- },
- "peerDependenciesMeta": {
- "playwright": {
- "optional": true
- },
- "playwright-core": {
- "optional": true
- }
- }
- },
- "node_modules/playwright-extra/node_modules/debug": {
- "version": "4.4.3",
- "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz",
- "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==",
- "license": "MIT",
- "dependencies": {
- "ms": "^2.1.3"
- },
- "engines": {
- "node": ">=6.0"
- },
- "peerDependenciesMeta": {
- "supports-color": {
- "optional": true
- }
- }
- },
- "node_modules/playwright-extra/node_modules/ms": {
- "version": "2.1.3",
- "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
- "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
- "license": "MIT"
- },
"node_modules/plist": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/plist/-/plist-3.1.0.tgz",
@@ -18240,33 +17165,6 @@
"node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
}
},
- "node_modules/prebuild-install": {
- "version": "7.1.3",
- "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.3.tgz",
- "integrity": "sha512-8Mf2cbV7x1cXPUILADGI3wuhfqWvtiLA1iclTDbFRZkgRQS0NqsPZphna9V+HyTEadheuPmjaJMsbzKQFOzLug==",
- "deprecated": "No longer maintained. Please contact the author of the relevant native addon; alternatives are available.",
- "license": "MIT",
- "dependencies": {
- "detect-libc": "^2.0.0",
- "expand-template": "^2.0.3",
- "github-from-package": "0.0.0",
- "minimist": "^1.2.3",
- "mkdirp-classic": "^0.5.3",
- "napi-build-utils": "^2.0.0",
- "node-abi": "^3.3.0",
- "pump": "^3.0.0",
- "rc": "^1.2.7",
- "simple-get": "^4.0.0",
- "tar-fs": "^2.0.0",
- "tunnel-agent": "^0.6.0"
- },
- "bin": {
- "prebuild-install": "bin.js"
- },
- "engines": {
- "node": ">=10"
- }
- },
"node_modules/prelude-ls": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz",
@@ -18299,7 +17197,6 @@
"integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==",
"dev": true,
"license": "MIT",
- "peer": true,
"dependencies": {
"ansi-regex": "^5.0.1",
"ansi-styles": "^5.0.0",
@@ -18315,7 +17212,6 @@
"integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==",
"dev": true,
"license": "MIT",
- "peer": true,
"engines": {
"node": ">=10"
},
@@ -18337,24 +17233,12 @@
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz",
"integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==",
+ "dev": true,
"license": "MIT",
"engines": {
"node": ">=0.4.0"
}
},
- "node_modules/prom-client": {
- "version": "15.1.3",
- "resolved": "https://registry.npmjs.org/prom-client/-/prom-client-15.1.3.tgz",
- "integrity": "sha512-6ZiOBfCywsD4k1BN9IX0uZhF+tJkV8q8llP64G5Hajs4JOeVLPCwpPVcpXy3BwYiUGgyJzsJJQeOIv7+hDSq8g==",
- "license": "Apache-2.0",
- "dependencies": {
- "@opentelemetry/api": "^1.4.0",
- "tdigest": "^0.1.1"
- },
- "engines": {
- "node": "^16 || ^18 || >=20"
- }
- },
"node_modules/promise-retry": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/promise-retry/-/promise-retry-2.0.1.tgz",
@@ -18408,19 +17292,6 @@
"url": "https://github.com/sponsors/wooorm"
}
},
- "node_modules/proxy-addr": {
- "version": "2.0.7",
- "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz",
- "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==",
- "license": "MIT",
- "dependencies": {
- "forwarded": "0.2.0",
- "ipaddr.js": "1.9.1"
- },
- "engines": {
- "node": ">= 0.10"
- }
- },
"node_modules/proxy-from-env": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-2.1.0.tgz",
@@ -18435,6 +17306,7 @@
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/pump/-/pump-3.0.4.tgz",
"integrity": "sha512-VS7sjc6KR7e1ukRFhQSY5LM2uBWAUPiOPa/A3mkKmiMwSmRFUITt0xuj+/lesgnCv+dPIEYlkzrcyXgquIHMcA==",
+ "dev": true,
"license": "MIT",
"dependencies": {
"end-of-stream": "^1.1.0",
@@ -18451,284 +17323,6 @@
"node": ">=6"
}
},
- "node_modules/puppeteer-extra-plugin": {
- "version": "3.2.3",
- "resolved": "https://registry.npmjs.org/puppeteer-extra-plugin/-/puppeteer-extra-plugin-3.2.3.tgz",
- "integrity": "sha512-6RNy0e6pH8vaS3akPIKGg28xcryKscczt4wIl0ePciZENGE2yoaQJNd17UiEbdmh5/6WW6dPcfRWT9lxBwCi2Q==",
- "license": "MIT",
- "dependencies": {
- "@types/debug": "^4.1.0",
- "debug": "^4.1.1",
- "merge-deep": "^3.0.1"
- },
- "engines": {
- "node": ">=9.11.2"
- },
- "peerDependencies": {
- "playwright-extra": "*",
- "puppeteer-extra": "*"
- },
- "peerDependenciesMeta": {
- "playwright-extra": {
- "optional": true
- },
- "puppeteer-extra": {
- "optional": true
- }
- }
- },
- "node_modules/puppeteer-extra-plugin-stealth": {
- "version": "2.11.2",
- "resolved": "https://registry.npmjs.org/puppeteer-extra-plugin-stealth/-/puppeteer-extra-plugin-stealth-2.11.2.tgz",
- "integrity": "sha512-bUemM5XmTj9i2ZerBzsk2AN5is0wHMNE6K0hXBzBXOzP5m5G3Wl0RHhiqKeHToe/uIH8AoZiGhc1tCkLZQPKTQ==",
- "license": "MIT",
- "dependencies": {
- "debug": "^4.1.1",
- "puppeteer-extra-plugin": "^3.2.3",
- "puppeteer-extra-plugin-user-preferences": "^2.4.1"
- },
- "engines": {
- "node": ">=8"
- },
- "peerDependencies": {
- "playwright-extra": "*",
- "puppeteer-extra": "*"
- },
- "peerDependenciesMeta": {
- "playwright-extra": {
- "optional": true
- },
- "puppeteer-extra": {
- "optional": true
- }
- }
- },
- "node_modules/puppeteer-extra-plugin-stealth/node_modules/debug": {
- "version": "4.4.3",
- "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz",
- "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==",
- "license": "MIT",
- "dependencies": {
- "ms": "^2.1.3"
- },
- "engines": {
- "node": ">=6.0"
- },
- "peerDependenciesMeta": {
- "supports-color": {
- "optional": true
- }
- }
- },
- "node_modules/puppeteer-extra-plugin-stealth/node_modules/ms": {
- "version": "2.1.3",
- "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
- "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
- "license": "MIT"
- },
- "node_modules/puppeteer-extra-plugin-user-data-dir": {
- "version": "2.4.1",
- "resolved": "https://registry.npmjs.org/puppeteer-extra-plugin-user-data-dir/-/puppeteer-extra-plugin-user-data-dir-2.4.1.tgz",
- "integrity": "sha512-kH1GnCcqEDoBXO7epAse4TBPJh9tEpVEK/vkedKfjOVOhZAvLkHGc9swMs5ChrJbRnf8Hdpug6TJlEuimXNQ+g==",
- "license": "MIT",
- "dependencies": {
- "debug": "^4.1.1",
- "fs-extra": "^10.0.0",
- "puppeteer-extra-plugin": "^3.2.3",
- "rimraf": "^3.0.2"
- },
- "engines": {
- "node": ">=8"
- },
- "peerDependencies": {
- "playwright-extra": "*",
- "puppeteer-extra": "*"
- },
- "peerDependenciesMeta": {
- "playwright-extra": {
- "optional": true
- },
- "puppeteer-extra": {
- "optional": true
- }
- }
- },
- "node_modules/puppeteer-extra-plugin-user-data-dir/node_modules/balanced-match": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
- "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
- "license": "MIT"
- },
- "node_modules/puppeteer-extra-plugin-user-data-dir/node_modules/brace-expansion": {
- "version": "1.1.14",
- "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.14.tgz",
- "integrity": "sha512-MWPGfDxnyzKU7rNOW9SP/c50vi3xrmrua/+6hfPbCS2ABNWfx24vPidzvC7krjU/RTo235sV776ymlsMtGKj8g==",
- "license": "MIT",
- "dependencies": {
- "balanced-match": "^1.0.0",
- "concat-map": "0.0.1"
- }
- },
- "node_modules/puppeteer-extra-plugin-user-data-dir/node_modules/debug": {
- "version": "4.4.3",
- "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz",
- "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==",
- "license": "MIT",
- "dependencies": {
- "ms": "^2.1.3"
- },
- "engines": {
- "node": ">=6.0"
- },
- "peerDependenciesMeta": {
- "supports-color": {
- "optional": true
- }
- }
- },
- "node_modules/puppeteer-extra-plugin-user-data-dir/node_modules/glob": {
- "version": "7.2.3",
- "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
- "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
- "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",
- "license": "ISC",
- "dependencies": {
- "fs.realpath": "^1.0.0",
- "inflight": "^1.0.4",
- "inherits": "2",
- "minimatch": "^3.1.1",
- "once": "^1.3.0",
- "path-is-absolute": "^1.0.0"
- },
- "engines": {
- "node": "*"
- },
- "funding": {
- "url": "https://github.com/sponsors/isaacs"
- }
- },
- "node_modules/puppeteer-extra-plugin-user-data-dir/node_modules/minimatch": {
- "version": "3.1.5",
- "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz",
- "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==",
- "license": "ISC",
- "dependencies": {
- "brace-expansion": "^1.1.7"
- },
- "engines": {
- "node": "*"
- }
- },
- "node_modules/puppeteer-extra-plugin-user-data-dir/node_modules/ms": {
- "version": "2.1.3",
- "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
- "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
- "license": "MIT"
- },
- "node_modules/puppeteer-extra-plugin-user-data-dir/node_modules/rimraf": {
- "version": "3.0.2",
- "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
- "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==",
- "deprecated": "Rimraf versions prior to v4 are no longer supported",
- "license": "ISC",
- "dependencies": {
- "glob": "^7.1.3"
- },
- "bin": {
- "rimraf": "bin.js"
- },
- "funding": {
- "url": "https://github.com/sponsors/isaacs"
- }
- },
- "node_modules/puppeteer-extra-plugin-user-preferences": {
- "version": "2.4.1",
- "resolved": "https://registry.npmjs.org/puppeteer-extra-plugin-user-preferences/-/puppeteer-extra-plugin-user-preferences-2.4.1.tgz",
- "integrity": "sha512-i1oAZxRbc1bk8MZufKCruCEC3CCafO9RKMkkodZltI4OqibLFXF3tj6HZ4LZ9C5vCXZjYcDWazgtY69mnmrQ9A==",
- "license": "MIT",
- "dependencies": {
- "debug": "^4.1.1",
- "deepmerge": "^4.2.2",
- "puppeteer-extra-plugin": "^3.2.3",
- "puppeteer-extra-plugin-user-data-dir": "^2.4.1"
- },
- "engines": {
- "node": ">=8"
- },
- "peerDependencies": {
- "playwright-extra": "*",
- "puppeteer-extra": "*"
- },
- "peerDependenciesMeta": {
- "playwright-extra": {
- "optional": true
- },
- "puppeteer-extra": {
- "optional": true
- }
- }
- },
- "node_modules/puppeteer-extra-plugin-user-preferences/node_modules/debug": {
- "version": "4.4.3",
- "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz",
- "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==",
- "license": "MIT",
- "dependencies": {
- "ms": "^2.1.3"
- },
- "engines": {
- "node": ">=6.0"
- },
- "peerDependenciesMeta": {
- "supports-color": {
- "optional": true
- }
- }
- },
- "node_modules/puppeteer-extra-plugin-user-preferences/node_modules/ms": {
- "version": "2.1.3",
- "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
- "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
- "license": "MIT"
- },
- "node_modules/puppeteer-extra-plugin/node_modules/debug": {
- "version": "4.4.3",
- "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz",
- "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==",
- "license": "MIT",
- "dependencies": {
- "ms": "^2.1.3"
- },
- "engines": {
- "node": ">=6.0"
- },
- "peerDependenciesMeta": {
- "supports-color": {
- "optional": true
- }
- }
- },
- "node_modules/puppeteer-extra-plugin/node_modules/ms": {
- "version": "2.1.3",
- "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
- "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
- "license": "MIT"
- },
- "node_modules/qs": {
- "version": "6.14.2",
- "resolved": "https://registry.npmjs.org/qs/-/qs-6.14.2.tgz",
- "integrity": "sha512-V/yCWTTF7VJ9hIh18Ugr2zhJMP01MY7c5kh4J870L7imm6/DIzBsNLTXzMwUA3yZ5b/KBqLx8Kp3uRvd7xSe3Q==",
- "license": "BSD-3-Clause",
- "dependencies": {
- "side-channel": "^1.1.0"
- },
- "engines": {
- "node": ">=0.6"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
"node_modules/quick-lru": {
"version": "5.1.1",
"resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-5.1.1.tgz",
@@ -18875,45 +17469,6 @@
}
}
},
- "node_modules/range-parser": {
- "version": "1.2.1",
- "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz",
- "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==",
- "license": "MIT",
- "engines": {
- "node": ">= 0.6"
- }
- },
- "node_modules/raw-body": {
- "version": "2.5.3",
- "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.3.tgz",
- "integrity": "sha512-s4VSOf6yN0rvbRZGxs8Om5CWj6seneMwK3oDb4lWDH0UPhWcxwOWw5+qk24bxq87szX1ydrwylIOp2uG1ojUpA==",
- "license": "MIT",
- "dependencies": {
- "bytes": "~3.1.2",
- "http-errors": "~2.0.1",
- "iconv-lite": "~0.4.24",
- "unpipe": "~1.0.0"
- },
- "engines": {
- "node": ">= 0.8"
- }
- },
- "node_modules/rc": {
- "version": "1.2.8",
- "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz",
- "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==",
- "license": "(BSD-2-Clause OR MIT OR Apache-2.0)",
- "dependencies": {
- "deep-extend": "^0.6.0",
- "ini": "~1.3.0",
- "minimist": "^1.2.0",
- "strip-json-comments": "~2.0.1"
- },
- "bin": {
- "rc": "cli.js"
- }
- },
"node_modules/rcedit": {
"version": "5.0.2",
"resolved": "https://registry.npmjs.org/rcedit/-/rcedit-5.0.2.tgz",
@@ -18933,6 +17488,7 @@
"resolved": "https://registry.npmjs.org/react/-/react-19.2.5.tgz",
"integrity": "sha512-llUJLzz1zTUBrskt2pwZgLq59AemifIftw4aB7JxOqf1HY2FDaGDxgwpAPVzHU1kdWabH7FauP4i1oEeer2WCA==",
"license": "MIT",
+ "peer": true,
"engines": {
"node": ">=0.10.0"
}
@@ -19005,6 +17561,7 @@
"resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.2.5.tgz",
"integrity": "sha512-J5bAZz+DXMMwW/wV3xzKke59Af6CHY7G4uYLN1OvBcKEsWOs4pQExj86BBKamxl/Ik5bx9whOrvBlSDfWzgSag==",
"license": "MIT",
+ "peer": true,
"dependencies": {
"scheduler": "^0.27.0"
},
@@ -19034,8 +17591,7 @@
"resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz",
"integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==",
"dev": true,
- "license": "MIT",
- "peer": true
+ "license": "MIT"
},
"node_modules/react-refresh": {
"version": "0.18.0",
@@ -19216,6 +17772,7 @@
"resolved": "https://registry.npmjs.org/react-use-measure/-/react-use-measure-2.1.7.tgz",
"integrity": "sha512-KrvcAo13I/60HpwGO5jpW7E9DfusKyLPLvuHlUyP5zqnmAPhNc6qTRjUQrdTADl0lpPpDVU2/Gg51UlOGHXbdg==",
"license": "MIT",
+ "optional": true,
"peerDependencies": {
"react": ">=16.13",
"react-dom": ">=16.13"
@@ -19280,20 +17837,6 @@
"dev": true,
"license": "MIT"
},
- "node_modules/readable-stream": {
- "version": "3.6.2",
- "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz",
- "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==",
- "license": "MIT",
- "dependencies": {
- "inherits": "^2.0.3",
- "string_decoder": "^1.1.1",
- "util-deprecate": "^1.0.1"
- },
- "engines": {
- "node": ">= 6"
- }
- },
"node_modules/redux": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/redux/-/redux-5.0.1.tgz",
@@ -19621,7 +18164,6 @@
"deprecated": "Rimraf versions prior to v4 are no longer supported",
"dev": true,
"license": "ISC",
- "peer": true,
"dependencies": {
"glob": "^7.1.3"
},
@@ -19634,8 +18176,7 @@
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
"integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
"dev": true,
- "license": "MIT",
- "peer": true
+ "license": "MIT"
},
"node_modules/rimraf/node_modules/brace-expansion": {
"version": "1.1.14",
@@ -19643,7 +18184,6 @@
"integrity": "sha512-MWPGfDxnyzKU7rNOW9SP/c50vi3xrmrua/+6hfPbCS2ABNWfx24vPidzvC7krjU/RTo235sV776ymlsMtGKj8g==",
"dev": true,
"license": "MIT",
- "peer": true,
"dependencies": {
"balanced-match": "^1.0.0",
"concat-map": "0.0.1"
@@ -19656,7 +18196,6 @@
"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",
- "peer": true,
"dependencies": {
"fs.realpath": "^1.0.0",
"inflight": "^1.0.4",
@@ -19678,7 +18217,6 @@
"integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==",
"dev": true,
"license": "ISC",
- "peer": true,
"dependencies": {
"brace-expansion": "^1.1.7"
},
@@ -19844,26 +18382,6 @@
"url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/safe-buffer": {
- "version": "5.2.1",
- "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
- "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==",
- "funding": [
- {
- "type": "github",
- "url": "https://github.com/sponsors/feross"
- },
- {
- "type": "patreon",
- "url": "https://www.patreon.com/feross"
- },
- {
- "type": "consulting",
- "url": "https://feross.org/support"
- }
- ],
- "license": "MIT"
- },
"node_modules/safe-push-apply": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/safe-push-apply/-/safe-push-apply-1.0.0.tgz",
@@ -19943,6 +18461,7 @@
"version": "1.6.0",
"resolved": "https://registry.npmjs.org/sax/-/sax-1.6.0.tgz",
"integrity": "sha512-6R3J5M4AcbtLUdZmRv2SygeVaM7IhrLXu9BmnOGmmACak8fiUtOsYNWUS4uK7upbmHIBbLBeFeI//477BKLBzA==",
+ "dev": true,
"license": "BlueOak-1.0.0",
"engines": {
"node": ">=11.0.0"
@@ -19987,6 +18506,7 @@
"version": "7.7.4",
"resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz",
"integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==",
+ "dev": true,
"license": "ISC",
"bin": {
"semver": "bin/semver.js"
@@ -20003,36 +18523,6 @@
"license": "MIT",
"optional": true
},
- "node_modules/send": {
- "version": "0.19.2",
- "resolved": "https://registry.npmjs.org/send/-/send-0.19.2.tgz",
- "integrity": "sha512-VMbMxbDeehAxpOtWJXlcUS5E8iXh6QmN+BkRX1GARS3wRaXEEgzCcB10gTQazO42tpNIya8xIyNx8fll1OFPrg==",
- "license": "MIT",
- "dependencies": {
- "debug": "2.6.9",
- "depd": "2.0.0",
- "destroy": "1.2.0",
- "encodeurl": "~2.0.0",
- "escape-html": "~1.0.3",
- "etag": "~1.8.1",
- "fresh": "~0.5.2",
- "http-errors": "~2.0.1",
- "mime": "1.6.0",
- "ms": "2.1.3",
- "on-finished": "~2.4.1",
- "range-parser": "~1.2.1",
- "statuses": "~2.0.2"
- },
- "engines": {
- "node": ">= 0.8.0"
- }
- },
- "node_modules/send/node_modules/ms": {
- "version": "2.1.3",
- "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
- "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
- "license": "MIT"
- },
"node_modules/serialize-error": {
"version": "7.0.1",
"resolved": "https://registry.npmjs.org/serialize-error/-/serialize-error-7.0.1.tgz",
@@ -20050,21 +18540,6 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
- "node_modules/serve-static": {
- "version": "1.16.3",
- "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.3.tgz",
- "integrity": "sha512-x0RTqQel6g5SY7Lg6ZreMmsOzncHFU7nhnRWkKgWuMTu5NN0DR5oruckMqRvacAN9d5w6ARnRBXl9xhDCgfMeA==",
- "license": "MIT",
- "dependencies": {
- "encodeurl": "~2.0.0",
- "escape-html": "~1.0.3",
- "parseurl": "~1.3.3",
- "send": "~0.19.1"
- },
- "engines": {
- "node": ">= 0.8.0"
- }
- },
"node_modules/set-cookie-parser": {
"version": "2.7.2",
"resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-2.7.2.tgz",
@@ -20135,48 +18610,6 @@
"node": ">=0.10.0"
}
},
- "node_modules/setprototypeof": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz",
- "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==",
- "license": "ISC"
- },
- "node_modules/shallow-clone": {
- "version": "0.1.2",
- "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-0.1.2.tgz",
- "integrity": "sha512-J1zdXCky5GmNnuauESROVu31MQSnLoYvlyEn6j2Ztk6Q5EHFIhxkMhYcv6vuDzl2XEzoRr856QwzMgWM/TmZgw==",
- "license": "MIT",
- "dependencies": {
- "is-extendable": "^0.1.1",
- "kind-of": "^2.0.1",
- "lazy-cache": "^0.2.3",
- "mixin-object": "^2.0.1"
- },
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/shallow-clone/node_modules/kind-of": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-2.0.1.tgz",
- "integrity": "sha512-0u8i1NZ/mg0b+W3MGGw5I7+6Eib2nx72S/QvXa0hYjEkjTknYmEYQJwGu3mLC0BrhtJjtQafTkyRUQ75Kx0LVg==",
- "license": "MIT",
- "dependencies": {
- "is-buffer": "^1.0.2"
- },
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/shallow-clone/node_modules/lazy-cache": {
- "version": "0.2.7",
- "resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-0.2.7.tgz",
- "integrity": "sha512-gkX52wvU/R8DVMMt78ATVPFMJqfW8FPz1GZ1sVHBVQHmu/WvhIWE4cE1GBzhJNFicDeYhnwp6Rl35BcAIM3YOQ==",
- "license": "MIT",
- "engines": {
- "node": ">=0.10.0"
- }
- },
"node_modules/shebang-command": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
@@ -20236,6 +18669,7 @@
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz",
"integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==",
+ "dev": true,
"license": "MIT",
"dependencies": {
"es-errors": "^1.3.0",
@@ -20255,6 +18689,7 @@
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.1.tgz",
"integrity": "sha512-mjn/0bi/oUURjc5Xl7IaWi/OJJJumuoJFQJfDDyO46+hBWsfaVM65TBHq2eoZBhzl9EchxOijpkbRC8SVBQU0w==",
+ "dev": true,
"license": "MIT",
"dependencies": {
"es-errors": "^1.3.0",
@@ -20271,6 +18706,7 @@
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz",
"integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==",
+ "dev": true,
"license": "MIT",
"dependencies": {
"call-bound": "^1.0.2",
@@ -20289,6 +18725,7 @@
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz",
"integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==",
+ "dev": true,
"license": "MIT",
"dependencies": {
"call-bound": "^1.0.2",
@@ -20318,51 +18755,6 @@
"dev": true,
"license": "ISC"
},
- "node_modules/simple-concat": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz",
- "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==",
- "funding": [
- {
- "type": "github",
- "url": "https://github.com/sponsors/feross"
- },
- {
- "type": "patreon",
- "url": "https://www.patreon.com/feross"
- },
- {
- "type": "consulting",
- "url": "https://feross.org/support"
- }
- ],
- "license": "MIT"
- },
- "node_modules/simple-get": {
- "version": "4.0.1",
- "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-4.0.1.tgz",
- "integrity": "sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==",
- "funding": [
- {
- "type": "github",
- "url": "https://github.com/sponsors/feross"
- },
- {
- "type": "patreon",
- "url": "https://www.patreon.com/feross"
- },
- {
- "type": "consulting",
- "url": "https://feross.org/support"
- }
- ],
- "license": "MIT",
- "dependencies": {
- "decompress-response": "^6.0.0",
- "once": "^1.3.1",
- "simple-concat": "^1.0.0"
- }
- },
"node_modules/simple-update-notifier": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/simple-update-notifier/-/simple-update-notifier-2.0.0.tgz",
@@ -20506,15 +18898,6 @@
"node": ">= 6"
}
},
- "node_modules/statuses": {
- "version": "2.0.2",
- "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz",
- "integrity": "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==",
- "license": "MIT",
- "engines": {
- "node": ">= 0.8"
- }
- },
"node_modules/std-env": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/std-env/-/std-env-4.1.0.tgz",
@@ -20563,15 +18946,6 @@
"react-dom": "^18.0.0 || ^19.0.0"
}
},
- "node_modules/string_decoder": {
- "version": "1.3.0",
- "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz",
- "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==",
- "license": "MIT",
- "dependencies": {
- "safe-buffer": "~5.2.0"
- }
- },
"node_modules/string-width": {
"version": "4.2.3",
"resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
@@ -20712,15 +19086,6 @@
"node": ">=8"
}
},
- "node_modules/strip-json-comments": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz",
- "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==",
- "license": "MIT",
- "engines": {
- "node": ">=0.10.0"
- }
- },
"node_modules/style-to-js": {
"version": "1.1.21",
"resolved": "https://registry.npmjs.org/style-to-js/-/style-to-js-1.1.21.tgz",
@@ -20817,6 +19182,7 @@
"resolved": "https://registry.npmjs.org/suspend-react/-/suspend-react-0.1.3.tgz",
"integrity": "sha512-aqldKgX9aZqpoDp3e8/BZ8Dm7x1pJl+qI3ZKxDN0i/IQTWUwBx/ManmlVJ3wowqbno6c2bmiIfs+Um6LbsjJyQ==",
"license": "MIT",
+ "optional": true,
"peerDependencies": {
"react": ">=17.0"
}
@@ -20842,7 +19208,8 @@
"version": "4.2.4",
"resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.2.4.tgz",
"integrity": "sha512-HhKppgO81FQof5m6TEnuBWCZGgfRAWbaeOaGT00KOy/Pf/j6oUihdvBpA7ltCeAvZpFhW3j0PTclkxsd4IXYDA==",
- "license": "MIT"
+ "license": "MIT",
+ "peer": true
},
"node_modules/tapable": {
"version": "2.3.3",
@@ -20874,34 +19241,6 @@
"node": ">=18"
}
},
- "node_modules/tar-fs": {
- "version": "2.1.4",
- "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.4.tgz",
- "integrity": "sha512-mDAjwmZdh7LTT6pNleZ05Yt65HC3E+NiQzl672vQG38jIrehtJk/J3mNwIg+vShQPcLF/LV7CMnDW6vjj6sfYQ==",
- "license": "MIT",
- "dependencies": {
- "chownr": "^1.1.1",
- "mkdirp-classic": "^0.5.2",
- "pump": "^3.0.0",
- "tar-stream": "^2.1.4"
- }
- },
- "node_modules/tar-stream": {
- "version": "2.2.0",
- "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz",
- "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==",
- "license": "MIT",
- "dependencies": {
- "bl": "^4.0.3",
- "end-of-stream": "^1.4.1",
- "fs-constants": "^1.0.0",
- "inherits": "^2.0.3",
- "readable-stream": "^3.1.1"
- },
- "engines": {
- "node": ">=6"
- }
- },
"node_modules/tar/node_modules/chownr": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/chownr/-/chownr-3.0.0.tgz",
@@ -20922,22 +19261,12 @@
"node": ">=18"
}
},
- "node_modules/tdigest": {
- "version": "0.1.2",
- "resolved": "https://registry.npmjs.org/tdigest/-/tdigest-0.1.2.tgz",
- "integrity": "sha512-+G0LLgjjo9BZX2MfdvPfH+MKLCrxlXSYec5DaPYP1fe6Iyhf0/fSmJ0bFiZ1F8BT6cGXl2LpltQptzjXKWEkKA==",
- "license": "MIT",
- "dependencies": {
- "bintrees": "1.0.2"
- }
- },
"node_modules/temp": {
"version": "0.9.4",
"resolved": "https://registry.npmjs.org/temp/-/temp-0.9.4.tgz",
"integrity": "sha512-yYrrsWnrXMcdsnu/7YMYAofM1ktpL5By7vZhf15CrXijWWrEYZks5AXBudalfSWJLlnen/QUJUB5aoB0kqZUGA==",
"dev": true,
"license": "MIT",
- "peer": true,
"dependencies": {
"mkdirp": "^0.5.1",
"rimraf": "~2.6.2"
@@ -20957,12 +19286,6 @@
"fs-extra": "^10.0.0"
}
},
- "node_modules/three": {
- "version": "0.180.0",
- "resolved": "https://registry.npmjs.org/three/-/three-0.180.0.tgz",
- "integrity": "sha512-o+qycAMZrh+TsE01GqWUxUIKR1AL0S8pq7zDkYOQw8GqfX8b8VoCKYUoHbhiX5j+7hr8XsuHDVU6+gkQJQKg9w==",
- "license": "MIT"
- },
"node_modules/tiny-async-pool": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/tiny-async-pool/-/tiny-async-pool-1.3.0.tgz",
@@ -20983,15 +19306,6 @@
"semver": "bin/semver"
}
},
- "node_modules/tiny-lru": {
- "version": "13.0.0",
- "resolved": "https://registry.npmjs.org/tiny-lru/-/tiny-lru-13.0.0.tgz",
- "integrity": "sha512-xDHxKKS1FdF0Tv2P+QT7IeSEg74K/8cEDzbv3Tv6UyHHUgBOjOiQiBp818MGj66dhurQus/IBcoAbwIKtSGc6Q==",
- "license": "BSD-3-Clause",
- "engines": {
- "node": ">=14"
- }
- },
"node_modules/tinybench": {
"version": "2.9.0",
"resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.9.0.tgz",
@@ -21074,15 +19388,6 @@
"tmp": "^0.2.0"
}
},
- "node_modules/toidentifier": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz",
- "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==",
- "license": "MIT",
- "engines": {
- "node": ">=0.6"
- }
- },
"node_modules/tough-cookie": {
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-6.0.1.tgz",
@@ -21177,18 +19482,6 @@
"integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==",
"license": "0BSD"
},
- "node_modules/tunnel-agent": {
- "version": "0.6.0",
- "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz",
- "integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==",
- "license": "Apache-2.0",
- "dependencies": {
- "safe-buffer": "^5.0.1"
- },
- "engines": {
- "node": "*"
- }
- },
"node_modules/tw-animate-css": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/tw-animate-css/-/tw-animate-css-1.4.0.tgz",
@@ -21234,19 +19527,6 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
- "node_modules/type-is": {
- "version": "1.6.18",
- "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz",
- "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==",
- "license": "MIT",
- "dependencies": {
- "media-typer": "0.3.0",
- "mime-types": "~2.1.24"
- },
- "engines": {
- "node": ">= 0.6"
- }
- },
"node_modules/typed-array-buffer": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.3.tgz",
@@ -21331,6 +19611,7 @@
"integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==",
"dev": true,
"license": "Apache-2.0",
+ "peer": true,
"bin": {
"tsc": "bin/tsc",
"tsserver": "bin/tsserver"
@@ -21339,81 +19620,6 @@
"node": ">=14.17"
}
},
- "node_modules/typescript-eslint": {
- "version": "8.59.1",
- "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.59.1.tgz",
- "integrity": "sha512-xqDcFVBmlrltH64lklOVp1wYxgJr6LVdg3NamBgH2OOQDLFdTKfIZXF5PfghrnXQKXZGTQs8tr1vL7fJvq8CTQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@typescript-eslint/eslint-plugin": "8.59.1",
- "@typescript-eslint/parser": "8.59.1",
- "@typescript-eslint/typescript-estree": "8.59.1",
- "@typescript-eslint/utils": "8.59.1"
- },
- "engines": {
- "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/typescript-eslint"
- },
- "peerDependencies": {
- "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0",
- "typescript": ">=4.8.4 <6.1.0"
- }
- },
- "node_modules/ua-is-frozen": {
- "version": "0.1.2",
- "resolved": "https://registry.npmjs.org/ua-is-frozen/-/ua-is-frozen-0.1.2.tgz",
- "integrity": "sha512-RwKDW2p3iyWn4UbaxpP2+VxwqXh0jpvdxsYpZ5j/MLLiQOfbsV5shpgQiw93+KMYQPcteeMQ289MaAFzs3G9pw==",
- "funding": [
- {
- "type": "github",
- "url": "https://github.com/sponsors/faisalman"
- },
- {
- "type": "opencollective",
- "url": "https://opencollective.com/ua-parser-js"
- },
- {
- "type": "paypal",
- "url": "https://paypal.me/faisalman"
- }
- ],
- "license": "MIT"
- },
- "node_modules/ua-parser-js": {
- "version": "2.0.9",
- "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-2.0.9.tgz",
- "integrity": "sha512-OsqGhxyo/wGdLSXMSJxuMGN6H4gDnKz6Fb3IBm4bxZFMnyy0sdf6MN96Ie8tC6z/btdO+Bsy8guxlvLdwT076w==",
- "funding": [
- {
- "type": "opencollective",
- "url": "https://opencollective.com/ua-parser-js"
- },
- {
- "type": "paypal",
- "url": "https://paypal.me/faisalman"
- },
- {
- "type": "github",
- "url": "https://github.com/sponsors/faisalman"
- }
- ],
- "license": "AGPL-3.0-or-later",
- "dependencies": {
- "detect-europe-js": "^0.1.2",
- "is-standalone-pwa": "^0.1.1",
- "ua-is-frozen": "^0.1.2"
- },
- "bin": {
- "ua-parser-js": "script/cli.js"
- },
- "engines": {
- "node": "*"
- }
- },
"node_modules/ufo": {
"version": "1.6.4",
"resolved": "https://registry.npmjs.org/ufo/-/ufo-1.6.4.tgz",
@@ -21588,24 +19794,17 @@
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz",
"integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==",
+ "dev": true,
"license": "MIT",
"engines": {
"node": ">= 10.0.0"
}
},
- "node_modules/unpipe": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",
- "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==",
- "license": "MIT",
- "engines": {
- "node": ">= 0.8"
- }
- },
"node_modules/update-browserslist-db": {
"version": "1.2.3",
"resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.2.3.tgz",
"integrity": "sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==",
+ "dev": true,
"funding": [
{
"type": "opencollective",
@@ -21744,6 +19943,7 @@
"resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.6.0.tgz",
"integrity": "sha512-Pp6GSwGP/NrPIrxVFAIkOQeyw8lFenOHijQWkUTrDvrF4ALqylP2C/KCkeS9dpUM3KvYRQhna5vt7IL95+ZQ9w==",
"license": "MIT",
+ "peer": true,
"peerDependencies": {
"react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0"
}
@@ -21761,15 +19961,6 @@
"integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==",
"license": "MIT"
},
- "node_modules/utils-merge": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz",
- "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==",
- "license": "MIT",
- "engines": {
- "node": ">= 0.4.0"
- }
- },
"node_modules/uuid": {
"version": "11.1.1",
"resolved": "https://registry.npmjs.org/uuid/-/uuid-11.1.1.tgz",
@@ -21789,24 +19980,6 @@
"integrity": "sha512-LdabyT4OffkyXFCe9UT+uMkxNBs5rcTVuZClvxQr08D5TUgo1OFKkoT65qYRCsiKBl/usHjpXvP4hHMzzDRj3A==",
"license": "MIT"
},
- "node_modules/vali-date": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/vali-date/-/vali-date-1.0.0.tgz",
- "integrity": "sha512-sgECfZthyaCKW10N0fm27cg8HYTFK5qMWgypqkXMQ4Wbl/zZKx7xZICgcoxIIE+WFAP/MBL2EFwC/YvLxw3Zeg==",
- "license": "MIT",
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/vary": {
- "version": "1.1.2",
- "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz",
- "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==",
- "license": "MIT",
- "engines": {
- "node": ">= 0.8"
- }
- },
"node_modules/verror": {
"version": "1.10.1",
"resolved": "https://registry.npmjs.org/verror/-/verror-1.10.1.tgz",
@@ -21870,6 +20043,7 @@
"resolved": "https://registry.npmjs.org/vite/-/vite-7.3.2.tgz",
"integrity": "sha512-Bby3NOsna2jsjfLVOHKes8sGwgl4TT0E6vvpYgnAYDIF/tie7MRaFthmKuHx1NSXjiTueXH3do80FMQgvEktRg==",
"license": "MIT",
+ "peer": true,
"dependencies": {
"esbuild": "^0.27.0",
"fdir": "^6.5.0",
@@ -22350,6 +20524,7 @@
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
"integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==",
+ "dev": true,
"license": "ISC"
},
"node_modules/xml-name-validator": {
@@ -22362,24 +20537,13 @@
"node": ">=18"
}
},
- "node_modules/xml2js": {
- "version": "0.6.2",
- "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.6.2.tgz",
- "integrity": "sha512-T4rieHaC1EXcES0Kxxj4JWgaUQHDk+qwHcYOCFHfiwKz7tOVPLq7Hjq9dM1WCMhylqMEfP7hMcOIChvotiZegA==",
- "license": "MIT",
- "dependencies": {
- "sax": ">=0.6.0",
- "xmlbuilder": "~11.0.0"
- },
- "engines": {
- "node": ">=4.0.0"
- }
- },
"node_modules/xmlbuilder": {
"version": "11.0.1",
"resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-11.0.1.tgz",
"integrity": "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==",
+ "dev": true,
"license": "MIT",
+ "optional": true,
"engines": {
"node": ">=4.0"
}
@@ -22466,6 +20630,7 @@
"resolved": "https://registry.npmjs.org/zod/-/zod-4.4.2.tgz",
"integrity": "sha512-IynmDyxsEsb9RKzO3J9+4SxXnl2FTFSzNBaKKaMV6tsSk0rw9gYw9gs+JFCq/qk2LCZ78KDwyj+Z289TijSkUw==",
"license": "MIT",
+ "peer": true,
"funding": {
"url": "https://github.com/sponsors/colinhacks"
}
@@ -22488,6 +20653,7 @@
"resolved": "https://registry.npmjs.org/zustand/-/zustand-5.0.12.tgz",
"integrity": "sha512-i77ae3aZq4dhMlRhJVCYgMLKuSiZAaUPAct2AksxQ+gOtimhGMdXljRT21P5BNpeT4kXlLIckvkPM029OljD7g==",
"license": "MIT",
+ "peer": true,
"engines": {
"node": ">=12.20.0"
},
diff --git a/tools/file_operations.py b/tools/file_operations.py
index fd9f793ec3f..b9c5bcc2840 100644
--- a/tools/file_operations.py
+++ b/tools/file_operations.py
@@ -353,6 +353,16 @@ class FileOperations(ABC):
"""Delete a file. Returns WriteResult with .error set on failure."""
...
+ def delete_path(self, path: str, recursive: bool = False) -> WriteResult:
+ """Cross-platform delete that handles files and (with recursive=True)
+ directory trees. Default implementation delegates to ``delete_file``
+ for the non-recursive case; backends with native recursive support
+ should override.
+ """
+ if recursive:
+ return WriteResult(error="Recursive delete not implemented for this backend")
+ return self.delete_file(path)
+
@abstractmethod
def move_file(self, src: str, dst: str) -> WriteResult:
"""Move/rename a file from src to dst. Returns WriteResult with .error set on failure."""
@@ -1065,13 +1075,64 @@ class ShellFileOperations(FileOperations):
)
def delete_file(self, path: str) -> WriteResult:
- """Delete a file via rm."""
+ """Delete a single file.
+
+ Cross-platform: runs via ``python -c`` against the terminal env's
+ Python so it works on Windows shells (``cmd.exe``/PowerShell) that
+ don't ship ``rm``. Directories are rejected here — use
+ ``delete_path(recursive=True)`` for trees.
+ """
+ return self._python_delete(path, recursive=False)
+
+ def delete_path(self, path: str, recursive: bool = False) -> WriteResult:
+ """Cross-platform delete that handles files and (with recursive=True)
+ directory trees. Always preferred over emitting ``rm -rf`` /
+ ``Remove-Item -Recurse`` directly so the same tool call works on
+ every backend (local / docker / ssh / Windows).
+ """
+ return self._python_delete(path, recursive=recursive)
+
+ def _python_delete(self, path: str, recursive: bool) -> WriteResult:
path = self._expand_path(path)
if _is_write_denied(path):
return WriteResult(error=f"Delete denied: {path} is a protected path")
- result = self._exec(f"rm -f {self._escape_shell_arg(path)}")
+
+ # We can't shell out to ``rm`` here — it doesn't exist on Windows
+ # ``cmd.exe`` or PowerShell, so this code path is what's left when
+ # the backend's terminal is a Windows shell. Path is baked into the
+ # snippet via ``repr()`` so quoting is correct on every shell.
+ snippet = (
+ "import shutil, pathlib, sys\n"
+ f"p = pathlib.Path({path!r})\n"
+ f"recursive = {bool(recursive)!r}\n"
+ "try:\n"
+ " if p.is_dir() and not p.is_symlink():\n"
+ " if recursive:\n"
+ " shutil.rmtree(p)\n"
+ " else:\n"
+ " print('is a directory: ' + str(p), file=sys.stderr); sys.exit(2)\n"
+ " else:\n"
+ # NOTE: avoid ``unlink(missing_ok=True)`` — that kwarg lands in
+ # Python 3.8 and the remote interpreter (docker/ssh) may still
+ # be 3.7 on older distros. The FileNotFoundError handler below
+ # covers the same case and works back to 3.4.
+ " p.unlink()\n"
+ "except FileNotFoundError:\n"
+ " pass\n"
+ "except Exception as exc:\n"
+ " print(str(exc), file=sys.stderr); sys.exit(1)\n"
+ )
+
+ result = self._exec(f"python3 -c {self._escape_shell_arg(snippet)}")
+
+ # Fall back to ``python`` (Windows / older systems where there's no
+ # ``python3`` symlink but a ``python`` binary is on PATH).
+ if result.exit_code != 0 and "python3" in (result.stdout or ""):
+ result = self._exec(f"python -c {self._escape_shell_arg(snippet)}")
+
if result.exit_code != 0:
- return WriteResult(error=f"Failed to delete {path}: {result.stdout}")
+ return WriteResult(error=f"Failed to delete {path}: {(result.stdout or '').strip() or 'unknown error'}")
+
return WriteResult()
def move_file(self, src: str, dst: str) -> WriteResult: